From 7cc69e7d4d5642067d795a6966c1578aec96edaa Mon Sep 17 00:00:00 2001 From: Ulrich GIBERNE Date: Fri, 5 Apr 2024 16:56:45 -0400 Subject: [PATCH] fix Airship Actions running --- .../urbanairship/reactnative/AirshipModule.kt | 4 +-- .../urbanairship/reactnative/AirshipSpec.kt | 3 +- example/src/App.tsx | 29 ---------------- ios/AirshipReactNative.swift | 6 ++-- ios/RTNAirship.mm | 5 ++- src/Action.ts | 34 +++++++++++++++++++ src/AirshipActions.ts | 9 +++-- src/AirshipAnalytics.ts | 10 ++---- src/CustomEvent.ts | 18 ++++++++++ src/NativeRTNAirship.ts | 3 +- src/index.tsx | 1 + 11 files changed, 69 insertions(+), 53 deletions(-) create mode 100644 src/Action.ts diff --git a/android/src/main/java/com/urbanairship/reactnative/AirshipModule.kt b/android/src/main/java/com/urbanairship/reactnative/AirshipModule.kt index 16d6878f..e99ee1ed 100644 --- a/android/src/main/java/com/urbanairship/reactnative/AirshipModule.kt +++ b/android/src/main/java/com/urbanairship/reactnative/AirshipModule.kt @@ -455,9 +455,9 @@ class AirshipModule internal constructor(val context: ReactApplicationContext) : } @ReactMethod - override fun actionRun(name: String?, value: Dynamic?, promise: Promise) { + override fun actionRun(action: ReadableMap, promise: Promise) { promise.resolveDeferred { callback -> - proxy.actions.runAction(requireNotNull(name), Utils.convertDynamic(value)) + proxy.actions.runAction(requireNotNull(action.getString("_name")), Utils.convertDynamic(action.getDynamic("_value"))) .addResultCallback { actionResult -> if (actionResult != null && actionResult.status == ActionResult.STATUS_COMPLETED) { callback(actionResult.value, null) diff --git a/android/src/oldarch/java/com/urbanairship/reactnative/AirshipSpec.kt b/android/src/oldarch/java/com/urbanairship/reactnative/AirshipSpec.kt index 960c766d..5c4bfadd 100644 --- a/android/src/oldarch/java/com/urbanairship/reactnative/AirshipSpec.kt +++ b/android/src/oldarch/java/com/urbanairship/reactnative/AirshipSpec.kt @@ -240,8 +240,7 @@ abstract class AirshipSpec internal constructor(context: ReactApplicationContext @ReactMethod @com.facebook.proguard.annotations.DoNotStrip abstract fun actionRun( - name: String?, - value: Dynamic?, + action: ReadableMap, promise: Promise ) diff --git a/example/src/App.tsx b/example/src/App.tsx index c3cce7d2..d31cf057 100644 --- a/example/src/App.tsx +++ b/example/src/App.tsx @@ -8,40 +8,11 @@ import MessageCenterScreen from './screens/MessageCenterScreen'; import MessageScreen from './screens/MessageScreen'; import PreferenceCenterScreen from './screens/PreferenceCenterScreen'; import Airship, { EventType } from '@ua/react-native-airship'; -import { CustomEvent } from '@ua/react-native-airship'; import MaterialIcons from 'react-native-vector-icons/MaterialIcons'; const Tab = createBottomTabNavigator(); const MessageCenterStack = createStackNavigator(); -Airship.takeOff({ - default: { - appKey: "VWDwdOFjRTKLRxCeXTVP6g", - appSecret: "5Ifi5rYgTm2QHey9JkP0WA", - logLevel: "verbose" - }, - site: "us", // use "eu" for EU cloud projects - urlAllowList: ["*"], - android: { - notificationConfig: { - icon: "ic_notification", - accentColor: "#00ff00" - } - } -}); - -var customEvent = new CustomEvent("event_name", 123.12); -customEvent.addProperty("my_custom_property", "some custom value"); -customEvent.addProperty("is_neat", true); -customEvent.addProperty("any_json", { - "foo": "bar" -}); -Airship.analytics.addCustomEvent(customEvent); - - -var url: string = "ulrich://some-deep-link" -Airship.actions.run("deep_link_action", url); - Airship.addListener(EventType.NotificationResponse, (event) => { console.log('NotificationResponse:', JSON.stringify(event)); }); diff --git a/ios/AirshipReactNative.swift b/ios/AirshipReactNative.swift index 453bd7cd..2fd6494c 100644 --- a/ios/AirshipReactNative.swift +++ b/ios/AirshipReactNative.swift @@ -328,10 +328,10 @@ public extension AirshipReactNative { // Actions @objc public extension AirshipReactNative { - func actionsRun(actionName: String, actionValue: Any?) async throws-> Any? { + func actionsRun(action: [String: Any]) async throws-> Any? { return try await AirshipProxy.shared.action.runAction( - actionName, - value: try AirshipJSON.wrap(actionValue) + action["_name"] as! String, + value: action["_value"] is NSNull ? nil : try AirshipJSON.wrap(action["_value"]) ) } } diff --git a/ios/RTNAirship.mm b/ios/RTNAirship.mm index 2d4d7a2a..f45e0cf4 100644 --- a/ios/RTNAirship.mm +++ b/ios/RTNAirship.mm @@ -336,11 +336,10 @@ + (BOOL)requiresMainQueueSetup { } RCT_REMAP_METHOD(actionRun, - actionRun:(NSString *)name value:(NSDictionary *)value + actionRun:(NSDictionary *)action resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) { - [AirshipReactNative.shared actionsRunWithActionName:name - actionValue:value + [AirshipReactNative.shared actionsRunWithAction:action completionHandler:^(id result , NSError *error) { diff --git a/src/Action.ts b/src/Action.ts new file mode 100644 index 00000000..bec53369 --- /dev/null +++ b/src/Action.ts @@ -0,0 +1,34 @@ +/* Copyright Airship and Contributors */ + +'use strict'; + +import { JsonValue } from './types'; + +/** + * Airship Action Object. + * This is used to encapsulate the Action name and the Action value. + */ +export class Action { + _name: string; + _value?: JsonValue; + + /** + * Airship Action constructor. + * + * @param name The action name. + * @param value The action value. + */ + constructor(name: string, value?: JsonValue) { + this._name = name; + this._value = value; + } + + /** + * Sets the action value. + * + * @param value The action value. + */ + setValue(value?: JsonValue) { + this._value = value; + } +} \ No newline at end of file diff --git a/src/AirshipActions.ts b/src/AirshipActions.ts index 6004373e..9b9af7b3 100644 --- a/src/AirshipActions.ts +++ b/src/AirshipActions.ts @@ -1,4 +1,5 @@ import { JsonValue } from './types'; +import { Action } from './Action'; /** * Airship actions. @@ -9,15 +10,13 @@ export class AirshipActions { /** * Runs an Airship action. * - * @param name The name of the action. - * @param value The action's value. + * @param action The Airship Action. * @return A promise that returns the action result if the action * successfully runs, or the Error if the action was unable to be run. */ public run( - actionName: string, - actionValue?: JsonValue + action: Action ): Promise { - return this.module.actionRun(actionName, actionValue); + return this.module.actionRun(action); } } diff --git a/src/AirshipAnalytics.ts b/src/AirshipAnalytics.ts index ee8e0c76..a9f0d994 100644 --- a/src/AirshipAnalytics.ts +++ b/src/AirshipAnalytics.ts @@ -1,3 +1,4 @@ +import { Action } from "./Action"; import { CustomEvent } from "./CustomEvent"; /** @@ -33,15 +34,10 @@ export class AirshipAnalytics { * custom event is rejected. */ public addCustomEvent(event: CustomEvent): Promise { - const actionArg = { - event_name: event._name, - event_value: event._value, - transaction_id: event._transactionId, - properties: event._properties - } + let action = new Action("add_custom_event_action", event.toJsonValue()) return new Promise((resolve, reject) => { - this.module.actionRun("add_custom_event_action", actionArg).then(() => { + this.module.actionRun(action).then(() => { resolve(null) }, (error: Error) => { reject(error) diff --git a/src/CustomEvent.ts b/src/CustomEvent.ts index 59321386..dae94dbb 100644 --- a/src/CustomEvent.ts +++ b/src/CustomEvent.ts @@ -48,4 +48,22 @@ export class CustomEvent { addProperty(name: string, value: JsonValue) { this._properties[name] = value; } + + /** + * Converts a CustomEvent into a JsonValue. + * + * @returns A JsonValue. + */ + toJsonValue(): JsonValue { + let jsonObject: JsonObject = {}; + jsonObject.event_name = this._name; + if (this._value) { + jsonObject.event_value = this._value; + } + jsonObject.properties = this._properties; + if (this._transactionId) { + jsonObject.transaction_id = this._transactionId; + } + return jsonObject; + } } diff --git a/src/NativeRTNAirship.ts b/src/NativeRTNAirship.ts index 2807d9ba..45e36a40 100644 --- a/src/NativeRTNAirship.ts +++ b/src/NativeRTNAirship.ts @@ -1,6 +1,5 @@ import type { TurboModule } from 'react-native'; import { TurboModuleRegistry } from 'react-native'; -import { JsonValue } from './types'; export interface Spec extends TurboModule { // Airship @@ -69,7 +68,7 @@ export interface Spec extends TurboModule { analyticsAssociateIdentifier(key: string, identifier?: string): Promise; // Action - actionRun(name: string, value?: JsonValue): Promise; + actionRun(action: Object): Promise; // Privacy Manager privacyManagerSetEnabledFeatures(features: string[]): Promise; diff --git a/src/index.tsx b/src/index.tsx index 4c9483be..1bf77bd3 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -19,6 +19,7 @@ export { SubscriptionListEditor } from './SubscriptionListEditor'; export { TagGroupEditor } from './TagGroupEditor'; export { ScopedSubscriptionListEditor } from './ScopedSubscriptionListEditor'; export { AttributeEditor } from './AttributeEditor'; +export { Action } from './Action'; export * from './types'; export * from './MessageView';