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,124 @@
|
|
|
1
|
+
import CioMessagingInApp
|
|
2
|
+
import Foundation
|
|
3
|
+
import UIKit
|
|
4
|
+
|
|
5
|
+
/// React Native wrapper for inline message display with content view lifecycle management.
|
|
6
|
+
///
|
|
7
|
+
/// This Swift class provides the actual functionality while allowing Objective-C/C++ files to
|
|
8
|
+
/// import only the header for compile-time safety across different linking configurations.
|
|
9
|
+
/// Methods are called dynamically from Objective-C using runtime resolution.
|
|
10
|
+
@objc(ReactInlineMessageView)
|
|
11
|
+
class ReactInlineMessageView: NSObject {
|
|
12
|
+
private weak var eventEmitter: AnyObject?
|
|
13
|
+
private let contentView: InlineMessageBridgeView = .init()
|
|
14
|
+
|
|
15
|
+
@objc
|
|
16
|
+
init(containerView: UIView) {
|
|
17
|
+
super.init()
|
|
18
|
+
contentView.attachToParent(parent: containerView, delegate: self)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
@objc
|
|
22
|
+
func setEventEmitter(_ eventEmitter: AnyObject?) {
|
|
23
|
+
self.eventEmitter = eventEmitter
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
@objc
|
|
27
|
+
func setElementId(_ elementId: String) {
|
|
28
|
+
// Set element ID on the prepared content view
|
|
29
|
+
contentView.elementId = elementId
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
@objc
|
|
33
|
+
func setupForReuse() {
|
|
34
|
+
contentView.onViewAttached()
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
@objc
|
|
38
|
+
func prepareForRecycle() {
|
|
39
|
+
// Remove content view for reuse, cleaning up observers and releasing resources
|
|
40
|
+
contentView.onViewDetached()
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
@objc
|
|
44
|
+
func updateLayout(_ boundsValue: NSValue) {
|
|
45
|
+
let bounds = boundsValue.cgRectValue
|
|
46
|
+
contentView.frame = bounds
|
|
47
|
+
contentView.setNeedsLayout()
|
|
48
|
+
contentView.layoutIfNeeded()
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// MARK: - Event Emission Helper
|
|
52
|
+
|
|
53
|
+
private func emitEvent(_ selectorName: String, payload: [String: Any?]) {
|
|
54
|
+
guard let emitter = eventEmitter else {
|
|
55
|
+
assertionFailure("Event emitter is nil when trying to emit \(selectorName)")
|
|
56
|
+
return
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
let selector = Selector((selectorName))
|
|
60
|
+
guard emitter.responds(to: selector) else {
|
|
61
|
+
assertionFailure("Event emitter does not respond to selector: \(selectorName)")
|
|
62
|
+
return
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
_ = emitter.perform(selector, with: payload as NSDictionary)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
private func sendOnSizeChangeEvent(width: Double = 0, height: Double) {
|
|
69
|
+
let duration = 200.0
|
|
70
|
+
var payload: [String: Any] = [
|
|
71
|
+
"height": height,
|
|
72
|
+
"duration": duration
|
|
73
|
+
]
|
|
74
|
+
|
|
75
|
+
// Only include positive width values as rendering requires valid width to calculate layout size
|
|
76
|
+
if width > 0 {
|
|
77
|
+
payload["width"] = width
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
emitEvent("emitOnSizeChangeEvent:", payload: payload)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
private func sendOnStateChangeEvent(state: InlineInAppMessageStateEvent) {
|
|
84
|
+
let payload: [String: Any] = [
|
|
85
|
+
"state": state.stringValue
|
|
86
|
+
]
|
|
87
|
+
|
|
88
|
+
emitEvent("emitOnStateChangeEvent:", payload: payload)
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
extension ReactInlineMessageView: InlineMessageBridgeViewDelegate {
|
|
93
|
+
func onActionClick(message: InAppMessage, actionValue: String, actionName: String) -> Bool {
|
|
94
|
+
let payload: [String: Any?] = [
|
|
95
|
+
"message": [
|
|
96
|
+
"messageId": message.messageId,
|
|
97
|
+
"deliveryId": message.deliveryId,
|
|
98
|
+
"elementId": message.elementId
|
|
99
|
+
],
|
|
100
|
+
"actionValue": actionValue,
|
|
101
|
+
"actionName": actionName
|
|
102
|
+
]
|
|
103
|
+
|
|
104
|
+
emitEvent("emitOnActionClickEvent:", payload: payload)
|
|
105
|
+
return true
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
func onMessageSizeChanged(width: CGFloat, height: CGFloat) {
|
|
109
|
+
sendOnSizeChangeEvent(width: width, height: height)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
func onNoMessageToDisplay() {
|
|
113
|
+
sendOnStateChangeEvent(state: .noMessageToDisplay)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
func onStartLoading(onComplete: @escaping () -> Void) {
|
|
117
|
+
sendOnStateChangeEvent(state: .loadingStarted)
|
|
118
|
+
onComplete()
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
func onFinishLoading() {
|
|
122
|
+
sendOnStateChangeEvent(state: .loadingFinished)
|
|
123
|
+
}
|
|
124
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
#import <React/RCTBridgeModule.h>
|
|
2
|
+
#import <RNZixflowSpec/RNZixflowSpec.h>
|
|
3
|
+
|
|
4
|
+
// Objective-C wrapper for new architecture TurboModule implementation
|
|
5
|
+
@interface RCTNativeCustomerIOLocation : NSObject <NativeCustomerIOLocationSpec>
|
|
6
|
+
// Bridge to Swift implementation for cross-language compatibility
|
|
7
|
+
@property(nonatomic, strong) id<NativeCustomerIOLocationSpec> swiftBridge;
|
|
8
|
+
@end
|
|
9
|
+
|
|
10
|
+
@implementation RCTNativeCustomerIOLocation
|
|
11
|
+
|
|
12
|
+
RCT_EXPORT_MODULE()
|
|
13
|
+
|
|
14
|
+
// Create TurboModule instance for new architecture JSI integration
|
|
15
|
+
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
|
|
16
|
+
(const facebook::react::ObjCTurboModule::InitParams &)params {
|
|
17
|
+
return std::make_shared<facebook::react::NativeCustomerIOLocationSpecJSI>(params);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
- (instancetype)init {
|
|
21
|
+
if (self = [super init]) {
|
|
22
|
+
// Use runtime class lookup - NativeLocation class only exists when CioLocation subspec is installed
|
|
23
|
+
Class swiftClass = NSClassFromString(@"NativeCustomerIOLocation");
|
|
24
|
+
if (swiftClass) {
|
|
25
|
+
_swiftBridge = [[swiftClass alloc] init];
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return self;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Module initialization can happen on background thread
|
|
32
|
+
+ (BOOL)requiresMainQueueSetup {
|
|
33
|
+
return NO;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
- (void)setLastKnownLocation:(double)latitude
|
|
37
|
+
longitude:(double)longitude {
|
|
38
|
+
if (!_swiftBridge) return;
|
|
39
|
+
[_swiftBridge setLastKnownLocation:latitude longitude:longitude];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
- (void)requestLocationUpdate {
|
|
43
|
+
if (!_swiftBridge) return;
|
|
44
|
+
[_swiftBridge requestLocationUpdate];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Export class factory function for React Native component registration
|
|
48
|
+
Class<RCTBridgeModule> NativeCustomerIOLocationCls(void) {
|
|
49
|
+
return RCTNativeCustomerIOLocation.class;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
@end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#if CIO_LOCATION_ENABLED
|
|
2
|
+
import CioDataPipelines
|
|
3
|
+
import CioLocation
|
|
4
|
+
import CoreLocation
|
|
5
|
+
|
|
6
|
+
@objc(NativeCustomerIOLocation)
|
|
7
|
+
public class NativeLocation: NSObject {
|
|
8
|
+
|
|
9
|
+
/// Parses the root config and returns a `LocationModule` if location config is present.
|
|
10
|
+
/// Keeps config parsing within the location module.
|
|
11
|
+
static func module(from config: [String: Any]) -> LocationModule? {
|
|
12
|
+
guard let locationConfig = config["location"] as? [String: Any] else { return nil }
|
|
13
|
+
let trackingModeValue = locationConfig["trackingMode"] as? String
|
|
14
|
+
let mode: LocationTrackingMode
|
|
15
|
+
switch trackingModeValue?.uppercased() {
|
|
16
|
+
case "OFF":
|
|
17
|
+
mode = .off
|
|
18
|
+
case "ON_APP_START":
|
|
19
|
+
mode = .onAppStart
|
|
20
|
+
default:
|
|
21
|
+
mode = .manual
|
|
22
|
+
}
|
|
23
|
+
return LocationModule(config: LocationConfig(mode: mode))
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
@objc
|
|
27
|
+
func setLastKnownLocation(_ latitude: Double, longitude: Double) {
|
|
28
|
+
let location = CLLocation(latitude: latitude, longitude: longitude)
|
|
29
|
+
CustomerIO.location.setLastKnownLocation(location)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
@objc
|
|
33
|
+
func requestLocationUpdate() {
|
|
34
|
+
CustomerIO.location.requestLocationUpdate()
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
#endif
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
#import "../utils/RCTCustomerIOUtils.h"
|
|
2
|
+
#import <React/RCTBridgeModule.h>
|
|
3
|
+
#import <React/RCTEventEmitter.h>
|
|
4
|
+
#import <React/RCTInitializing.h>
|
|
5
|
+
#import <React/RCTInvalidating.h>
|
|
6
|
+
#import <RNZixflowSpec/RNZixflowSpec.h>
|
|
7
|
+
|
|
8
|
+
// Protocol that extends the spec with event emitter methods
|
|
9
|
+
@protocol NativeCustomerIOLoggingBridge <NativeCustomerIOLoggingSpec, RCTInitializing, RCTInvalidating>
|
|
10
|
+
- (void)setEventEmitter:(id)emitter;
|
|
11
|
+
@end
|
|
12
|
+
|
|
13
|
+
// Objective-C wrapper for new architecture TurboModule implementation
|
|
14
|
+
@interface RCTNativeCustomerIOLogging
|
|
15
|
+
: NativeCustomerIOLoggingSpecBase <NativeCustomerIOLoggingSpec>
|
|
16
|
+
// Bridge to Swift implementation for cross-language compatibility
|
|
17
|
+
@property(nonatomic, strong) id<NativeCustomerIOLoggingBridge> swiftBridge;
|
|
18
|
+
@end
|
|
19
|
+
|
|
20
|
+
@implementation RCTNativeCustomerIOLogging
|
|
21
|
+
|
|
22
|
+
RCT_EXPORT_MODULE()
|
|
23
|
+
|
|
24
|
+
// Create TurboModule instance for new architecture JSI integration
|
|
25
|
+
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
|
|
26
|
+
(const facebook::react::ObjCTurboModule::InitParams &)params {
|
|
27
|
+
return std::make_shared<facebook::react::NativeCustomerIOLoggingSpecJSI>(params);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Validates Swift bridge is available before method calls
|
|
31
|
+
- (void)assertBridgeAvailable:(NSString *)context {
|
|
32
|
+
RCT_ASSERT_BRIDGE_AVAILABLE(self.swiftBridge, context);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
- (instancetype)init {
|
|
36
|
+
if (self = [super init]) {
|
|
37
|
+
// Use runtime class lookup to avoid import issues and circular dependencies
|
|
38
|
+
Class swiftClass = NSClassFromString(@"NativeCustomerIOLogging");
|
|
39
|
+
RCT_ASSERT_NOT_NIL(swiftClass, @"NativeCustomerIOLogging Swift class", @"during runtime lookup");
|
|
40
|
+
_swiftBridge = [[swiftClass alloc] init];
|
|
41
|
+
[self assertBridgeAvailable:@"creating NativeCustomerIOLogging Swift instance"];
|
|
42
|
+
|
|
43
|
+
// Set event emitter reference for new architecture
|
|
44
|
+
[_swiftBridge setEventEmitter:self];
|
|
45
|
+
}
|
|
46
|
+
return self;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Background initialization is fine since logs are ignored until listeners are attached
|
|
50
|
+
+ (BOOL)requiresMainQueueSetup {
|
|
51
|
+
return NO;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
- (void)initialize {
|
|
55
|
+
[self assertBridgeAvailable:@"during initialize"];
|
|
56
|
+
[_swiftBridge initialize];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
- (void)invalidate {
|
|
60
|
+
[self assertBridgeAvailable:@"during invalidate"];
|
|
61
|
+
[_swiftBridge invalidate];
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
- (void)addListener:(nonnull NSString *)eventName {
|
|
65
|
+
RCT_LEGACY_ARCH_WARNING(addListener);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
- (void)removeListeners:(double)count {
|
|
69
|
+
RCT_LEGACY_ARCH_WARNING(removeListeners);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
- (void)emitOnCioLogEvent:(NSDictionary *)value {
|
|
73
|
+
[super emitOnCioLogEvent:value];
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Export class factory function for React Native component registration
|
|
77
|
+
Class<RCTBridgeModule> NativeCustomerIOLoggingCls(void) {
|
|
78
|
+
return RCTNativeCustomerIOLogging.class;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
@end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import CioInternalCommon
|
|
2
|
+
import Foundation
|
|
3
|
+
import React
|
|
4
|
+
|
|
5
|
+
// Logging module for new React Native architecture (TurboModule)
|
|
6
|
+
@objc(NativeCustomerIOLogging)
|
|
7
|
+
public class NativeCustomerIOLogging: NSObject {
|
|
8
|
+
// Reference to the ObjC event emitter for new architecture (TurboModule)
|
|
9
|
+
private weak var objcEventEmitter: AnyObject?
|
|
10
|
+
private lazy var logEventCallback: (_ body: [String: Any]) -> Void = { [weak self] body in
|
|
11
|
+
self?.sendEvent(body: body)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// Set ObjC event emitter reference for new architecture
|
|
15
|
+
@objc
|
|
16
|
+
public func setEventEmitter(_ emitter: AnyObject) {
|
|
17
|
+
objcEventEmitter = emitter
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Initialize log dispatcher - called by React Native
|
|
21
|
+
@objc
|
|
22
|
+
public func initialize() {
|
|
23
|
+
// Initialize log dispatcher when module is ready
|
|
24
|
+
DIGraphShared.shared.logger.setLogDispatcher { [weak self] level, message in
|
|
25
|
+
guard let self else { return }
|
|
26
|
+
|
|
27
|
+
let body = [
|
|
28
|
+
"logLevel": level.rawValue,
|
|
29
|
+
"message": message
|
|
30
|
+
]
|
|
31
|
+
logEventCallback(body)
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Clear log dispatcher to prevent leaks - called by React Native
|
|
36
|
+
@objc
|
|
37
|
+
public func invalidate() {
|
|
38
|
+
// Clear log dispatcher to prevent leaks
|
|
39
|
+
clearLogEventListener()
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Clears the log dispatcher to prevent leaks when module is deallocated or invalidated
|
|
43
|
+
private func clearLogEventListener() {
|
|
44
|
+
DIGraphShared.shared.logger.setLogDispatcher(nil)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Send log event to React Native layer using ObjC event emitter
|
|
48
|
+
private func sendEvent(body: [String: Any]) {
|
|
49
|
+
guard let emitter = objcEventEmitter else {
|
|
50
|
+
assertionFailure("NativeCustomerIOLogging: ObjC event emitter is nil, cannot send log event")
|
|
51
|
+
return
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// New architecture: use injected ObjC event emitter from TurboModule
|
|
55
|
+
let selector = Selector(("emitOnCioLogEvent:"))
|
|
56
|
+
guard emitter.responds(to: selector) else {
|
|
57
|
+
assertionFailure("ObjC event emitter does not respond to selector: emitOnCioLogEvent:")
|
|
58
|
+
return
|
|
59
|
+
}
|
|
60
|
+
_ = emitter.perform(selector, with: body as NSDictionary)
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
#import "../utils/RCTCustomerIOUtils.h"
|
|
2
|
+
#import <React/RCTBridgeModule.h>
|
|
3
|
+
#import <RNZixflowSpec/RNZixflowSpec.h>
|
|
4
|
+
|
|
5
|
+
// Objective-C wrapper for new architecture TurboModule implementation
|
|
6
|
+
@interface RCTNativeMessagingPush : NSObject <NativeCustomerIOMessagingPushSpec>
|
|
7
|
+
// Bridge to Swift implementation for cross-language compatibility
|
|
8
|
+
@property(nonatomic, strong) id<NativeCustomerIOMessagingPushSpec> swiftBridge;
|
|
9
|
+
@end
|
|
10
|
+
|
|
11
|
+
@implementation RCTNativeMessagingPush
|
|
12
|
+
|
|
13
|
+
RCT_EXPORT_MODULE()
|
|
14
|
+
|
|
15
|
+
// Create TurboModule instance for new architecture JSI integration
|
|
16
|
+
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
|
|
17
|
+
(const facebook::react::ObjCTurboModule::InitParams &)params {
|
|
18
|
+
return std::make_shared<facebook::react::NativeCustomerIOMessagingPushSpecJSI>(params);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Validates Swift bridge is available before method calls
|
|
22
|
+
- (void)assertBridgeAvailable:(NSString *)context {
|
|
23
|
+
RCT_ASSERT_BRIDGE_AVAILABLE(self.swiftBridge, context);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
- (instancetype)init {
|
|
27
|
+
if (self = [super init]) {
|
|
28
|
+
// Use runtime class lookup to avoid import issues and circular dependencies
|
|
29
|
+
Class swiftClass = NSClassFromString(@"NativeMessagingPush");
|
|
30
|
+
RCT_ASSERT_NOT_NIL(swiftClass, @"NativeMessagingPush Swift class", @"during runtime lookup");
|
|
31
|
+
_swiftBridge = [[swiftClass alloc] init];
|
|
32
|
+
[self assertBridgeAvailable:@"creating NativeMessagingPush Swift instance"];
|
|
33
|
+
}
|
|
34
|
+
return self;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Module initialization can happen on background thread
|
|
38
|
+
+ (BOOL)requiresMainQueueSetup {
|
|
39
|
+
return NO;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
- (void)onMessageReceived:(NSDictionary *)message
|
|
43
|
+
handleNotificationTrigger:(BOOL)handleNotificationTrigger
|
|
44
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
45
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
46
|
+
[self assertBridgeAvailable:@"during handleMessage"];
|
|
47
|
+
[_swiftBridge onMessageReceived:message
|
|
48
|
+
handleNotificationTrigger:handleNotificationTrigger
|
|
49
|
+
resolve:resolve
|
|
50
|
+
reject:reject];
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
- (void)trackNotificationResponseReceived:(NSDictionary *)payload {
|
|
54
|
+
[self assertBridgeAvailable:@"during trackNotificationResponseReceived"];
|
|
55
|
+
[_swiftBridge trackNotificationResponseReceived:payload];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
- (void)trackNotificationReceived:(NSDictionary *)payload {
|
|
59
|
+
[self assertBridgeAvailable:@"during trackNotificationReceived"];
|
|
60
|
+
[_swiftBridge trackNotificationReceived:payload];
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
- (void)getRegisteredDeviceToken:(RCTPromiseResolveBlock)resolve
|
|
64
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
65
|
+
[self assertBridgeAvailable:@"during getRegisteredDeviceToken"];
|
|
66
|
+
[_swiftBridge getRegisteredDeviceToken:resolve reject:reject];
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
- (void)showPromptForPushNotifications:(NSDictionary *)options
|
|
70
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
71
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
72
|
+
[self assertBridgeAvailable:@"during showPromptForPushNotifications"];
|
|
73
|
+
[_swiftBridge showPromptForPushNotifications:options resolve:resolve reject:reject];
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
- (void)getPushPermissionStatus:(RCTPromiseResolveBlock)resolve
|
|
77
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
78
|
+
[self assertBridgeAvailable:@"during getPushPermissionStatus"];
|
|
79
|
+
[_swiftBridge getPushPermissionStatus:resolve reject:reject];
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Export class factory function for React Native component registration
|
|
83
|
+
Class<RCTBridgeModule> NativeCustomerIOMessagingPushCls(void) {
|
|
84
|
+
return RCTNativeMessagingPush.class;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
@end
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import CioInternalCommon
|
|
2
|
+
import CioMessagingPush
|
|
3
|
+
import Foundation
|
|
4
|
+
|
|
5
|
+
enum PushPermissionStatus: String, CaseIterable {
|
|
6
|
+
case denied
|
|
7
|
+
case notDetermined
|
|
8
|
+
case granted
|
|
9
|
+
|
|
10
|
+
var value: String {
|
|
11
|
+
rawValue.uppercased()
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
@objc(NativeMessagingPush)
|
|
16
|
+
public class NativeMessagingPush: NSObject {
|
|
17
|
+
private let logger: CioInternalCommon.Logger = DIGraphShared.shared.logger
|
|
18
|
+
|
|
19
|
+
@objc
|
|
20
|
+
public func onMessageReceived(
|
|
21
|
+
_ message: NSDictionary,
|
|
22
|
+
handleNotificationTrigger: Bool,
|
|
23
|
+
resolve: @escaping RCTPromiseResolveBlock,
|
|
24
|
+
reject: @escaping RCTPromiseRejectBlock
|
|
25
|
+
) {
|
|
26
|
+
Preconditions.unsupportedOnIOS(methodName: "onMessageReceived")
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Tracks `opened` push metrics when a push notification is interacted with.
|
|
30
|
+
@objc
|
|
31
|
+
public func trackNotificationResponseReceived(_ payload: NSDictionary) {
|
|
32
|
+
trackPushMetrics(payload: payload, event: .opened)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Tracks `delivered` push metrics when a push notification is received.
|
|
36
|
+
@objc
|
|
37
|
+
public func trackNotificationReceived(_ payload: NSDictionary) {
|
|
38
|
+
trackPushMetrics(payload: payload, event: .delivered)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Get the currently registered device token for the app
|
|
42
|
+
@objc(getRegisteredDeviceToken:reject:)
|
|
43
|
+
public func getRegisteredDeviceToken(resolve: @escaping (RCTPromiseResolveBlock), reject: @escaping (RCTPromiseRejectBlock)) {
|
|
44
|
+
guard let token = CustomerIO.shared.registeredDeviceToken else {
|
|
45
|
+
reject(CustomerioConstants.cioTag, CustomerioConstants.showDeviceTokenFailureError, nil)
|
|
46
|
+
return
|
|
47
|
+
}
|
|
48
|
+
resolve(token)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
private func trackPushMetrics(payload: NSDictionary, event: Metric) {
|
|
52
|
+
guard let deliveryId = payload[CustomerioConstants.CioDeliveryId] as? String,
|
|
53
|
+
let deviceToken = payload[CustomerioConstants.CioDeliveryToken] as? String
|
|
54
|
+
else { return }
|
|
55
|
+
|
|
56
|
+
MessagingPush.shared.trackMetric(deliveryID: deliveryId, event: event, deviceToken: deviceToken)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
@objc(showPromptForPushNotifications:resolve:reject:)
|
|
60
|
+
public func showPromptForPushNotifications(options: [String: AnyHashable], resolve: @escaping (RCTPromiseResolveBlock), reject: @escaping (RCTPromiseRejectBlock)) {
|
|
61
|
+
// Show prompt if status is not determined
|
|
62
|
+
getPushNotificationPermissionStatus { status in
|
|
63
|
+
if status == .notDetermined {
|
|
64
|
+
self.requestPushAuthorization(options: options) { permissionStatus in
|
|
65
|
+
guard let isGranted = permissionStatus as? Bool else {
|
|
66
|
+
reject(CustomerioConstants.cioTag, CustomerioConstants.showPromptFailureError, permissionStatus as? Error)
|
|
67
|
+
return
|
|
68
|
+
}
|
|
69
|
+
resolve(isGranted ? PushPermissionStatus.granted.value : PushPermissionStatus.denied.value)
|
|
70
|
+
}
|
|
71
|
+
} else {
|
|
72
|
+
resolve(status.value)
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
@objc(getPushPermissionStatus:reject:)
|
|
78
|
+
public func getPushPermissionStatus(resolve: @escaping (RCTPromiseResolveBlock), _: @escaping (RCTPromiseRejectBlock)) {
|
|
79
|
+
getPushNotificationPermissionStatus { status in
|
|
80
|
+
resolve(status.value)
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
private func requestPushAuthorization(options: [String: Any], onComplete: @escaping (Any) -> Void) {
|
|
85
|
+
let current = UNUserNotificationCenter.current()
|
|
86
|
+
var notificationOptions: UNAuthorizationOptions = [.alert]
|
|
87
|
+
if let ios = options[CustomerioConstants.platformiOS] as? [String: Any] {
|
|
88
|
+
if let soundOption = ios[CustomerioConstants.sound] as? Bool, soundOption {
|
|
89
|
+
notificationOptions.insert(.sound)
|
|
90
|
+
}
|
|
91
|
+
if let badgeOption = ios[CustomerioConstants.badge] as? Bool, badgeOption {
|
|
92
|
+
notificationOptions.insert(.badge)
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
current.requestAuthorization(options: notificationOptions) { isGranted, error in
|
|
96
|
+
if let error = error {
|
|
97
|
+
onComplete(error)
|
|
98
|
+
return
|
|
99
|
+
}
|
|
100
|
+
onComplete(isGranted)
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
private func getPushNotificationPermissionStatus(completionHandler: @escaping (PushPermissionStatus) -> Void) {
|
|
105
|
+
var status = PushPermissionStatus.notDetermined
|
|
106
|
+
let current = UNUserNotificationCenter.current()
|
|
107
|
+
current.getNotificationSettings(completionHandler: { permission in
|
|
108
|
+
switch permission.authorizationStatus {
|
|
109
|
+
case .authorized, .provisional, .ephemeral:
|
|
110
|
+
status = .granted
|
|
111
|
+
case .denied:
|
|
112
|
+
status = .denied
|
|
113
|
+
default:
|
|
114
|
+
status = .notDetermined
|
|
115
|
+
}
|
|
116
|
+
completionHandler(status)
|
|
117
|
+
})
|
|
118
|
+
}
|
|
119
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import CioDataPipelines
|
|
2
|
+
import CioInternalCommon
|
|
3
|
+
import CioMessagingInApp
|
|
4
|
+
|
|
5
|
+
enum SDKConfigBuilderError: Error {
|
|
6
|
+
case missingCdpApiKey
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
extension SDKConfigBuilder {
|
|
10
|
+
private enum Config: String {
|
|
11
|
+
case migrationSiteId
|
|
12
|
+
case cdpApiKey
|
|
13
|
+
case region
|
|
14
|
+
case logLevel
|
|
15
|
+
case apiHost
|
|
16
|
+
case cdnHost
|
|
17
|
+
case flushAt
|
|
18
|
+
case flushInterval
|
|
19
|
+
case screenViewUse
|
|
20
|
+
case trackApplicationLifecycleEvents
|
|
21
|
+
case autoTrackDeviceAttributes
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
@available(iOSApplicationExtension, unavailable)
|
|
25
|
+
static func create(from config: [String: Any?]) throws -> SDKConfigBuilder {
|
|
26
|
+
guard let cdpApiKey = config[Config.cdpApiKey.rawValue] as? String else {
|
|
27
|
+
throw SDKConfigBuilderError.missingCdpApiKey
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
let builder = SDKConfigBuilder(cdpApiKey: cdpApiKey)
|
|
31
|
+
Config.migrationSiteId.ifNotNil(in: config, thenPassItTo: builder.migrationSiteId)
|
|
32
|
+
Config.region.ifNotNil(in: config, thenPassItTo: builder.region, transformingBy: Region.getRegion)
|
|
33
|
+
Config.logLevel.ifNotNil(in: config, thenPassItTo: builder.logLevel, transformingBy: CioLogLevel.getLogLevel)
|
|
34
|
+
Config.flushAt.ifNotNil(in: config, thenPassItTo: builder.flushAt) { (value: Double) in Int(value) }
|
|
35
|
+
Config.flushInterval.ifNotNil(in: config, thenPassItTo: builder.flushInterval)
|
|
36
|
+
Config.screenViewUse.ifNotNil(in: config, thenPassItTo: builder.screenViewUse) { ScreenView.getScreenView($0) }
|
|
37
|
+
Config.trackApplicationLifecycleEvents.ifNotNil(in: config, thenPassItTo: builder.trackApplicationLifecycleEvents)
|
|
38
|
+
Config.autoTrackDeviceAttributes.ifNotNil(in: config, thenPassItTo: builder.autoTrackDeviceAttributes)
|
|
39
|
+
Config.apiHost.ifNotNil(in: config, thenPassItTo: builder.apiHost)
|
|
40
|
+
Config.cdnHost.ifNotNil(in: config, thenPassItTo: builder.cdnHost)
|
|
41
|
+
|
|
42
|
+
return builder
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
extension RawRepresentable where RawValue == String {
|
|
47
|
+
func ifNotNil<Raw>(
|
|
48
|
+
in config: [String: Any?]?,
|
|
49
|
+
thenPassItTo handler: (Raw) -> Any
|
|
50
|
+
) {
|
|
51
|
+
ifNotNil(in: config, thenPassItTo: handler) { $0 }
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
func ifNotNil<Raw, Transformed>(
|
|
55
|
+
in config: [String: Any?]?,
|
|
56
|
+
thenPassItTo handler: (Transformed) -> Any,
|
|
57
|
+
transformingBy transform: (Raw) -> Transformed?
|
|
58
|
+
) {
|
|
59
|
+
if let value = config?[rawValue] as? Raw, let result = transform(value) {
|
|
60
|
+
_ = handler(result)
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
enum CustomerioConstants {
|
|
2
|
+
// InApp Messaging
|
|
3
|
+
static let inAppEventListener = "InAppEventListener"
|
|
4
|
+
static let eventType = "eventType"
|
|
5
|
+
static let messageId = "messageId"
|
|
6
|
+
static let deliveryId = "deliveryId"
|
|
7
|
+
static let actionValue = "actionValue"
|
|
8
|
+
static let actionName = "actionName"
|
|
9
|
+
static let messageShown = "messageShown"
|
|
10
|
+
static let messageDismissed = "messageDismissed"
|
|
11
|
+
static let errorWithMessage = "errorWithMessage"
|
|
12
|
+
static let messageActionTaken = "messageActionTaken"
|
|
13
|
+
|
|
14
|
+
// Push Messaging
|
|
15
|
+
static let CioDeliveryId = "CIO-Delivery-ID"
|
|
16
|
+
static let CioDeliveryToken = "CIO-Delivery-Token"
|
|
17
|
+
static let showPromptFailureError = "Error requesting push notification permission."
|
|
18
|
+
static let showDeviceTokenFailureError = "Error fetching registered device token."
|
|
19
|
+
static let platformiOS = "ios"
|
|
20
|
+
static let sound = "sound"
|
|
21
|
+
static let badge = "badge"
|
|
22
|
+
|
|
23
|
+
// Logging
|
|
24
|
+
static let cioTag = "[CIO]"
|
|
25
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import CioInternalCommon
|
|
2
|
+
import Foundation
|
|
3
|
+
|
|
4
|
+
/// Preconditions and utility functions for React Native wrapper
|
|
5
|
+
public enum Preconditions {
|
|
6
|
+
/// Throws a runtime exception in debug builds and logs a warning in release builds if a method
|
|
7
|
+
/// that is only supported on Android is called from iOS.
|
|
8
|
+
///
|
|
9
|
+
/// Use this to guard any platform-specific methods that are not expected to called on iOS from TypeScript.
|
|
10
|
+
public static func unsupportedOnIOS(methodName: String) {
|
|
11
|
+
let message = "'\(methodName)' is unsupported on iOS and should not be called."
|
|
12
|
+
|
|
13
|
+
#if DEBUG
|
|
14
|
+
fatalError(message)
|
|
15
|
+
#else
|
|
16
|
+
let logger = DIGraphShared.shared.logger
|
|
17
|
+
logger.error(message)
|
|
18
|
+
#endif
|
|
19
|
+
}
|
|
20
|
+
}
|