diff --git a/android/gradle.properties b/android/gradle.properties
index 781b120d..db3db310 100644
--- a/android/gradle.properties
+++ b/android/gradle.properties
@@ -3,4 +3,4 @@ Airship_minSdkVersion=21
Airship_targetSdkVersion=34
Airship_compileSdkVersion=34
Airship_ndkversion=26.1.10909125
-Airship_airshipProxyVersion=8.3.0
+Airship_airshipProxyVersion=9.1.3
diff --git a/android/src/main/java/com/urbanairship/reactnative/AirshipExtender.kt b/android/src/main/java/com/urbanairship/reactnative/AirshipExtender.kt
index 7e5cc367..0ee2ed2f 100644
--- a/android/src/main/java/com/urbanairship/reactnative/AirshipExtender.kt
+++ b/android/src/main/java/com/urbanairship/reactnative/AirshipExtender.kt
@@ -10,6 +10,7 @@ import com.urbanairship.UAirship
* Register the extender fully qualified class name in the manifest under the key
* `com.urbanairship.reactnative.AIRSHIP_EXTENDER`.
*/
-interface AirshipExtender {
+@Deprecated("Use com.urbanairship.android.framework.proxy.AirshipPluginExtender instead and register it under the manifest key `com.urbanairship.plugin.extender`")
+interface AirshipExtender {
fun onAirshipReady(context: Context, airship: UAirship)
}
\ No newline at end of file
diff --git a/android/src/main/java/com/urbanairship/reactnative/AirshipModule.kt b/android/src/main/java/com/urbanairship/reactnative/AirshipModule.kt
index e333864f..5a55566f 100644
--- a/android/src/main/java/com/urbanairship/reactnative/AirshipModule.kt
+++ b/android/src/main/java/com/urbanairship/reactnative/AirshipModule.kt
@@ -8,10 +8,13 @@ import com.urbanairship.PendingResult
import com.urbanairship.actions.ActionResult
import com.urbanairship.actions.ActionValue
import com.urbanairship.android.framework.proxy.EventType
+import com.urbanairship.android.framework.proxy.NotificationConfig
import com.urbanairship.android.framework.proxy.ProxyLogger
import com.urbanairship.android.framework.proxy.events.EventEmitter
import com.urbanairship.android.framework.proxy.proxies.AirshipProxy
+import com.urbanairship.android.framework.proxy.proxies.EnableUserNotificationsArgs
import com.urbanairship.android.framework.proxy.proxies.FeatureFlagProxy
+import com.urbanairship.android.framework.proxy.proxies.LiveUpdateRequest
import com.urbanairship.android.framework.proxy.proxies.SuspendingPredicate
import com.urbanairship.json.JsonMap
import com.urbanairship.json.JsonSerializable
@@ -238,9 +241,12 @@ class AirshipModule internal constructor(val context: ReactApplicationContext) :
}
@ReactMethod
- override fun pushEnableUserNotifications(promise: Promise) {
+ override fun pushEnableUserNotifications(options: ReadableMap?, promise: Promise) {
promise.resolveSuspending(scope) {
- proxy.push.enableUserPushNotifications()
+ val args = options?.let {
+ EnableUserNotificationsArgs.fromJson(Utils.convertMap(it).toJsonValue())
+ }
+ proxy.push.enableUserPushNotifications(args = args)
}
}
@@ -693,6 +699,12 @@ class AirshipModule internal constructor(val context: ReactApplicationContext) :
}
}
+ override fun liveActivityListAll(promise: Promise) {
+ promise.resolveResult {
+ throw IllegalStateException("Not supported on Android")
+ }
+ }
+
override fun liveActivityList(request: ReadableMap?, promise: Promise) {
promise.resolveResult {
throw IllegalStateException("Not supported on Android")
@@ -717,6 +729,48 @@ class AirshipModule internal constructor(val context: ReactApplicationContext) :
}
}
+ override fun liveUpdateListAll(promise: Promise) {
+ promise.resolveSuspending(scope) {
+ proxy.liveUpdateManager.listAll().let {
+ JsonValue.wrapOpt(it)
+ }
+ }
+ }
+
+ override fun liveUpdateList(request: ReadableMap?, promise: Promise) {
+ promise.resolveSuspending(scope) {
+ proxy.liveUpdateManager.list(
+ LiveUpdateRequest.List.fromJson(Utils.convertMap(requireNotNull(request)).toJsonValue())
+ ).let {
+ JsonValue.wrapOpt(it)
+ }
+ }
+ }
+
+ override fun liveUpdateCreate(request: ReadableMap?, promise: Promise) {
+ promise.resolveSuspending(scope) {
+ proxy.liveUpdateManager.create(
+ LiveUpdateRequest.Create.fromJson(Utils.convertMap(requireNotNull(request)).toJsonValue())
+ )
+ }
+ }
+
+ override fun liveUpdateUpdate(request: ReadableMap?, promise: Promise) {
+ promise.resolveSuspending(scope) {
+ proxy.liveUpdateManager.update(
+ LiveUpdateRequest.Update.fromJson(Utils.convertMap(requireNotNull(request)).toJsonValue())
+ )
+ }
+ }
+
+ override fun liveUpdateEnd(request: ReadableMap?, promise: Promise) {
+ promise.resolveSuspending(scope) {
+ proxy.liveUpdateManager.end(
+ LiveUpdateRequest.End.fromJson(Utils.convertMap(requireNotNull(request)).toJsonValue())
+ )
+ }
+ }
+
private fun notifyPending() {
if (context.hasActiveReactInstance()) {
val appEventEmitter = context.getJSModule(RCTNativeAppEventEmitter::class.java)
diff --git a/android/src/main/java/com/urbanairship/reactnative/ReactAutopilot.kt b/android/src/main/java/com/urbanairship/reactnative/ReactAutopilot.kt
index 194ac959..a6868e3a 100644
--- a/android/src/main/java/com/urbanairship/reactnative/ReactAutopilot.kt
+++ b/android/src/main/java/com/urbanairship/reactnative/ReactAutopilot.kt
@@ -17,7 +17,9 @@ import com.urbanairship.embedded.AirshipEmbeddedInfo
import com.urbanairship.embedded.AirshipEmbeddedObserver
import com.urbanairship.json.JsonMap
import com.urbanairship.json.jsonMapOf
-import kotlinx.coroutines.MainScope
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.launch
@@ -26,14 +28,12 @@ import kotlinx.coroutines.launch
*/
class ReactAutopilot : BaseAutopilot() {
- override fun onAirshipReady(airship: UAirship) {
- super.onAirshipReady(airship)
+ private val scope = CoroutineScope(Dispatchers.Main + SupervisorJob())
+ override fun onReady(context: Context, airship: UAirship) {
ProxyLogger.info("Airship React Native version: %s, SDK version: %s", BuildConfig.AIRSHIP_MODULE_VERSION, UAirship.getVersion())
- val context = UAirship.getApplicationContext()
-
- MainScope().launch {
+ scope.launch {
EventEmitter.shared().pendingEventListener
.filter { !it.type.isForeground() }
.collect {
@@ -41,18 +41,19 @@ class ReactAutopilot : BaseAutopilot() {
}
}
- MainScope().launch {
+ scope.launch {
AirshipEmbeddedObserver(filter = { true }).embeddedViewInfoFlow.collect {
EventEmitter.shared().addEvent(PendingEmbeddedUpdated(it))
}
}
- // Set our custom notification providerr
+ // Set our custom notification provider
val notificationProvider = ReactNotificationProvider(context, airship.airshipConfigOptions)
airship.pushManager.notificationProvider = notificationProvider
airship.analytics.registerSDKExtension(Extension.REACT_NATIVE, BuildConfig.AIRSHIP_MODULE_VERSION)
+ // Legacy extender
val extender = createExtender(context)
extender?.onAirshipReady(context, airship)
}
@@ -61,6 +62,7 @@ class ReactAutopilot : BaseAutopilot() {
DataMigrator(context).migrateData(proxyStore)
}
+ @Suppress("deprecation")
private fun createExtender(context: Context): AirshipExtender? {
val ai: ApplicationInfo
try {
@@ -77,7 +79,7 @@ class ReactAutopilot : BaseAutopilot() {
try {
val extenderClass = Class.forName(classname)
- return extenderClass.newInstance() as AirshipExtender
+ return extenderClass.getDeclaredConstructor().newInstance() as AirshipExtender
} catch (e: Exception) {
ProxyLogger.error(e, "Unable to create extender: $classname")
}
diff --git a/android/src/oldarch/java/com/urbanairship/reactnative/AirshipSpec.kt b/android/src/oldarch/java/com/urbanairship/reactnative/AirshipSpec.kt
index cd8d914d..27a0fd42 100644
--- a/android/src/oldarch/java/com/urbanairship/reactnative/AirshipSpec.kt
+++ b/android/src/oldarch/java/com/urbanairship/reactnative/AirshipSpec.kt
@@ -98,7 +98,7 @@ abstract class AirshipSpec internal constructor(context: ReactApplicationContext
@ReactMethod
@com.facebook.proguard.annotations.DoNotStrip
- abstract fun pushEnableUserNotifications(promise: Promise)
+ abstract fun pushEnableUserNotifications(options: ReadableMap?, promise: Promise)
@ReactMethod
@com.facebook.proguard.annotations.DoNotStrip
@@ -405,6 +405,10 @@ abstract class AirshipSpec internal constructor(context: ReactApplicationContext
@com.facebook.proguard.annotations.DoNotStrip
abstract fun featureFlagManagerTrackInteraction(flag: ReadableMap?, promise: Promise)
+ @ReactMethod
+ @com.facebook.proguard.annotations.DoNotStrip
+ abstract fun liveActivityListAll(promise: Promise)
+
@ReactMethod
@com.facebook.proguard.annotations.DoNotStrip
abstract fun liveActivityList(request: ReadableMap?, promise: Promise)
@@ -420,6 +424,24 @@ abstract class AirshipSpec internal constructor(context: ReactApplicationContext
@ReactMethod
@com.facebook.proguard.annotations.DoNotStrip
abstract fun liveActivityEnd(request: ReadableMap?, promise: Promise)
-}
+ @ReactMethod
+ @com.facebook.proguard.annotations.DoNotStrip
+ abstract fun liveUpdateListAll(promise: Promise)
+
+ @ReactMethod
+ @com.facebook.proguard.annotations.DoNotStrip
+ abstract fun liveUpdateList(request: ReadableMap?, promise: Promise)
+
+ @ReactMethod
+ @com.facebook.proguard.annotations.DoNotStrip
+ abstract fun liveUpdateCreate(request: ReadableMap?, promise: Promise)
+ @ReactMethod
+ @com.facebook.proguard.annotations.DoNotStrip
+ abstract fun liveUpdateUpdate(request: ReadableMap?, promise: Promise)
+
+ @ReactMethod
+ @com.facebook.proguard.annotations.DoNotStrip
+ abstract fun liveUpdateEnd(request: ReadableMap?, promise: Promise)
+}
diff --git a/example/android/app/src/main/AndroidManifest.xml b/example/android/app/src/main/AndroidManifest.xml
index 4122f36a..0ab88c50 100644
--- a/example/android/app/src/main/AndroidManifest.xml
+++ b/example/android/app/src/main/AndroidManifest.xml
@@ -3,23 +3,28 @@
-
-
-
-
-
-
+ android:roundIcon="@mipmap/ic_launcher_round"
+ android:theme="@style/AppTheme">
+
+
+
+
+
+
+
+
+
diff --git a/example/android/app/src/main/java/com/urbanairship/sample/AirshipExtender.kt b/example/android/app/src/main/java/com/urbanairship/sample/AirshipExtender.kt
new file mode 100644
index 00000000..269ebb57
--- /dev/null
+++ b/example/android/app/src/main/java/com/urbanairship/sample/AirshipExtender.kt
@@ -0,0 +1,69 @@
+package com.urbanairship.sample
+
+import android.app.NotificationChannel
+import android.app.NotificationManager
+import android.app.PendingIntent
+import android.content.Context
+import android.content.Intent
+import android.os.Build
+import androidx.annotation.Keep
+import androidx.core.app.NotificationCompat
+import androidx.core.app.NotificationManagerCompat
+import com.urbanairship.UAirship
+import com.urbanairship.android.framework.proxy.AirshipPluginExtender
+import com.urbanairship.json.requireField
+import com.urbanairship.liveupdate.LiveUpdate
+import com.urbanairship.liveupdate.LiveUpdateEvent
+import com.urbanairship.liveupdate.LiveUpdateManager
+import com.urbanairship.liveupdate.LiveUpdateResult
+import com.urbanairship.liveupdate.SuspendLiveUpdateNotificationHandler
+
+
+@Keep
+public final class AirshipExtender: AirshipPluginExtender {
+ override fun onAirshipReady(context: Context, airship: UAirship) {
+ LiveUpdateManager.shared().register("Example", ExampleLiveUpdateHandler())
+ }
+}
+
+public final class ExampleLiveUpdateHandler: SuspendLiveUpdateNotificationHandler() {
+ override suspend fun onUpdate(
+ context: Context,
+ event: LiveUpdateEvent,
+ update: LiveUpdate
+ ): LiveUpdateResult {
+
+ if (event == LiveUpdateEvent.END) {
+ // Dismiss the live update on END. The default behavior will leave the Live Update
+ // in the notification tray until the dismissal time is reached or the user dismisses it.
+ return LiveUpdateResult.cancel()
+ }
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ val importance = NotificationManager.IMPORTANCE_DEFAULT
+ val channel = NotificationChannel("emoji-example", "Emoji example", importance)
+ channel.description = "Emoji example"
+ NotificationManagerCompat.from(context).createNotificationChannel(channel)
+ }
+
+ val launchIntent = context.packageManager
+ .getLaunchIntentForPackage(context.packageName)
+ ?.addCategory(update.name)
+ ?.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_SINGLE_TOP)
+ ?.setPackage(null)
+
+ val contentIntent = PendingIntent.getActivity(
+ context, 0, launchIntent, PendingIntent.FLAG_IMMUTABLE
+ )
+
+ val notification = NotificationCompat.Builder(context, "emoji-example")
+ .setSmallIcon(R.drawable.ic_notification)
+ .setPriority(NotificationCompat.PRIORITY_MAX)
+ .setCategory(NotificationCompat.CATEGORY_EVENT)
+ .setContentTitle("Example Live Update")
+ .setContentText(update.content.requireField("emoji"))
+ .setContentIntent(contentIntent)
+
+ return LiveUpdateResult.ok(notification)
+ }
+}
\ No newline at end of file
diff --git a/example/android/app/src/main/res/drawable-anydpi-v24/ic_notification.xml b/example/android/app/src/main/res/drawable-anydpi-v24/ic_notification.xml
new file mode 100644
index 00000000..6f92d40c
--- /dev/null
+++ b/example/android/app/src/main/res/drawable-anydpi-v24/ic_notification.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/example/android/app/src/main/res/drawable-hdpi/ic_notification.png b/example/android/app/src/main/res/drawable-hdpi/ic_notification.png
new file mode 100644
index 00000000..8e46a11c
Binary files /dev/null and b/example/android/app/src/main/res/drawable-hdpi/ic_notification.png differ
diff --git a/example/android/app/src/main/res/drawable-mdpi/ic_notification.png b/example/android/app/src/main/res/drawable-mdpi/ic_notification.png
new file mode 100644
index 00000000..32067e0c
Binary files /dev/null and b/example/android/app/src/main/res/drawable-mdpi/ic_notification.png differ
diff --git a/example/android/app/src/main/res/drawable-xhdpi/ic_notification.png b/example/android/app/src/main/res/drawable-xhdpi/ic_notification.png
new file mode 100644
index 00000000..bc21cccd
Binary files /dev/null and b/example/android/app/src/main/res/drawable-xhdpi/ic_notification.png differ
diff --git a/example/android/app/src/main/res/drawable-xxhdpi/ic_notification.png b/example/android/app/src/main/res/drawable-xxhdpi/ic_notification.png
new file mode 100644
index 00000000..a0753ae4
Binary files /dev/null and b/example/android/app/src/main/res/drawable-xxhdpi/ic_notification.png differ
diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock
index 203fd248..aba700cc 100644
--- a/example/ios/Podfile.lock
+++ b/example/ios/Podfile.lock
@@ -17,7 +17,7 @@ PODS:
- Airship/Core
- Airship/PreferenceCenter (18.9.2):
- Airship/Core
- - AirshipFrameworkProxy (8.3.0):
+ - AirshipFrameworkProxy (9.1.3):
- Airship (= 18.9.2)
- AirshipServiceExtension (18.9.2)
- boost (1.83.0)
@@ -908,7 +908,7 @@ PODS:
- glog
- React-debug
- react-native-airship (19.3.2):
- - AirshipFrameworkProxy (= 8.3.0)
+ - AirshipFrameworkProxy (= 9.1.3)
- glog
- RCT-Folly (= 2022.05.16.00)
- React-Core
@@ -1280,7 +1280,7 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS:
Airship: 7f891aa9bb142d02f35aaef5ebdb09c2b5730a6d
- AirshipFrameworkProxy: 48208d21ca1376d9bc111efd31981af84bfcf8f3
+ AirshipFrameworkProxy: 9a983b72a47ce10d8eda32b446ea553ef7bcc8f2
AirshipServiceExtension: 0ed795b521a76f8391e13896fbe1dee6ce9196ca
boost: d3f49c53809116a5d38da093a8aa78bf551aed09
DoubleConversion: fea03f2699887d960129cc54bba7e52542b6f953
@@ -1311,7 +1311,7 @@ SPEC CHECKSUMS:
React-jsinspector: 9ac353eccf6ab54d1e0a33862ba91221d1e88460
React-logger: 0a57b68dd2aec7ff738195f081f0520724b35dab
React-Mapbuffer: 63913773ed7f96b814a2521e13e6d010282096ad
- react-native-airship: c68835c32f7b5a100b25bf5f2ecc6e4fae6ddce4
+ react-native-airship: 6afeeef72fa57a06a716afaca0ababb8adfaee81
react-native-safe-area-context: b97eb6f9e3b7f437806c2ce5983f479f8eb5de4b
React-nativeconfig: d7af5bae6da70fa15ce44f045621cf99ed24087c
React-NativeModulesApple: 0123905d5699853ac68519607555a9a4f5c7b3ac
diff --git a/example/package-lock.json b/example/package-lock.json
index 8e0b163d..67c2988d 100644
--- a/example/package-lock.json
+++ b/example/package-lock.json
@@ -11,7 +11,8 @@
"babel-plugin-module-resolver": "^5.0.0",
"moment": "^2.30.1",
"react": "18.2.0",
- "react-native": "0.73.4"
+ "react-native": "0.73.4",
+ "react-native-uuid": "^2.0.2"
},
"devDependencies": {
"@babel/core": "^7.20.0",
@@ -12184,6 +12185,15 @@
"react-native": "*"
}
},
+ "node_modules/react-native-uuid": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/react-native-uuid/-/react-native-uuid-2.0.2.tgz",
+ "integrity": "sha512-5ypj/hV58P+6VREdjkW0EudSibsH3WdqDERoHKnD9syFWjF+NfRWWrJb2sa3LIwI5zpzMvUiabs+DX40WHpEMw==",
+ "engines": {
+ "node": ">=10.0.0",
+ "npm": ">=6.0.0"
+ }
+ },
"node_modules/react-native-vector-icons": {
"version": "10.0.3",
"resolved": "https://registry.npmjs.org/react-native-vector-icons/-/react-native-vector-icons-10.0.3.tgz",
diff --git a/example/package.json b/example/package.json
index 007c27a1..91027d3f 100644
--- a/example/package.json
+++ b/example/package.json
@@ -12,7 +12,8 @@
"babel-plugin-module-resolver": "^5.0.0",
"moment": "^2.30.1",
"react": "18.2.0",
- "react-native": "0.73.4"
+ "react-native": "0.73.4",
+ "react-native-uuid": "^2.0.2"
},
"devDependencies": {
"@babel/core": "^7.20.0",
diff --git a/example/src/screens/HomeScreen.tsx b/example/src/screens/HomeScreen.tsx
index 835cf737..d0ae546d 100644
--- a/example/src/screens/HomeScreen.tsx
+++ b/example/src/screens/HomeScreen.tsx
@@ -6,6 +6,7 @@
*/
import React, { useState, useEffect, useCallback } from 'react';
+import uuid from 'react-native-uuid';
import {
View,
Text,
@@ -82,49 +83,28 @@ export default function HomeScreen() {
[refreshTags]
);
- const handleNotificationsEnabled = useCallback((enabled: boolean) => {
- Airship.push.setUserNotificationsEnabled(enabled);
- setNotificationsEnabled(enabled);
+ const handleNotificationsEnabled = useCallback(async (enabled: boolean) => {
+ if (enabled) {
+ await Airship.push.enableUserNotifications({
+ fallback: 'systemSettings',
+ });
+ } else {
+ Airship.push.setUserNotificationsEnabled(false);
+ }
}, []);
useEffect(() => {
- // Add takeOff here
-
- Airship.push
- .getNotificationStatus()
- .then((id) => {
- console.log(id);
- })
- .catch((error) => {
- console.error('Error getting notification status:', error);
- });
-
setEmbeddedReady(Airship.inApp.isEmbeddedReady('test'));
- Airship.push.iOS
- .getAuthorizedNotificationSettings()
- .then((id) => {
- console.log(id);
- })
- .catch((error) => {
- console.error('Error getting notification settings:', error);
- });
-
- Airship.push.iOS.getAuthorizedNotificationStatus().then((id) => {
- console.log(id);
- });
-
- Airship.push.getNotificationStatus().then((id) => {
- console.log(id);
- });
-
Airship.channel.getChannelId().then((id) => {
if (id) {
setChannelId(id);
}
});
- Airship.push.isUserNotificationsEnabled().then(setNotificationsEnabled);
+ Airship.push
+ .getNotificationStatus()
+ .then((status) => setNotificationsEnabled(status.isUserOptedIn));
const fetchTags = async () => {
const fetchedTags = await Airship.channel.getTags();
@@ -140,20 +120,32 @@ export default function HomeScreen() {
fetchNamedUser();
- let subscription = Airship.addListener(
+ let channelListener = Airship.addListener(
EventType.ChannelCreated,
(event) => {
setChannelId(event.channelId);
}
);
- Airship.inApp.addEmbeddedReadyListener('test', (isReady) => {
- console.log('Test ' + isReady);
- setEmbeddedReady(isReady);
- });
+ let embeddedListener = Airship.inApp.addEmbeddedReadyListener(
+ 'test',
+ (isReady) => {
+ setEmbeddedReady(isReady);
+ }
+ );
+
+ let optInListener = Airship.addListener(
+ EventType.PushNotificationStatusChangedStatus,
+ (event) => {
+ console.log('Event', event);
+ setNotificationsEnabled(event.status.isUserOptedIn);
+ }
+ );
return () => {
- subscription.remove();
+ channelListener.remove();
+ embeddedListener.remove();
+ optInListener.remove();
};
}, []);
@@ -183,10 +175,20 @@ export default function HomeScreen() {
)}
- {Platform.OS === 'ios' ? (
-
-
{channelId ? (
diff --git a/ios/AirshipReactNative.swift b/ios/AirshipReactNative.swift
index 5c2585c0..cfa74c0d 100644
--- a/ios/AirshipReactNative.swift
+++ b/ios/AirshipReactNative.swift
@@ -98,6 +98,7 @@ public class AirshipReactNative: NSObject {
}
}
+
@MainActor
func onLoad(
launchOptions: [UIApplication.LaunchOptionsKey: Any]?
@@ -243,8 +244,13 @@ public extension AirshipReactNative {
}
@objc
- func pushEnableUserNotifications() async throws -> Bool {
- return try await AirshipProxy.shared.push.enableUserPushNotifications()
+ func pushEnableUserNotifications(options: Any?) async throws -> Bool {
+ let args: EnableUserPushNotificationsArgs? = if let options {
+ try AirshipJSON.wrap(options).decode()
+ } else {
+ nil
+ }
+ return try await AirshipProxy.shared.push.enableUserPushNotifications(args: args)
}
@objc
@@ -599,6 +605,7 @@ public extension AirshipReactNative {
// Live Activity
@objc
public extension AirshipReactNative {
+
@objc
func liveActivityList(options: Any) async throws -> Any {
if #available(iOS 16.1, *) {
@@ -609,6 +616,16 @@ public extension AirshipReactNative {
}
}
+ @objc
+ func liveActivityListAll() async throws -> Any {
+ if #available(iOS 16.1, *) {
+ let result = try await LiveActivityManager.shared.listAll()
+ return try AirshipJSON.wrap(result).unWrap() as Any
+ } else {
+ throw AirshipErrors.error("Not available before 16.1")
+ }
+ }
+
@objc
func liveActivityCreate(options: Any) async throws -> Any {
do {
diff --git a/ios/RTNAirship.mm b/ios/RTNAirship.mm
index 2a89a15e..971f3227 100644
--- a/ios/RTNAirship.mm
+++ b/ios/RTNAirship.mm
@@ -188,10 +188,10 @@ + (BOOL)requiresMainQueueSetup {
}
RCT_REMAP_METHOD(pushEnableUserNotifications,
- pushEnableUserNotifications:(RCTPromiseResolveBlock)resolve
+ pushEnableUserNotifications:(NSDictionary *)options
+ resolve:(RCTPromiseResolveBlock)resolve
reject:(RCTPromiseRejectBlock)reject) {
- [AirshipReactNative.shared pushEnableUserNotificationsWithCompletionHandler:^(BOOL result, NSError *error) {
-
+ [AirshipReactNative.shared pushEnableUserNotificationsWithOptions:options completionHandler:^(BOOL result, NSError *error) {
[self handleResult:@(result)
error:error
resolve:resolve
@@ -770,6 +770,15 @@ + (BOOL)requiresMainQueueSetup {
}];
}
+RCT_REMAP_METHOD(liveActivityListAll,
+ liveActivityListAll:(RCTPromiseResolveBlock)resolve
+ reject:(RCTPromiseRejectBlock)reject) {
+
+ [AirshipReactNative.shared liveActivityListAllWithCompletionHandler:^(id result, NSError * _Nullable error) {
+ [self handleResult:result error:error resolve:resolve reject:reject];
+ }];
+}
+
RCT_REMAP_METHOD(liveActivityList,
liveActivityListRequest:(NSDictionary *)request
liveActivityList:(RCTPromiseResolveBlock)resolve
@@ -814,9 +823,44 @@ + (BOOL)requiresMainQueueSetup {
}];
}
+RCT_REMAP_METHOD(liveUpdateListAll,
+ liveUpdateListAll:(RCTPromiseResolveBlock)resolve
+ reject:(RCTPromiseRejectBlock)reject) {
+ reject(@"AIRSHIP_ERROR", @"Not supported on iOS", nil);
+}
+RCT_REMAP_METHOD(liveUpdateList,
+ liveUpdateListRequest:(NSDictionary *)request
+ liveUpdateList:(RCTPromiseResolveBlock)resolve
+ reject:(RCTPromiseRejectBlock)reject) {
+
+ reject(@"AIRSHIP_ERROR", @"Not supported on iOS", nil);
+}
+RCT_REMAP_METHOD(liveUpdateCreate,
+ liveUpdateCreateRequest:(NSDictionary *)request
+ liveUpdateCreate:(RCTPromiseResolveBlock)resolve
+ reject:(RCTPromiseRejectBlock)reject) {
+
+ reject(@"AIRSHIP_ERROR", @"Not supported on iOS", nil);
+}
+
+RCT_REMAP_METHOD(liveUpdateUpdate,
+ liveUpdateUpdateRequest:(NSDictionary *)request
+ liveUpdateUpdate:(RCTPromiseResolveBlock)resolve
+ reject:(RCTPromiseRejectBlock)reject) {
+
+ reject(@"AIRSHIP_ERROR", @"Not supported on iOS", nil);
+}
+
+RCT_REMAP_METHOD(liveUpdateEnd,
+ liveUpdateEndRequest:(NSDictionary *)request
+ liveUpdateEnd:(RCTPromiseResolveBlock)resolve
+ reject:(RCTPromiseRejectBlock)reject) {
+
+ reject(@"AIRSHIP_ERROR", @"Not supported on iOS", nil);
+}
-(void)handleResult:(id)result
diff --git a/react-native-airship.podspec b/react-native-airship.podspec
index 8ab89686..9b4d0c8a 100644
--- a/react-native-airship.podspec
+++ b/react-native-airship.podspec
@@ -22,6 +22,6 @@ Pod::Spec.new do |s|
s.dependency "React-Core"
end
- s.dependency "AirshipFrameworkProxy", "8.3.0"
+ s.dependency "AirshipFrameworkProxy", "9.1.3"
end
diff --git a/src/AirshipLiveActivityManager.ts b/src/AirshipLiveActivityManager.ts
index 6d019794..459e3864 100644
--- a/src/AirshipLiveActivityManager.ts
+++ b/src/AirshipLiveActivityManager.ts
@@ -21,12 +21,21 @@ export class AirshipLiveActivityManager {
return this.module.liveActivityList(request);
}
+ /**
+ * Lists all Live Activities.
+ * @param request The request options.
+ * @returns A promise with the result.
+ */
+ public listAll(): Promise {
+ return this.module.liveActivityListAll();
+ }
+
/**
* Creates a Live Activity.
* @param request The request options.
* @returns A promise with the result.
*/
- public create(request: LiveActivityCreateRequest): Promise {
+ public create(request: LiveActivityCreateRequest): Promise {
return this.module.liveActivityCreate(request);
}
@@ -35,7 +44,7 @@ export class AirshipLiveActivityManager {
* @param request The request options.
* @returns A promise with the result.
*/
- public update(request: LiveActivityUpdateRequest): Promise {
+ public update(request: LiveActivityUpdateRequest): Promise {
return this.module.liveActivityUpdate(request);
}
@@ -44,7 +53,7 @@ export class AirshipLiveActivityManager {
* @param request The request options.
* @returns A promise with the result.
*/
- public end(request: LiveActivityEndRequest): Promise {
+ public end(request: LiveActivityEndRequest): Promise {
return this.module.liveActivityEnd(request);
}
}
diff --git a/src/AirshipLiveUpdateManager.ts b/src/AirshipLiveUpdateManager.ts
new file mode 100644
index 00000000..67a095b5
--- /dev/null
+++ b/src/AirshipLiveUpdateManager.ts
@@ -0,0 +1,59 @@
+import {
+ LiveUpdate,
+ LiveUpdateListRequest,
+ LiveUpdateCreateRequest,
+ LiveUpdateUpdateRequest,
+ LiveUpdateEndRequest,
+} from './types';
+
+/**
+ * Live Update manager.
+ */
+export class AirshipLiveUpdateManager {
+ constructor(private readonly module: any) {}
+
+ /**
+ * Lists any Live Updates for the request.
+ * @param request The request options.
+ * @returns A promise with the result.
+ */
+ public list(request: LiveUpdateListRequest): Promise {
+ return this.module.liveUpdateList(request);
+ }
+
+ /**
+ * Lists all Live Updates.
+ * @returns A promise with the result.
+ */
+ public listAll(): Promise {
+ return this.module.liveUpdateListAll();
+ }
+
+ /**
+ * Creates a Live Update.
+ * @param request The request options.
+ * @returns A promise with the result.
+ */
+ public create(request: LiveUpdateCreateRequest): Promise {
+ return this.module.liveUpdateCreate(request);
+ }
+
+ /**
+ * Updates a Live Update.
+ * @param request The request options.
+ * @returns A promise with the result.
+ */
+ public update(request: LiveUpdateUpdateRequest): Promise {
+ return this.module.liveUpdateUpdate(request);
+ }
+
+ /**
+ * Ends a Live Update.
+ * @param request The request options.
+ * @returns A promise with the result.
+ */
+ public end(request: LiveUpdateEndRequest): Promise {
+ return this.module.liveUpdateEnd(request);
+ }
+}
+
diff --git a/src/AirshipPush.ts b/src/AirshipPush.ts
index 64df4892..a2dc9b61 100644
--- a/src/AirshipPush.ts
+++ b/src/AirshipPush.ts
@@ -1,5 +1,5 @@
import { NativeEventEmitter, Platform } from 'react-native';
-import { Android, iOS, PushNotificationStatus, PushPayload } from './types';
+import { Android, iOS, PushNotificationStatus, PushPayload, PromptPermissionFallback } from './types';
/**
* Airship Push.
@@ -45,10 +45,13 @@ export class AirshipPush {
/**
* Enables user notifications.
+ * @param options Optional options.
* @returns A promise with the permission result.
*/
- public enableUserNotifications(): Promise {
- return this.module.pushEnableUserNotifications();
+ public enableUserNotifications(options?: {
+ fallback?: PromptPermissionFallback
+ }): Promise {
+ return this.module.pushEnableUserNotifications(options);
}
/**
diff --git a/src/AirshipRoot.ts b/src/AirshipRoot.ts
index d81ab208..c9f4bd9c 100644
--- a/src/AirshipRoot.ts
+++ b/src/AirshipRoot.ts
@@ -13,6 +13,7 @@ import { AirshipFeatureFlagManager } from './AirshipFeatureFlagManager';
import { AirshipConfig, EventTypeMap, EventType } from './types';
import { Subscription, UAEventEmitter } from './UAEventEmitter';
import { AirshipLiveActivityManager } from './AirshipLiveActivityManager';
+import { AirshipLiveUpdateManager } from './AirshipLiveUpdateManager';
/**
* Airship
@@ -35,6 +36,11 @@ export class AirshipRoot {
*/
public readonly iOS: AirshipRootIOS;
+ /**
+ * iOS only accessors
+ */
+ public readonly android: AirshipRootAndroid;
+
private readonly eventEmitter: UAEventEmitter;
constructor(private readonly module: any) {
@@ -52,6 +58,7 @@ export class AirshipRoot {
this.push = new AirshipPush(module);
this.featureFlagManager = new AirshipFeatureFlagManager(module);
this.iOS = new AirshipRootIOS(module);
+ this.android = new AirshipRootAndroid(module);
}
/**
@@ -119,3 +126,11 @@ export class AirshipRootIOS {
this.liveActivityManager = new AirshipLiveActivityManager(module);
}
}
+
+export class AirshipRootAndroid {
+ public readonly liveUpdateManager: AirshipLiveUpdateManager;
+
+ constructor(module: any) {
+ this.liveUpdateManager = new AirshipLiveUpdateManager(module);
+ }
+}
diff --git a/src/NativeRTNAirship.ts b/src/NativeRTNAirship.ts
index e52128d4..9ee88914 100644
--- a/src/NativeRTNAirship.ts
+++ b/src/NativeRTNAirship.ts
@@ -28,7 +28,7 @@ export interface Spec extends TurboModule {
// Push
pushSetUserNotificationsEnabled(enabled: boolean): Promise;
pushIsUserNotificationsEnabled(): Promise;
- pushEnableUserNotifications(): Promise;
+ pushEnableUserNotifications(options?: Object): Promise;
pushGetNotificationStatus(): Promise