zixflow-reactnative 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +451 -0
- package/android/build.gradle +155 -0
- package/android/cio-core.gradle +12 -0
- package/android/consumer-rules.pro +3 -0
- package/android/gradle.properties +5 -0
- package/android/src/main/AndroidManifest.xml +19 -0
- package/android/src/main/java/io/customer/reactnative/sdk/CustomerIOReactNativePackage.kt +85 -0
- package/android/src/main/java/io/customer/reactnative/sdk/NativeCustomerIOModule.kt +201 -0
- package/android/src/main/java/io/customer/reactnative/sdk/constant/Keys.kt +20 -0
- package/android/src/main/java/io/customer/reactnative/sdk/extension/MapExtensions.kt +92 -0
- package/android/src/main/java/io/customer/reactnative/sdk/extension/ReactExtensions.kt +11 -0
- package/android/src/main/java/io/customer/reactnative/sdk/extension/StringExtensions.kt +3 -0
- package/android/src/main/java/io/customer/reactnative/sdk/extension/ViewExtensions.kt +34 -0
- package/android/src/main/java/io/customer/reactnative/sdk/location/NativeLocationModule.kt +66 -0
- package/android/src/main/java/io/customer/reactnative/sdk/logging/NativeCustomerIOLoggingModule.kt +90 -0
- package/android/src/main/java/io/customer/reactnative/sdk/messaginginapp/InlineInAppMessageViewManager.kt +56 -0
- package/android/src/main/java/io/customer/reactnative/sdk/messaginginapp/NativeMessagingInAppModule.kt +215 -0
- package/android/src/main/java/io/customer/reactnative/sdk/messaginginapp/NotificationInboxExtensions.kt +23 -0
- package/android/src/main/java/io/customer/reactnative/sdk/messaginginapp/ReactInAppEventListener.kt +77 -0
- package/android/src/main/java/io/customer/reactnative/sdk/messaginginapp/ReactInAppPlatformDelegate.kt +37 -0
- package/android/src/main/java/io/customer/reactnative/sdk/messaginginapp/ReactInlineInAppMessageView.kt +44 -0
- package/android/src/main/java/io/customer/reactnative/sdk/messaginginapp/ReactNotificationInboxChangeListener.kt +47 -0
- package/android/src/main/java/io/customer/reactnative/sdk/messagingpush/NativeMessagingPushModule.kt +283 -0
- package/android/src/main/java/io/customer/reactnative/sdk/messagingpush/PermissionStatus.kt +9 -0
- package/android/src/main/java/io/customer/reactnative/sdk/messagingpush/PushMessagingExtensions.kt +58 -0
- package/android/src/main/java/io/customer/reactnative/sdk/util/Preconditions.kt +35 -0
- package/android/src/main/res/values/customer_io_config.xml +13 -0
- package/customerio-reactnative.podspec +60 -0
- package/ios/CustomerioReactnative.xcodeproj/project.pbxproj +285 -0
- package/ios/CustomerioReactnative.xcodeproj/project.xcworkspace/contents.xcworkspacedata +4 -0
- package/ios/CustomerioReactnative.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
- package/ios/wrappers/CustomerioReactnative-Bridging-Header.h +2 -0
- package/ios/wrappers/NativeCustomerIO.mm +100 -0
- package/ios/wrappers/NativeCustomerIO.swift +162 -0
- package/ios/wrappers/inapp/InboxMessage+Conversion.swift +22 -0
- package/ios/wrappers/inapp/NativeMessagingInApp.mm +122 -0
- package/ios/wrappers/inapp/NativeMessagingInApp.swift +214 -0
- package/ios/wrappers/inapp/ReactInAppEventListener.swift +74 -0
- package/ios/wrappers/inapp/inline/InlineInAppMessageStateEvent.swift +23 -0
- package/ios/wrappers/inapp/inline/RCTInlineMessageNative.h +18 -0
- package/ios/wrappers/inapp/inline/RCTInlineMessageNative.mm +168 -0
- package/ios/wrappers/inapp/inline/ReactInlineMessageView.h +42 -0
- package/ios/wrappers/inapp/inline/ReactInlineMessageView.swift +124 -0
- package/ios/wrappers/location/NativeLocation.mm +52 -0
- package/ios/wrappers/location/NativeLocation.swift +37 -0
- package/ios/wrappers/logging/NativeCustomerIOLogging.mm +81 -0
- package/ios/wrappers/logging/NativeCustomerIOLogging.swift +62 -0
- package/ios/wrappers/push/NativeMessagingPush.mm +87 -0
- package/ios/wrappers/push/NativeMessagingPush.swift +119 -0
- package/ios/wrappers/utils/CioConfigUtils.swift +63 -0
- package/ios/wrappers/utils/CioConstants.swift +25 -0
- package/ios/wrappers/utils/Preconditions.swift +20 -0
- package/ios/wrappers/utils/RCTCustomerIOUtils.h +19 -0
- package/lib/commonjs/cio-params.js +2 -0
- package/lib/commonjs/cio-params.js.map +1 -0
- package/lib/commonjs/components/InlineInAppMessageView.js +146 -0
- package/lib/commonjs/components/InlineInAppMessageView.js.map +1 -0
- package/lib/commonjs/components/index.js +14 -0
- package/lib/commonjs/components/index.js.map +1 -0
- package/lib/commonjs/customerio-cdp.js +163 -0
- package/lib/commonjs/customerio-cdp.js.map +1 -0
- package/lib/commonjs/customerio-inapp.js +107 -0
- package/lib/commonjs/customerio-inapp.js.map +1 -0
- package/lib/commonjs/customerio-location.js +53 -0
- package/lib/commonjs/customerio-location.js.map +1 -0
- package/lib/commonjs/customerio-push.js +115 -0
- package/lib/commonjs/customerio-push.js.map +1 -0
- package/lib/commonjs/index.js +17 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/native-logger-listener.js +84 -0
- package/lib/commonjs/native-logger-listener.js.map +1 -0
- package/lib/commonjs/notification-inbox.js +132 -0
- package/lib/commonjs/notification-inbox.js.map +1 -0
- package/lib/commonjs/package.json +1 -0
- package/lib/commonjs/postInstall.js +13 -0
- package/lib/commonjs/postInstall.js.map +1 -0
- package/lib/commonjs/specs/components/InlineMessageNativeComponent.ts +59 -0
- package/lib/commonjs/specs/modules/NativeCustomerIO.js +40 -0
- package/lib/commonjs/specs/modules/NativeCustomerIO.js.map +1 -0
- package/lib/commonjs/specs/modules/NativeCustomerIOLocation.js +15 -0
- package/lib/commonjs/specs/modules/NativeCustomerIOLocation.js.map +1 -0
- package/lib/commonjs/specs/modules/NativeCustomerIOLogging.js +19 -0
- package/lib/commonjs/specs/modules/NativeCustomerIOLogging.js.map +1 -0
- package/lib/commonjs/specs/modules/NativeCustomerIOMessagingInApp.js +16 -0
- package/lib/commonjs/specs/modules/NativeCustomerIOMessagingInApp.js.map +1 -0
- package/lib/commonjs/specs/modules/NativeCustomerIOMessagingPush.js +15 -0
- package/lib/commonjs/specs/modules/NativeCustomerIOMessagingPush.js.map +1 -0
- package/lib/commonjs/types/data-pipelines.js +123 -0
- package/lib/commonjs/types/data-pipelines.js.map +1 -0
- package/lib/commonjs/types/in-app.js +43 -0
- package/lib/commonjs/types/in-app.js.map +1 -0
- package/lib/commonjs/types/index.js +39 -0
- package/lib/commonjs/types/index.js.map +1 -0
- package/lib/commonjs/types/internal.js +2 -0
- package/lib/commonjs/types/internal.js.map +1 -0
- package/lib/commonjs/types/push.js +49 -0
- package/lib/commonjs/types/push.js.map +1 -0
- package/lib/commonjs/utils/native-bridge.js +31 -0
- package/lib/commonjs/utils/native-bridge.js.map +1 -0
- package/lib/commonjs/utils/param-validation.js +136 -0
- package/lib/commonjs/utils/param-validation.js.map +1 -0
- package/lib/commonjs/zixflow.js +71 -0
- package/lib/commonjs/zixflow.js.map +1 -0
- package/lib/module/cio-params.js +2 -0
- package/lib/module/cio-params.js.map +1 -0
- package/lib/module/components/InlineInAppMessageView.js +141 -0
- package/lib/module/components/InlineInAppMessageView.js.map +1 -0
- package/lib/module/components/index.js +6 -0
- package/lib/module/components/index.js.map +1 -0
- package/lib/module/customerio-cdp.js +157 -0
- package/lib/module/customerio-cdp.js.map +1 -0
- package/lib/module/customerio-inapp.js +92 -0
- package/lib/module/customerio-inapp.js.map +1 -0
- package/lib/module/customerio-location.js +48 -0
- package/lib/module/customerio-location.js.map +1 -0
- package/lib/module/customerio-push.js +111 -0
- package/lib/module/customerio-push.js.map +1 -0
- package/lib/module/index.js +12 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/native-logger-listener.js +79 -0
- package/lib/module/native-logger-listener.js.map +1 -0
- package/lib/module/notification-inbox.js +127 -0
- package/lib/module/notification-inbox.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/postInstall.js +13 -0
- package/lib/module/postInstall.js.map +1 -0
- package/lib/module/specs/components/InlineMessageNativeComponent.ts +59 -0
- package/lib/module/specs/modules/NativeCustomerIO.js +41 -0
- package/lib/module/specs/modules/NativeCustomerIO.js.map +1 -0
- package/lib/module/specs/modules/NativeCustomerIOLocation.js +13 -0
- package/lib/module/specs/modules/NativeCustomerIOLocation.js.map +1 -0
- package/lib/module/specs/modules/NativeCustomerIOLogging.js +18 -0
- package/lib/module/specs/modules/NativeCustomerIOLogging.js.map +1 -0
- package/lib/module/specs/modules/NativeCustomerIOMessagingInApp.js +15 -0
- package/lib/module/specs/modules/NativeCustomerIOMessagingInApp.js.map +1 -0
- package/lib/module/specs/modules/NativeCustomerIOMessagingPush.js +13 -0
- package/lib/module/specs/modules/NativeCustomerIOMessagingPush.js.map +1 -0
- package/lib/module/types/data-pipelines.js +126 -0
- package/lib/module/types/data-pipelines.js.map +1 -0
- package/lib/module/types/in-app.js +42 -0
- package/lib/module/types/in-app.js.map +1 -0
- package/lib/module/types/index.js +6 -0
- package/lib/module/types/index.js.map +1 -0
- package/lib/module/types/internal.js +2 -0
- package/lib/module/types/internal.js.map +1 -0
- package/lib/module/types/push.js +47 -0
- package/lib/module/types/push.js.map +1 -0
- package/lib/module/utils/native-bridge.js +25 -0
- package/lib/module/utils/native-bridge.js.map +1 -0
- package/lib/module/utils/param-validation.js +132 -0
- package/lib/module/utils/param-validation.js.map +1 -0
- package/lib/module/zixflow.js +23 -0
- package/lib/module/zixflow.js.map +1 -0
- package/lib/typescript/commonjs/cio-params.d.ts +5 -0
- package/lib/typescript/commonjs/cio-params.d.ts.map +1 -0
- package/lib/typescript/commonjs/components/InlineInAppMessageView.d.ts +41 -0
- package/lib/typescript/commonjs/components/InlineInAppMessageView.d.ts.map +1 -0
- package/lib/typescript/commonjs/components/index.d.ts +3 -0
- package/lib/typescript/commonjs/components/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/customerio-cdp.d.ts +40 -0
- package/lib/typescript/commonjs/customerio-cdp.d.ts.map +1 -0
- package/lib/typescript/commonjs/customerio-inapp.d.ts +48 -0
- package/lib/typescript/commonjs/customerio-inapp.d.ts.map +1 -0
- package/lib/typescript/commonjs/customerio-location.d.ts +31 -0
- package/lib/typescript/commonjs/customerio-location.d.ts.map +1 -0
- package/lib/typescript/commonjs/customerio-push.d.ts +56 -0
- package/lib/typescript/commonjs/customerio-push.d.ts.map +1 -0
- package/lib/typescript/commonjs/index.d.ts +8 -0
- package/lib/typescript/commonjs/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/native-logger-listener.d.ts +8 -0
- package/lib/typescript/commonjs/native-logger-listener.d.ts.map +1 -0
- package/lib/typescript/commonjs/notification-inbox.d.ts +57 -0
- package/lib/typescript/commonjs/notification-inbox.d.ts.map +1 -0
- package/lib/typescript/commonjs/package.json +1 -0
- package/lib/typescript/commonjs/postInstall.d.ts +2 -0
- package/lib/typescript/commonjs/postInstall.d.ts.map +1 -0
- package/lib/typescript/commonjs/specs/components/InlineMessageNativeComponent.d.ts +40 -0
- package/lib/typescript/commonjs/specs/components/InlineMessageNativeComponent.d.ts.map +1 -0
- package/lib/typescript/commonjs/specs/modules/NativeCustomerIO.d.ts +46 -0
- package/lib/typescript/commonjs/specs/modules/NativeCustomerIO.d.ts.map +1 -0
- package/lib/typescript/commonjs/specs/modules/NativeCustomerIOLocation.d.ts +14 -0
- package/lib/typescript/commonjs/specs/modules/NativeCustomerIOLocation.d.ts.map +1 -0
- package/lib/typescript/commonjs/specs/modules/NativeCustomerIOLogging.d.ts +18 -0
- package/lib/typescript/commonjs/specs/modules/NativeCustomerIOLogging.d.ts.map +1 -0
- package/lib/typescript/commonjs/specs/modules/NativeCustomerIOMessagingInApp.d.ts +23 -0
- package/lib/typescript/commonjs/specs/modules/NativeCustomerIOMessagingInApp.d.ts.map +1 -0
- package/lib/typescript/commonjs/specs/modules/NativeCustomerIOMessagingPush.d.ts +20 -0
- package/lib/typescript/commonjs/specs/modules/NativeCustomerIOMessagingPush.d.ts.map +1 -0
- package/lib/typescript/commonjs/types/data-pipelines.d.ts +143 -0
- package/lib/typescript/commonjs/types/data-pipelines.d.ts.map +1 -0
- package/lib/typescript/commonjs/types/in-app.d.ts +67 -0
- package/lib/typescript/commonjs/types/in-app.d.ts.map +1 -0
- package/lib/typescript/commonjs/types/index.d.ts +4 -0
- package/lib/typescript/commonjs/types/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/types/internal.d.ts +20 -0
- package/lib/typescript/commonjs/types/internal.d.ts.map +1 -0
- package/lib/typescript/commonjs/types/push.d.ts +49 -0
- package/lib/typescript/commonjs/types/push.d.ts.map +1 -0
- package/lib/typescript/commonjs/utils/native-bridge.d.ts +9 -0
- package/lib/typescript/commonjs/utils/native-bridge.d.ts.map +1 -0
- package/lib/typescript/commonjs/utils/param-validation.d.ts +44 -0
- package/lib/typescript/commonjs/utils/param-validation.d.ts.map +1 -0
- package/lib/typescript/commonjs/zixflow.d.ts +14 -0
- package/lib/typescript/commonjs/zixflow.d.ts.map +1 -0
- package/lib/typescript/module/cio-params.d.ts +5 -0
- package/lib/typescript/module/cio-params.d.ts.map +1 -0
- package/lib/typescript/module/components/InlineInAppMessageView.d.ts +41 -0
- package/lib/typescript/module/components/InlineInAppMessageView.d.ts.map +1 -0
- package/lib/typescript/module/components/index.d.ts +3 -0
- package/lib/typescript/module/components/index.d.ts.map +1 -0
- package/lib/typescript/module/customerio-cdp.d.ts +40 -0
- package/lib/typescript/module/customerio-cdp.d.ts.map +1 -0
- package/lib/typescript/module/customerio-inapp.d.ts +48 -0
- package/lib/typescript/module/customerio-inapp.d.ts.map +1 -0
- package/lib/typescript/module/customerio-location.d.ts +31 -0
- package/lib/typescript/module/customerio-location.d.ts.map +1 -0
- package/lib/typescript/module/customerio-push.d.ts +56 -0
- package/lib/typescript/module/customerio-push.d.ts.map +1 -0
- package/lib/typescript/module/index.d.ts +8 -0
- package/lib/typescript/module/index.d.ts.map +1 -0
- package/lib/typescript/module/native-logger-listener.d.ts +8 -0
- package/lib/typescript/module/native-logger-listener.d.ts.map +1 -0
- package/lib/typescript/module/notification-inbox.d.ts +57 -0
- package/lib/typescript/module/notification-inbox.d.ts.map +1 -0
- package/lib/typescript/module/package.json +1 -0
- package/lib/typescript/module/postInstall.d.ts +2 -0
- package/lib/typescript/module/postInstall.d.ts.map +1 -0
- package/lib/typescript/module/specs/components/InlineMessageNativeComponent.d.ts +40 -0
- package/lib/typescript/module/specs/components/InlineMessageNativeComponent.d.ts.map +1 -0
- package/lib/typescript/module/specs/modules/NativeCustomerIO.d.ts +46 -0
- package/lib/typescript/module/specs/modules/NativeCustomerIO.d.ts.map +1 -0
- package/lib/typescript/module/specs/modules/NativeCustomerIOLocation.d.ts +14 -0
- package/lib/typescript/module/specs/modules/NativeCustomerIOLocation.d.ts.map +1 -0
- package/lib/typescript/module/specs/modules/NativeCustomerIOLogging.d.ts +18 -0
- package/lib/typescript/module/specs/modules/NativeCustomerIOLogging.d.ts.map +1 -0
- package/lib/typescript/module/specs/modules/NativeCustomerIOMessagingInApp.d.ts +23 -0
- package/lib/typescript/module/specs/modules/NativeCustomerIOMessagingInApp.d.ts.map +1 -0
- package/lib/typescript/module/specs/modules/NativeCustomerIOMessagingPush.d.ts +20 -0
- package/lib/typescript/module/specs/modules/NativeCustomerIOMessagingPush.d.ts.map +1 -0
- package/lib/typescript/module/types/data-pipelines.d.ts +143 -0
- package/lib/typescript/module/types/data-pipelines.d.ts.map +1 -0
- package/lib/typescript/module/types/in-app.d.ts +67 -0
- package/lib/typescript/module/types/in-app.d.ts.map +1 -0
- package/lib/typescript/module/types/index.d.ts +4 -0
- package/lib/typescript/module/types/index.d.ts.map +1 -0
- package/lib/typescript/module/types/internal.d.ts +20 -0
- package/lib/typescript/module/types/internal.d.ts.map +1 -0
- package/lib/typescript/module/types/push.d.ts +49 -0
- package/lib/typescript/module/types/push.d.ts.map +1 -0
- package/lib/typescript/module/utils/native-bridge.d.ts +9 -0
- package/lib/typescript/module/utils/native-bridge.d.ts.map +1 -0
- package/lib/typescript/module/utils/param-validation.d.ts +44 -0
- package/lib/typescript/module/utils/param-validation.d.ts.map +1 -0
- package/lib/typescript/module/zixflow.d.ts +14 -0
- package/lib/typescript/module/zixflow.d.ts.map +1 -0
- package/package.json +165 -0
- package/src/cio-params.ts +4 -0
- package/src/components/InlineInAppMessageView.tsx +187 -0
- package/src/components/index.ts +3 -0
- package/src/customerio-cdp.ts +190 -0
- package/src/customerio-inapp.ts +127 -0
- package/src/customerio-location.ts +56 -0
- package/src/customerio-push.ts +127 -0
- package/src/index.ts +9 -0
- package/src/native-logger-listener.ts +84 -0
- package/src/notification-inbox.ts +154 -0
- package/src/postInstall.js +10 -0
- package/src/specs/components/InlineMessageNativeComponent.ts +59 -0
- package/src/specs/modules/NativeCustomerIO.ts +55 -0
- package/src/specs/modules/NativeCustomerIOLocation.ts +15 -0
- package/src/specs/modules/NativeCustomerIOLogging.ts +24 -0
- package/src/specs/modules/NativeCustomerIOMessagingInApp.ts +30 -0
- package/src/specs/modules/NativeCustomerIOMessagingPush.ts +27 -0
- package/src/types/data-pipelines.ts +150 -0
- package/src/types/in-app.ts +69 -0
- package/src/types/index.ts +3 -0
- package/src/types/internal.ts +20 -0
- package/src/types/push.ts +50 -0
- package/src/utils/native-bridge.ts +30 -0
- package/src/utils/param-validation.ts +178 -0
- package/src/zixflow.ts +24 -0
- package/zixflow-reactnative-richpush.podspec +42 -0
- package/zixflow-reactnative.podspec +66 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
package io.customer.reactnative.sdk
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.BaseReactPackage
|
|
4
|
+
import com.facebook.react.bridge.NativeModule
|
|
5
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
6
|
+
import com.facebook.react.module.model.ReactModuleInfo
|
|
7
|
+
import com.facebook.react.module.model.ReactModuleInfoProvider
|
|
8
|
+
import com.facebook.react.uimanager.ViewManager
|
|
9
|
+
import io.customer.reactnative.sdk.location.NativeLocationModule
|
|
10
|
+
import io.customer.reactnative.sdk.logging.NativeCustomerIOLoggingModule
|
|
11
|
+
import io.customer.reactnative.sdk.messaginginapp.InlineInAppMessageViewManager
|
|
12
|
+
import io.customer.reactnative.sdk.messaginginapp.NativeMessagingInAppModule
|
|
13
|
+
import io.customer.reactnative.sdk.messagingpush.NativeMessagingPushModule
|
|
14
|
+
import io.customer.reactnative.sdk.util.assertNotNull
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* React Native package for Customer.io SDK that registers all TurboModules and ViewManagers.
|
|
18
|
+
* Implements new architecture support for React Native.
|
|
19
|
+
*/
|
|
20
|
+
class CustomerIOReactNativePackage : BaseReactPackage() {
|
|
21
|
+
/**
|
|
22
|
+
* Creates the list of view managers for the Customer.io React Native SDK.
|
|
23
|
+
*/
|
|
24
|
+
override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
|
|
25
|
+
return listOf(InlineInAppMessageViewManager())
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? {
|
|
29
|
+
// Debugging reveals that this method is never called for ViewManagers.
|
|
30
|
+
// But since ReactNative docs recommend overriding it, we do so here for ViewManagers.
|
|
31
|
+
// See: https://reactnative.dev/docs/fabric-native-components-introduction?platforms=android#4-write-the-reactwebviewpackage
|
|
32
|
+
return when (name) {
|
|
33
|
+
InlineInAppMessageViewManager.NAME -> InlineInAppMessageViewManager()
|
|
34
|
+
NativeCustomerIOLoggingModule.NAME -> NativeCustomerIOLoggingModule(reactContext)
|
|
35
|
+
NativeCustomerIOModule.NAME -> NativeCustomerIOModule(reactContext = reactContext)
|
|
36
|
+
NativeLocationModule.NAME -> if (BuildConfig.CIO_LOCATION_ENABLED) {
|
|
37
|
+
NativeLocationModule(reactContext)
|
|
38
|
+
} else null
|
|
39
|
+
NativeMessagingInAppModule.NAME -> NativeMessagingInAppModule(reactContext)
|
|
40
|
+
NativeMessagingPushModule.NAME -> NativeMessagingPushModule(reactContext)
|
|
41
|
+
else -> assertNotNull<NativeModule>(value = null) { "Unknown module name: $name" }
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Creates a ReactModuleInfo for React module registration with the given configuration.
|
|
47
|
+
* Using positional arguments instead of named arguments as named args break on RN 0.76.
|
|
48
|
+
*/
|
|
49
|
+
private fun createReactModuleInfo(
|
|
50
|
+
name: String,
|
|
51
|
+
className: String = name,
|
|
52
|
+
canOverrideExistingModule: Boolean = false,
|
|
53
|
+
needsEagerInit: Boolean = false,
|
|
54
|
+
isCxxModule: Boolean = false,
|
|
55
|
+
isTurboModule: Boolean = true,
|
|
56
|
+
) = ReactModuleInfo(
|
|
57
|
+
name,
|
|
58
|
+
className,
|
|
59
|
+
canOverrideExistingModule,
|
|
60
|
+
needsEagerInit,
|
|
61
|
+
isCxxModule,
|
|
62
|
+
isTurboModule,
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
override fun getReactModuleInfoProvider(): ReactModuleInfoProvider {
|
|
66
|
+
// List of all Fabric ViewManagers and TurboModules registered in this package.
|
|
67
|
+
// Used by React Native to identify and instantiate the modules.
|
|
68
|
+
// Location module is always registered so TurboModuleRegistry.getEnforcing()
|
|
69
|
+
// doesn't crash at import time. getModule() returns null when disabled.
|
|
70
|
+
val moduleNames: List<String> = listOf(
|
|
71
|
+
InlineInAppMessageViewManager.NAME,
|
|
72
|
+
NativeCustomerIOLoggingModule.NAME,
|
|
73
|
+
NativeCustomerIOModule.NAME,
|
|
74
|
+
NativeLocationModule.NAME,
|
|
75
|
+
NativeMessagingInAppModule.NAME,
|
|
76
|
+
NativeMessagingPushModule.NAME,
|
|
77
|
+
)
|
|
78
|
+
return ReactModuleInfoProvider {
|
|
79
|
+
// Register all ViewManagers and TurboModules
|
|
80
|
+
moduleNames.associateWith { moduleName ->
|
|
81
|
+
createReactModuleInfo(name = moduleName)
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
package io.customer.reactnative.sdk
|
|
2
|
+
|
|
3
|
+
import android.app.Application
|
|
4
|
+
import com.facebook.react.bridge.Promise
|
|
5
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
6
|
+
import com.facebook.react.bridge.ReadableMap
|
|
7
|
+
import io.customer.datapipelines.config.ScreenView
|
|
8
|
+
import io.customer.reactnative.sdk.constant.Keys
|
|
9
|
+
import io.customer.reactnative.sdk.extension.getTypedValue
|
|
10
|
+
import io.customer.reactnative.sdk.extension.toMap
|
|
11
|
+
import io.customer.reactnative.sdk.location.NativeLocationModule
|
|
12
|
+
import io.customer.reactnative.sdk.messaginginapp.NativeMessagingInAppModule
|
|
13
|
+
import io.customer.reactnative.sdk.messagingpush.NativeMessagingPushModule
|
|
14
|
+
import io.customer.reactnative.sdk.util.assertNotNull
|
|
15
|
+
import io.customer.sdk.CustomerIO
|
|
16
|
+
import io.customer.sdk.CustomerIOBuilder
|
|
17
|
+
import io.customer.sdk.core.di.SDKComponent
|
|
18
|
+
import io.customer.sdk.core.util.CioLogLevel
|
|
19
|
+
import io.customer.sdk.core.util.Logger
|
|
20
|
+
import io.customer.sdk.data.model.Region
|
|
21
|
+
import io.customer.sdk.events.Metric
|
|
22
|
+
import io.customer.sdk.events.TrackMetric
|
|
23
|
+
import io.customer.sdk.events.serializedName
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* React Native module implementation for Customer.io Native SDK
|
|
27
|
+
* using TurboModules with new architecture.
|
|
28
|
+
*/
|
|
29
|
+
class NativeCustomerIOModule(
|
|
30
|
+
private val reactContext: ReactApplicationContext,
|
|
31
|
+
) : NativeCustomerIOSpec(reactContext) {
|
|
32
|
+
private val logger: Logger
|
|
33
|
+
get() = SDKComponent.logger
|
|
34
|
+
|
|
35
|
+
// Returns CustomerIO instance if initialized, null otherwise, with configurable failure handling.
|
|
36
|
+
private inline fun getSDKInstanceOrNull(
|
|
37
|
+
onFailure: (exception: Throwable) -> Unit = {}
|
|
38
|
+
): CustomerIO? = runCatching {
|
|
39
|
+
// If the SDK is not initialized, `CustomerIO.instance()` throws an exception
|
|
40
|
+
CustomerIO.instance()
|
|
41
|
+
}.onFailure(onFailure).getOrNull()
|
|
42
|
+
|
|
43
|
+
// Returns CustomerIO instance if initialized, null otherwise, logging error on failure.
|
|
44
|
+
private fun requireSDKInstance(): CustomerIO? = getSDKInstanceOrNull {
|
|
45
|
+
logger.error("CustomerIO SDK is not initialized. Please call initialize() first.")
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
override fun initialize(config: ReadableMap?, args: ReadableMap?, promise: Promise?) {
|
|
50
|
+
// Skip initialization if already initialized
|
|
51
|
+
if (getSDKInstanceOrNull() != null) {
|
|
52
|
+
logger.info("CustomerIO SDK is already initialized. Skipping initialization.")
|
|
53
|
+
promise?.resolve(true)
|
|
54
|
+
return
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
try {
|
|
58
|
+
val packageConfig = config.toMap()
|
|
59
|
+
val cdpApiKey = packageConfig.getTypedValue<String>(
|
|
60
|
+
Keys.Config.CDP_API_KEY
|
|
61
|
+
) ?: throw IllegalArgumentException("CDP API Key is required to initialize Customer.io")
|
|
62
|
+
|
|
63
|
+
val logLevelRawValue = packageConfig.getTypedValue<String>(Keys.Config.LOG_LEVEL)
|
|
64
|
+
val regionRawValue = packageConfig.getTypedValue<String>(Keys.Config.REGION)
|
|
65
|
+
val region = regionRawValue.let { Region.getRegion(it) }
|
|
66
|
+
val screenViewRawValue =
|
|
67
|
+
packageConfig.getTypedValue<String>(Keys.Config.SCREEN_VIEW_USE)
|
|
68
|
+
|
|
69
|
+
CustomerIOBuilder(
|
|
70
|
+
applicationContext = reactContext.applicationContext as Application,
|
|
71
|
+
cdpApiKey = cdpApiKey
|
|
72
|
+
).apply {
|
|
73
|
+
logLevelRawValue?.let { logLevel(CioLogLevel.getLogLevel(it)) }
|
|
74
|
+
regionRawValue?.let { region(region) }
|
|
75
|
+
screenViewRawValue?.let { screenViewUse(ScreenView.getScreenView(it)) }
|
|
76
|
+
|
|
77
|
+
packageConfig.getTypedValue<Boolean>(Keys.Config.AUTO_TRACK_DEVICE_ATTRIBUTES)
|
|
78
|
+
?.let { autoTrackDeviceAttributes(it) }
|
|
79
|
+
packageConfig.getTypedValue<String>(Keys.Config.MIGRATION_SITE_ID)
|
|
80
|
+
?.let { migrationSiteId(it) }
|
|
81
|
+
packageConfig.getTypedValue<Int>(Keys.Config.FLUSH_AT)
|
|
82
|
+
?.let { flushAt(it) }
|
|
83
|
+
packageConfig.getTypedValue<Int>(Keys.Config.FLUSH_INTERVAL)
|
|
84
|
+
?.let { flushInterval(it) }
|
|
85
|
+
packageConfig.getTypedValue<Boolean>(Keys.Config.TRACK_APP_LIFECYCLE_EVENTS)
|
|
86
|
+
?.let { trackApplicationLifecycleEvents(it) }
|
|
87
|
+
packageConfig.getTypedValue<String>(Keys.Config.API_HOST)
|
|
88
|
+
?.let { apiHost(it) }
|
|
89
|
+
packageConfig.getTypedValue<String>(Keys.Config.CDN_HOST)
|
|
90
|
+
?.let { cdnHost(it) }
|
|
91
|
+
|
|
92
|
+
// Configure push messaging module based on config provided by customer app
|
|
93
|
+
packageConfig.getTypedValue<Map<String, Any>>(key = "push").let { pushConfig ->
|
|
94
|
+
NativeMessagingPushModule.addNativeModuleFromConfig(
|
|
95
|
+
builder = this,
|
|
96
|
+
config = pushConfig ?: emptyMap()
|
|
97
|
+
)
|
|
98
|
+
}
|
|
99
|
+
// Configure in-app messaging module based on config provided by customer app
|
|
100
|
+
packageConfig.getTypedValue<Map<String, Any>>(key = "inApp")?.let { inAppConfig ->
|
|
101
|
+
NativeMessagingInAppModule.addNativeModuleFromConfig(
|
|
102
|
+
builder = this,
|
|
103
|
+
config = inAppConfig,
|
|
104
|
+
region = region
|
|
105
|
+
)
|
|
106
|
+
}
|
|
107
|
+
// Configure location module if enabled via gradle property
|
|
108
|
+
if (BuildConfig.CIO_LOCATION_ENABLED) {
|
|
109
|
+
packageConfig.getTypedValue<Map<String, Any>>(key = "location")?.let { locationConfig ->
|
|
110
|
+
NativeLocationModule.addNativeModuleFromConfig(
|
|
111
|
+
builder = this,
|
|
112
|
+
config = locationConfig
|
|
113
|
+
)
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}.build()
|
|
117
|
+
|
|
118
|
+
logger.info("Customer.io instance initialized successfully from app")
|
|
119
|
+
promise?.resolve(true)
|
|
120
|
+
} catch (ex: Exception) {
|
|
121
|
+
logger.error("Failed to initialize Customer.io instance from app, ${ex.message}")
|
|
122
|
+
promise?.reject(ex)
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
override fun identify(params: ReadableMap?) {
|
|
127
|
+
val userId = params?.getString("userId")
|
|
128
|
+
val traits = params?.getMap("traits")
|
|
129
|
+
|
|
130
|
+
if (userId == null && traits == null) {
|
|
131
|
+
logger.error("Either userId or traits must be provided for identify")
|
|
132
|
+
return
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
userId?.let {
|
|
136
|
+
requireSDKInstance()?.identify(userId, traits.toMap())
|
|
137
|
+
} ?: run {
|
|
138
|
+
requireSDKInstance()?.setProfileAttributes(traits.toMap())
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
override fun clearIdentify() {
|
|
143
|
+
requireSDKInstance()?.clearIdentify()
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
override fun track(name: String?, properties: ReadableMap?) {
|
|
147
|
+
val eventName = assertNotNull(name) ?: return
|
|
148
|
+
|
|
149
|
+
requireSDKInstance()?.track(eventName, properties.toMap())
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
override fun screen(title: String?, properties: ReadableMap?) {
|
|
153
|
+
val screenTitle = assertNotNull(title) ?: return
|
|
154
|
+
|
|
155
|
+
requireSDKInstance()?.screen(screenTitle, properties.toMap())
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
override fun setProfileAttributes(attributes: ReadableMap?) {
|
|
159
|
+
requireSDKInstance()?.setProfileAttributes(attributes.toMap())
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
override fun setDeviceAttributes(attributes: ReadableMap?) {
|
|
163
|
+
requireSDKInstance()?.setDeviceAttributes(attributes.toMap())
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
override fun registerDeviceToken(token: String?) {
|
|
167
|
+
val deviceToken = assertNotNull(token) ?: return
|
|
168
|
+
|
|
169
|
+
requireSDKInstance()?.registerDeviceToken(deviceToken)
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
override fun trackMetric(deliveryID: String?, deviceToken: String?, event: String?) {
|
|
173
|
+
try {
|
|
174
|
+
if (deliveryID == null || deviceToken == null || event == null) {
|
|
175
|
+
throw IllegalArgumentException("Missing required parameters")
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
val metric = Metric.values().find {
|
|
179
|
+
it.serializedName.equals(event, true)
|
|
180
|
+
} ?: throw IllegalArgumentException("Invalid metric event name")
|
|
181
|
+
|
|
182
|
+
requireSDKInstance()?.trackMetric(
|
|
183
|
+
event = TrackMetric.Push(
|
|
184
|
+
deliveryId = deliveryID,
|
|
185
|
+
deviceToken = deviceToken,
|
|
186
|
+
metric = metric
|
|
187
|
+
)
|
|
188
|
+
)
|
|
189
|
+
} catch (e: Exception) {
|
|
190
|
+
logger.error("Error tracking push metric: ${e.message}")
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
override fun deleteDeviceToken() {
|
|
195
|
+
requireSDKInstance()?.deleteDeviceToken()
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
companion object {
|
|
199
|
+
internal const val NAME = "NativeCustomerIO"
|
|
200
|
+
}
|
|
201
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
package io.customer.reactnative.sdk.constant
|
|
2
|
+
|
|
3
|
+
internal object Keys {
|
|
4
|
+
object Config {
|
|
5
|
+
const val LOG_LEVEL = "logLevel"
|
|
6
|
+
const val REGION = "region"
|
|
7
|
+
const val AUTO_TRACK_DEVICE_ATTRIBUTES = "autoTrackDeviceAttributes"
|
|
8
|
+
const val CDP_API_KEY = "cdpApiKey"
|
|
9
|
+
const val SITE_ID = "siteId"
|
|
10
|
+
const val MIGRATION_SITE_ID = "migrationSiteId"
|
|
11
|
+
const val TRACK_APP_LIFECYCLE_EVENTS = "trackApplicationLifecycleEvents"
|
|
12
|
+
const val FLUSH_AT = "flushAt"
|
|
13
|
+
const val FLUSH_INTERVAL = "flushInterval"
|
|
14
|
+
const val SCREEN_VIEW_USE = "screenViewUse"
|
|
15
|
+
const val API_HOST = "apiHost"
|
|
16
|
+
const val CDN_HOST = "cdnHost"
|
|
17
|
+
// Push messaging
|
|
18
|
+
const val PUSH_CLICK_BEHAVIOR = "pushClickBehavior"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
package io.customer.reactnative.sdk.extension
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.Arguments
|
|
4
|
+
import com.facebook.react.bridge.ReadableMap
|
|
5
|
+
import com.facebook.react.bridge.WritableArray
|
|
6
|
+
import com.facebook.react.bridge.WritableMap
|
|
7
|
+
|
|
8
|
+
// Converts ReadableMap to Kotlin Map, filtering out null values.
|
|
9
|
+
internal fun ReadableMap?.toMap(): Map<String, Any> {
|
|
10
|
+
return this?.toHashMap()?.filterValues {
|
|
11
|
+
it != null
|
|
12
|
+
}?.mapValues { it.value as Any } ?: emptyMap()
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// Retrieves a typed value from the map using reified type parameter.
|
|
16
|
+
internal inline fun <reified V> Map<String, Any?>?.getTypedValue(key: String): V? {
|
|
17
|
+
return this?.get(key) as? V
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Converts Kotlin Map to WritableMap for React Native, handling nested maps/arrays recursively.
|
|
22
|
+
* Long values are converted to Double since JavaScript doesn't have type Long.
|
|
23
|
+
*/
|
|
24
|
+
internal fun Map<String, Any?>.toWritableMap(): WritableMap {
|
|
25
|
+
val writableMap = Arguments.createMap()
|
|
26
|
+
|
|
27
|
+
for ((key, value) in this) {
|
|
28
|
+
when (value) {
|
|
29
|
+
null -> writableMap.putNull(key)
|
|
30
|
+
is String -> writableMap.putString(key, value)
|
|
31
|
+
is Int -> writableMap.putInt(key, value)
|
|
32
|
+
is Double -> writableMap.putDouble(key, value)
|
|
33
|
+
is Float -> writableMap.putDouble(key, value.toDouble())
|
|
34
|
+
is Boolean -> writableMap.putBoolean(key, value)
|
|
35
|
+
is Long -> writableMap.putDouble(key, value.toDouble()) // JS has no Long
|
|
36
|
+
is Map<*, *> -> {
|
|
37
|
+
@Suppress("UNCHECKED_CAST")
|
|
38
|
+
writableMap.putMap(key, (value as Map<String, Any?>).toWritableMap())
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
is List<*> -> writableMap.putArray(key, value.toWritableArray())
|
|
42
|
+
else -> {
|
|
43
|
+
// Fallback — convert to string
|
|
44
|
+
writableMap.putString(key, value.toString())
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return writableMap
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Converts Kotlin List to WritableArray for React Native, handling nested lists/maps recursively.
|
|
54
|
+
* Long values are converted to Double since JavaScript doesn't have type Long.
|
|
55
|
+
*/
|
|
56
|
+
internal fun List<*>.toWritableArray(): WritableArray {
|
|
57
|
+
val writableArray = Arguments.createArray()
|
|
58
|
+
|
|
59
|
+
for (value in this) {
|
|
60
|
+
when (value) {
|
|
61
|
+
null -> writableArray.pushNull()
|
|
62
|
+
is String -> writableArray.pushString(value)
|
|
63
|
+
is Int -> writableArray.pushInt(value)
|
|
64
|
+
is Double -> writableArray.pushDouble(value)
|
|
65
|
+
is Float -> writableArray.pushDouble(value.toDouble())
|
|
66
|
+
is Boolean -> writableArray.pushBoolean(value)
|
|
67
|
+
is Long -> writableArray.pushDouble(value.toDouble())
|
|
68
|
+
is Map<*, *> -> {
|
|
69
|
+
@Suppress("UNCHECKED_CAST")
|
|
70
|
+
writableArray.pushMap((value as Map<String, Any?>).toWritableMap())
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
is List<*> -> writableArray.pushArray(value.toWritableArray())
|
|
74
|
+
else -> writableArray.pushString(value.toString())
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return writableArray
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Puts a value into WritableMap, calling putNull if value is null, otherwise executing putBlock.
|
|
82
|
+
internal inline fun <T> WritableMap.putOrNull(
|
|
83
|
+
key: String,
|
|
84
|
+
value: T?,
|
|
85
|
+
putBlock: WritableMap.(String, T) -> Unit,
|
|
86
|
+
) {
|
|
87
|
+
if (value == null) {
|
|
88
|
+
putNull(key)
|
|
89
|
+
} else {
|
|
90
|
+
putBlock(key, value)
|
|
91
|
+
}
|
|
92
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
package io.customer.reactnative.sdk.extension
|
|
2
|
+
|
|
3
|
+
import android.view.View
|
|
4
|
+
import com.facebook.react.bridge.ReactContext
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Extension property to get [ReactContext] from a View.
|
|
8
|
+
* Casts the view's context to ReactContext for React Native integration.
|
|
9
|
+
*/
|
|
10
|
+
internal val View.reactContext: ReactContext
|
|
11
|
+
get() = context as ReactContext
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
package io.customer.reactnative.sdk.extension
|
|
2
|
+
|
|
3
|
+
import android.view.View
|
|
4
|
+
import com.facebook.react.bridge.WritableMap
|
|
5
|
+
import com.facebook.react.uimanager.UIManagerHelper
|
|
6
|
+
import com.facebook.react.uimanager.events.Event
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Extension function to send UI events from native Android views to React JS.
|
|
10
|
+
* Retrieves the event dispatcher and dispatches the event to React Native bridge.
|
|
11
|
+
*
|
|
12
|
+
* @param eventName The name of the event to be sent to React JS
|
|
13
|
+
* @param payload Optional data payload to include with the event
|
|
14
|
+
*/
|
|
15
|
+
internal fun View.sendUIEventToReactJS(
|
|
16
|
+
eventName: String,
|
|
17
|
+
payload: WritableMap? = null,
|
|
18
|
+
) {
|
|
19
|
+
val eventDispatcher = UIManagerHelper.getEventDispatcherForReactTag(reactContext, id)
|
|
20
|
+
eventDispatcher?.dispatchEvent(UIStateEvent(this, eventName, payload))
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Event class for sending UI state changes from Android views to React Native.
|
|
25
|
+
* Extends the React Native Event class to provide a bridge for native-to-JS communication.
|
|
26
|
+
*/
|
|
27
|
+
private class UIStateEvent(
|
|
28
|
+
view: View,
|
|
29
|
+
private val name: String,
|
|
30
|
+
private val payload: WritableMap? = null
|
|
31
|
+
) : Event<UIStateEvent>(UIManagerHelper.getSurfaceId(view.reactContext), view.id) {
|
|
32
|
+
override fun getEventName() = name
|
|
33
|
+
override fun getEventData(): WritableMap? = payload
|
|
34
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
package io.customer.reactnative.sdk.location
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
4
|
+
import com.facebook.react.module.annotations.ReactModule
|
|
5
|
+
import io.customer.location.LocationModuleConfig
|
|
6
|
+
import io.customer.location.LocationTrackingMode
|
|
7
|
+
import io.customer.location.ModuleLocation
|
|
8
|
+
import io.customer.reactnative.sdk.NativeCustomerIOLocationSpec
|
|
9
|
+
import io.customer.reactnative.sdk.extension.getTypedValue
|
|
10
|
+
import io.customer.sdk.CustomerIOBuilder
|
|
11
|
+
import io.customer.sdk.core.di.SDKComponent
|
|
12
|
+
import io.customer.sdk.core.util.Logger
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* React Native module implementation for Customer.io Location Native SDK
|
|
16
|
+
* using TurboModules with new architecture.
|
|
17
|
+
*/
|
|
18
|
+
@ReactModule(name = NativeLocationModule.NAME)
|
|
19
|
+
class NativeLocationModule(
|
|
20
|
+
private val reactContext: ReactApplicationContext,
|
|
21
|
+
) : NativeCustomerIOLocationSpec(reactContext) {
|
|
22
|
+
private val logger: Logger
|
|
23
|
+
get() = SDKComponent.logger
|
|
24
|
+
|
|
25
|
+
private fun getLocationServices() = runCatching {
|
|
26
|
+
ModuleLocation.instance().locationServices
|
|
27
|
+
}.onFailure {
|
|
28
|
+
logger.error("Location module is not initialized. Ensure location config is provided during SDK initialization.")
|
|
29
|
+
}.getOrNull()
|
|
30
|
+
|
|
31
|
+
override fun setLastKnownLocation(latitude: Double, longitude: Double) {
|
|
32
|
+
getLocationServices()?.setLastKnownLocation(latitude, longitude)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
override fun requestLocationUpdate() {
|
|
36
|
+
getLocationServices()?.requestLocationUpdate()
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
companion object {
|
|
40
|
+
const val NAME = "NativeCustomerIOLocation"
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Adds location module to native Android SDK based on the configuration provided by
|
|
44
|
+
* customer app.
|
|
45
|
+
*
|
|
46
|
+
* @param builder instance of CustomerIOBuilder to add location module.
|
|
47
|
+
* @param config configuration provided by customer app for location module.
|
|
48
|
+
*/
|
|
49
|
+
internal fun addNativeModuleFromConfig(
|
|
50
|
+
builder: CustomerIOBuilder,
|
|
51
|
+
config: Map<String, Any>
|
|
52
|
+
) {
|
|
53
|
+
val trackingModeValue = config.getTypedValue<String>("trackingMode")
|
|
54
|
+
val trackingMode = trackingModeValue?.let { value ->
|
|
55
|
+
runCatching { enumValueOf<LocationTrackingMode>(value) }.getOrNull()
|
|
56
|
+
} ?: LocationTrackingMode.MANUAL
|
|
57
|
+
|
|
58
|
+
val module = ModuleLocation(
|
|
59
|
+
LocationModuleConfig.Builder()
|
|
60
|
+
.setLocationTrackingMode(trackingMode)
|
|
61
|
+
.build()
|
|
62
|
+
)
|
|
63
|
+
builder.addCustomerIOModule(module)
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
package/android/src/main/java/io/customer/reactnative/sdk/logging/NativeCustomerIOLoggingModule.kt
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
package io.customer.reactnative.sdk.logging
|
|
2
|
+
|
|
3
|
+
import android.util.Log
|
|
4
|
+
import com.facebook.react.bridge.Arguments
|
|
5
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
6
|
+
import com.facebook.react.bridge.ReadableMap
|
|
7
|
+
import io.customer.reactnative.sdk.NativeCustomerIOLoggingSpec
|
|
8
|
+
import io.customer.sdk.core.di.SDKComponent
|
|
9
|
+
import io.customer.sdk.core.util.CioLogLevel
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* React Native module implementation for Customer.io Logging Native SDK
|
|
13
|
+
* using TurboModules with new architecture.
|
|
14
|
+
*/
|
|
15
|
+
class NativeCustomerIOLoggingModule(
|
|
16
|
+
reactContext: ReactApplicationContext,
|
|
17
|
+
) : NativeCustomerIOLoggingSpec(reactContext) {
|
|
18
|
+
override fun getName(): String = NAME
|
|
19
|
+
|
|
20
|
+
// Log event emitter function to send events to React Native layer
|
|
21
|
+
private var logEventEmitter: ((ReadableMap) -> Unit)? = null
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Executes the given block and logs any uncaught exceptions using Android logger to protect
|
|
25
|
+
* against unexpected crashes and failures.
|
|
26
|
+
*/
|
|
27
|
+
private fun runWithTryCatch(action: () -> Unit) {
|
|
28
|
+
try {
|
|
29
|
+
action()
|
|
30
|
+
} catch (ex: Exception) {
|
|
31
|
+
// Use Android logger to avoid cyclic calls from internal SDK logging
|
|
32
|
+
Log.e("[CIO]", "Error in NativeCustomerIOLoggingModule: ${ex.message}", ex)
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
override fun initialize() {
|
|
37
|
+
runWithTryCatch {
|
|
38
|
+
super.initialize()
|
|
39
|
+
setLogEventEmitter { data ->
|
|
40
|
+
emitOnCioLogEvent(data)
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
override fun invalidate() {
|
|
46
|
+
runWithTryCatch {
|
|
47
|
+
cleanupLogEventEmitter()
|
|
48
|
+
super.invalidate()
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
private fun cleanupLogEventEmitter() {
|
|
53
|
+
runWithTryCatch {
|
|
54
|
+
// Clear log dispatcher to prevent memory leaks and further events
|
|
55
|
+
SDKComponent.logger.setLogDispatcher(null)
|
|
56
|
+
this.logEventEmitter = null
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Sets the event emitter function used to send log events to React Native.
|
|
61
|
+
private fun setLogEventEmitter(emitter: ((ReadableMap) -> Unit)?) {
|
|
62
|
+
if (emitter == null) {
|
|
63
|
+
// Clear log dispatcher if emitter is null
|
|
64
|
+
cleanupLogEventEmitter()
|
|
65
|
+
return
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
SDKComponent.logger.setLogDispatcher { level, message ->
|
|
69
|
+
emitLogEvent(level, message)
|
|
70
|
+
}
|
|
71
|
+
this.logEventEmitter = emitter
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Converts native SDK log events to React Native compatible format and emits them.
|
|
75
|
+
private fun emitLogEvent(level: CioLogLevel, message: String) {
|
|
76
|
+
// Defensive check: only emit if emitter is available
|
|
77
|
+
val emitter = logEventEmitter ?: return
|
|
78
|
+
|
|
79
|
+
val data = buildMap {
|
|
80
|
+
put("logLevel", level.name.lowercase())
|
|
81
|
+
put("message", message)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
emitter.invoke(Arguments.makeNativeMap(data))
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
companion object {
|
|
88
|
+
internal const val NAME = "NativeCustomerIOLogging"
|
|
89
|
+
}
|
|
90
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
package io.customer.reactnative.sdk.messaginginapp
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.module.annotations.ReactModule
|
|
4
|
+
import com.facebook.react.uimanager.SimpleViewManager
|
|
5
|
+
import com.facebook.react.uimanager.ThemedReactContext
|
|
6
|
+
import com.facebook.react.uimanager.ViewManagerDelegate
|
|
7
|
+
import com.facebook.react.uimanager.annotations.ReactProp
|
|
8
|
+
import com.facebook.react.viewmanagers.InlineMessageNativeManagerDelegate
|
|
9
|
+
import com.facebook.react.viewmanagers.InlineMessageNativeManagerInterface
|
|
10
|
+
import io.customer.messaginginapp.ui.bridge.WrapperPlatformDelegate
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Base view manager for inline in-app message components.
|
|
14
|
+
*
|
|
15
|
+
* Provides common functionality for both old and new React Native architecture
|
|
16
|
+
* implementations, including view creation, event handling, and property management.
|
|
17
|
+
*/
|
|
18
|
+
@ReactModule(name = InlineInAppMessageViewManager.NAME)
|
|
19
|
+
class InlineInAppMessageViewManager :
|
|
20
|
+
InlineMessageNativeManagerInterface<ReactInlineInAppMessageView>,
|
|
21
|
+
SimpleViewManager<ReactInlineInAppMessageView>() {
|
|
22
|
+
private val delegate = InlineMessageNativeManagerDelegate(this)
|
|
23
|
+
|
|
24
|
+
override fun getName() = NAME
|
|
25
|
+
override fun getDelegate(): ViewManagerDelegate<ReactInlineInAppMessageView> = delegate
|
|
26
|
+
|
|
27
|
+
override fun createViewInstance(reactContext: ThemedReactContext): ReactInlineInAppMessageView {
|
|
28
|
+
return ReactInlineInAppMessageView(reactContext)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* This method exports custom direct event types for the inline message view.
|
|
33
|
+
* It registers two custom events:
|
|
34
|
+
* - onSizeChange: Triggered when the size of the inline message changes.
|
|
35
|
+
* - onStateChange: Triggered when the state of the inline message changes.
|
|
36
|
+
*/
|
|
37
|
+
override fun getExportedCustomDirectEventTypeConstants(): Map<String?, Any?> {
|
|
38
|
+
val customEvents = super.getExportedCustomDirectEventTypeConstants() ?: mutableMapOf()
|
|
39
|
+
val registerCustomEvent = { eventName: String ->
|
|
40
|
+
customEvents.put(eventName, mapOf("registrationName" to eventName))
|
|
41
|
+
}
|
|
42
|
+
registerCustomEvent(WrapperPlatformDelegate.ON_SIZE_CHANGE)
|
|
43
|
+
registerCustomEvent(WrapperPlatformDelegate.ON_STATE_CHANGE)
|
|
44
|
+
registerCustomEvent(ReactInAppPlatformDelegate.ON_ACTION_CLICK)
|
|
45
|
+
return customEvents
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
@ReactProp(name = "elementId")
|
|
49
|
+
override fun setElementId(view: ReactInlineInAppMessageView?, value: String?) {
|
|
50
|
+
view?.elementId = value
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
companion object {
|
|
54
|
+
internal const val NAME = "InlineMessageNative"
|
|
55
|
+
}
|
|
56
|
+
}
|