zixflow-reactnative 1.1.3 → 1.1.5

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.
Files changed (239) hide show
  1. package/README.md +631 -261
  2. package/android/build.gradle +18 -1
  3. package/android/consumer-rules.pro +3 -2
  4. package/android/gradle.properties +1 -1
  5. package/android/src/main/java/com/zixflow/reactnative/sdk/NativeZixflowModule.kt +41 -5
  6. package/android/src/main/java/com/zixflow/reactnative/sdk/ZixflowReactNativePackage.kt +25 -1
  7. package/android/src/main/java/com/zixflow/reactnative/sdk/constant/Keys.kt +19 -0
  8. package/android/src/main/java/com/zixflow/reactnative/sdk/geofence/NativeGeofenceModule.kt +65 -0
  9. package/android/src/main/java/com/zixflow/reactnative/sdk/liveactivities/NativeLiveActivitiesModule.kt +310 -0
  10. package/android/src/main/java/com/zixflow/reactnative/sdk/messaginginapp/NativeMessagingInAppModule.kt +150 -0
  11. package/android/src/main/java/com/zixflow/reactnative/sdk/messaginginapp/ReactInboxEventListener.kt +99 -0
  12. package/android/src/main/java/com/zixflow/reactnative/sdk/messaginginbox/NotificationInboxBellViewManager.kt +38 -0
  13. package/android/src/main/java/com/zixflow/reactnative/sdk/messaginginbox/NotificationInboxViewManager.kt +30 -0
  14. package/android/src/main/java/com/zixflow/reactnative/sdk/messaginginbox/ReactComposeHostView.kt +96 -0
  15. package/android/src/main/java/com/zixflow/reactnative/sdk/messaginginbox/ReactNotificationInboxBellView.kt +48 -0
  16. package/android/src/main/java/com/zixflow/reactnative/sdk/messaginginbox/ReactNotificationInboxView.kt +17 -0
  17. package/android/src/main/java/com/zixflow/reactnative/sdk/messagingpush/NativeMessagingPushModule.kt +11 -1
  18. package/android/src/main/res/values/zixflow_config.xml +1 -1
  19. package/android/zixflow-core.gradle +15 -2
  20. package/docs/cocoapods-deployment-target-normalization.md +139 -0
  21. package/ios/cocoapods_deployment_target.rb +432 -0
  22. package/ios/wrappers/NativeZixflow.mm +37 -0
  23. package/ios/wrappers/NativeZixflow.swift +135 -1
  24. package/ios/wrappers/ZixflowReactNativeDeepLinkRequestStore.swift +123 -0
  25. package/ios/wrappers/ZixflowReactNativeDeepLinkRouter.swift +312 -0
  26. package/ios/wrappers/geofence/NativeGeofence.mm +46 -0
  27. package/ios/wrappers/geofence/NativeGeofence.swift +27 -0
  28. package/ios/wrappers/inapp/NativeMessagingInApp.mm +22 -0
  29. package/ios/wrappers/inapp/NativeMessagingInApp.swift +91 -0
  30. package/ios/wrappers/inbox/InboxHostContainment.swift +40 -0
  31. package/ios/wrappers/inbox/RCTNotificationInboxBellNative.h +12 -0
  32. package/ios/wrappers/inbox/RCTNotificationInboxBellNative.mm +98 -0
  33. package/ios/wrappers/inbox/RCTNotificationInboxViewNative.h +12 -0
  34. package/ios/wrappers/inbox/RCTNotificationInboxViewNative.mm +78 -0
  35. package/ios/wrappers/inbox/ReactInboxEventListener.swift +76 -0
  36. package/ios/wrappers/inbox/ReactNotificationInboxBellView.h +22 -0
  37. package/ios/wrappers/inbox/ReactNotificationInboxBellView.swift +109 -0
  38. package/ios/wrappers/inbox/ReactNotificationInboxView.h +22 -0
  39. package/ios/wrappers/inbox/ReactNotificationInboxView.swift +69 -0
  40. package/ios/wrappers/liveactivities/NativeLiveActivities.mm +83 -0
  41. package/ios/wrappers/liveactivities/NativeLiveActivities.swift +390 -0
  42. package/ios/wrappers/location/NativeLocation.swift +7 -5
  43. package/ios/wrappers/utils/ZixflowConstants.swift +4 -0
  44. package/ios/wrappers/zixflow_reactnative.h +6 -0
  45. package/lib/commonjs/components/NotificationInboxBellView.js +49 -0
  46. package/lib/commonjs/components/NotificationInboxBellView.js.map +1 -0
  47. package/lib/commonjs/components/NotificationInboxView.js +36 -0
  48. package/lib/commonjs/components/NotificationInboxView.js.map +1 -0
  49. package/lib/commonjs/components/index.js +14 -0
  50. package/lib/commonjs/components/index.js.map +1 -1
  51. package/lib/commonjs/index.js +81 -4
  52. package/lib/commonjs/index.js.map +1 -1
  53. package/lib/commonjs/notification-inbox.js +1 -0
  54. package/lib/commonjs/notification-inbox.js.map +1 -1
  55. package/lib/commonjs/specs/components/NotificationInboxBellNativeComponent.ts +24 -0
  56. package/lib/commonjs/specs/components/NotificationInboxViewNativeComponent.ts +22 -0
  57. package/lib/commonjs/specs/modules/NativeZixflow.js.map +1 -1
  58. package/lib/commonjs/specs/modules/NativeZixflowGeofence.js +15 -0
  59. package/lib/commonjs/specs/modules/NativeZixflowGeofence.js.map +1 -0
  60. package/lib/commonjs/specs/modules/NativeZixflowLiveActivities.js +23 -0
  61. package/lib/commonjs/specs/modules/NativeZixflowLiveActivities.js.map +1 -0
  62. package/lib/commonjs/specs/modules/NativeZixflowMessagingInApp.js +3 -1
  63. package/lib/commonjs/specs/modules/NativeZixflowMessagingInApp.js.map +1 -1
  64. package/lib/commonjs/specs/modules/NativeZixflowMessagingPush.js +3 -1
  65. package/lib/commonjs/specs/modules/NativeZixflowMessagingPush.js.map +1 -1
  66. package/lib/commonjs/types/data-pipelines.js +13 -1
  67. package/lib/commonjs/types/data-pipelines.js.map +1 -1
  68. package/lib/commonjs/types/in-app.js +24 -1
  69. package/lib/commonjs/types/in-app.js.map +1 -1
  70. package/lib/commonjs/types/inbox.js +79 -0
  71. package/lib/commonjs/types/inbox.js.map +1 -0
  72. package/lib/commonjs/types/index.js +22 -0
  73. package/lib/commonjs/types/index.js.map +1 -1
  74. package/lib/commonjs/types/live-activities.js +85 -0
  75. package/lib/commonjs/types/live-activities.js.map +1 -0
  76. package/lib/commonjs/utils/param-validation.js +76 -1
  77. package/lib/commonjs/utils/param-validation.js.map +1 -1
  78. package/lib/commonjs/zixflow-cdp.js +99 -1
  79. package/lib/commonjs/zixflow-cdp.js.map +1 -1
  80. package/lib/commonjs/zixflow-geofence.js +55 -0
  81. package/lib/commonjs/zixflow-geofence.js.map +1 -0
  82. package/lib/commonjs/zixflow-inapp.js +120 -0
  83. package/lib/commonjs/zixflow-inapp.js.map +1 -1
  84. package/lib/commonjs/zixflow-liveactivities.js +85 -0
  85. package/lib/commonjs/zixflow-liveactivities.js.map +1 -0
  86. package/lib/module/components/NotificationInboxBellView.js +44 -0
  87. package/lib/module/components/NotificationInboxBellView.js.map +1 -0
  88. package/lib/module/components/NotificationInboxView.js +31 -0
  89. package/lib/module/components/NotificationInboxView.js.map +1 -0
  90. package/lib/module/components/index.js +5 -0
  91. package/lib/module/components/index.js.map +1 -1
  92. package/lib/module/index.js +8 -3
  93. package/lib/module/index.js.map +1 -1
  94. package/lib/module/notification-inbox.js +1 -1
  95. package/lib/module/notification-inbox.js.map +1 -1
  96. package/lib/module/specs/components/NotificationInboxBellNativeComponent.ts +24 -0
  97. package/lib/module/specs/components/NotificationInboxViewNativeComponent.ts +22 -0
  98. package/lib/module/specs/modules/NativeZixflow.js.map +1 -1
  99. package/lib/module/specs/modules/NativeZixflowGeofence.js +13 -0
  100. package/lib/module/specs/modules/NativeZixflowGeofence.js.map +1 -0
  101. package/lib/module/specs/modules/NativeZixflowLiveActivities.js +21 -0
  102. package/lib/module/specs/modules/NativeZixflowLiveActivities.js.map +1 -0
  103. package/lib/module/specs/modules/NativeZixflowMessagingInApp.js +3 -1
  104. package/lib/module/specs/modules/NativeZixflowMessagingInApp.js.map +1 -1
  105. package/lib/module/specs/modules/NativeZixflowMessagingPush.js +3 -1
  106. package/lib/module/specs/modules/NativeZixflowMessagingPush.js.map +1 -1
  107. package/lib/module/types/data-pipelines.js +13 -0
  108. package/lib/module/types/data-pipelines.js.map +1 -1
  109. package/lib/module/types/in-app.js +24 -0
  110. package/lib/module/types/in-app.js.map +1 -1
  111. package/lib/module/types/inbox.js +75 -0
  112. package/lib/module/types/inbox.js.map +1 -0
  113. package/lib/module/types/index.js +2 -0
  114. package/lib/module/types/index.js.map +1 -1
  115. package/lib/module/types/live-activities.js +88 -0
  116. package/lib/module/types/live-activities.js.map +1 -0
  117. package/lib/module/utils/param-validation.js +76 -1
  118. package/lib/module/utils/param-validation.js.map +1 -1
  119. package/lib/module/zixflow-cdp.js +99 -1
  120. package/lib/module/zixflow-cdp.js.map +1 -1
  121. package/lib/module/zixflow-geofence.js +50 -0
  122. package/lib/module/zixflow-geofence.js.map +1 -0
  123. package/lib/module/zixflow-inapp.js +99 -1
  124. package/lib/module/zixflow-inapp.js.map +1 -1
  125. package/lib/module/zixflow-liveactivities.js +80 -0
  126. package/lib/module/zixflow-liveactivities.js.map +1 -0
  127. package/lib/typescript/commonjs/components/NotificationInboxBellView.d.ts +39 -0
  128. package/lib/typescript/commonjs/components/NotificationInboxBellView.d.ts.map +1 -0
  129. package/lib/typescript/commonjs/components/NotificationInboxView.d.ts +25 -0
  130. package/lib/typescript/commonjs/components/NotificationInboxView.d.ts.map +1 -0
  131. package/lib/typescript/commonjs/components/index.d.ts +4 -0
  132. package/lib/typescript/commonjs/components/index.d.ts.map +1 -1
  133. package/lib/typescript/commonjs/index.d.ts +8 -1
  134. package/lib/typescript/commonjs/index.d.ts.map +1 -1
  135. package/lib/typescript/commonjs/notification-inbox.d.ts +5 -0
  136. package/lib/typescript/commonjs/notification-inbox.d.ts.map +1 -1
  137. package/lib/typescript/commonjs/specs/components/NotificationInboxBellNativeComponent.d.ts +13 -0
  138. package/lib/typescript/commonjs/specs/components/NotificationInboxBellNativeComponent.d.ts.map +1 -0
  139. package/lib/typescript/commonjs/specs/components/NotificationInboxViewNativeComponent.d.ts +12 -0
  140. package/lib/typescript/commonjs/specs/components/NotificationInboxViewNativeComponent.d.ts.map +1 -0
  141. package/lib/typescript/commonjs/specs/modules/NativeZixflow.d.ts +6 -1
  142. package/lib/typescript/commonjs/specs/modules/NativeZixflow.d.ts.map +1 -1
  143. package/lib/typescript/commonjs/specs/modules/NativeZixflowGeofence.d.ts +13 -0
  144. package/lib/typescript/commonjs/specs/modules/NativeZixflowGeofence.d.ts.map +1 -0
  145. package/lib/typescript/commonjs/specs/modules/NativeZixflowLiveActivities.d.ts +31 -0
  146. package/lib/typescript/commonjs/specs/modules/NativeZixflowLiveActivities.d.ts.map +1 -0
  147. package/lib/typescript/commonjs/specs/modules/NativeZixflowMessagingInApp.d.ts +5 -1
  148. package/lib/typescript/commonjs/specs/modules/NativeZixflowMessagingInApp.d.ts.map +1 -1
  149. package/lib/typescript/commonjs/specs/modules/NativeZixflowMessagingPush.d.ts +1 -1
  150. package/lib/typescript/commonjs/specs/modules/NativeZixflowMessagingPush.d.ts.map +1 -1
  151. package/lib/typescript/commonjs/types/data-pipelines.d.ts +53 -1
  152. package/lib/typescript/commonjs/types/data-pipelines.d.ts.map +1 -1
  153. package/lib/typescript/commonjs/types/in-app.d.ts +22 -0
  154. package/lib/typescript/commonjs/types/in-app.d.ts.map +1 -1
  155. package/lib/typescript/commonjs/types/inbox.d.ts +97 -0
  156. package/lib/typescript/commonjs/types/inbox.d.ts.map +1 -0
  157. package/lib/typescript/commonjs/types/index.d.ts +2 -0
  158. package/lib/typescript/commonjs/types/index.d.ts.map +1 -1
  159. package/lib/typescript/commonjs/types/live-activities.d.ts +161 -0
  160. package/lib/typescript/commonjs/types/live-activities.d.ts.map +1 -0
  161. package/lib/typescript/commonjs/utils/param-validation.d.ts +7 -0
  162. package/lib/typescript/commonjs/utils/param-validation.d.ts.map +1 -1
  163. package/lib/typescript/commonjs/zixflow-cdp.d.ts +38 -0
  164. package/lib/typescript/commonjs/zixflow-cdp.d.ts.map +1 -1
  165. package/lib/typescript/commonjs/zixflow-geofence.d.ts +36 -0
  166. package/lib/typescript/commonjs/zixflow-geofence.d.ts.map +1 -0
  167. package/lib/typescript/commonjs/zixflow-inapp.d.ts +36 -2
  168. package/lib/typescript/commonjs/zixflow-inapp.d.ts.map +1 -1
  169. package/lib/typescript/commonjs/zixflow-liveactivities.d.ts +66 -0
  170. package/lib/typescript/commonjs/zixflow-liveactivities.d.ts.map +1 -0
  171. package/lib/typescript/module/components/NotificationInboxBellView.d.ts +39 -0
  172. package/lib/typescript/module/components/NotificationInboxBellView.d.ts.map +1 -0
  173. package/lib/typescript/module/components/NotificationInboxView.d.ts +25 -0
  174. package/lib/typescript/module/components/NotificationInboxView.d.ts.map +1 -0
  175. package/lib/typescript/module/components/index.d.ts +4 -0
  176. package/lib/typescript/module/components/index.d.ts.map +1 -1
  177. package/lib/typescript/module/index.d.ts +8 -1
  178. package/lib/typescript/module/index.d.ts.map +1 -1
  179. package/lib/typescript/module/notification-inbox.d.ts +5 -0
  180. package/lib/typescript/module/notification-inbox.d.ts.map +1 -1
  181. package/lib/typescript/module/specs/components/NotificationInboxBellNativeComponent.d.ts +13 -0
  182. package/lib/typescript/module/specs/components/NotificationInboxBellNativeComponent.d.ts.map +1 -0
  183. package/lib/typescript/module/specs/components/NotificationInboxViewNativeComponent.d.ts +12 -0
  184. package/lib/typescript/module/specs/components/NotificationInboxViewNativeComponent.d.ts.map +1 -0
  185. package/lib/typescript/module/specs/modules/NativeZixflow.d.ts +6 -1
  186. package/lib/typescript/module/specs/modules/NativeZixflow.d.ts.map +1 -1
  187. package/lib/typescript/module/specs/modules/NativeZixflowGeofence.d.ts +13 -0
  188. package/lib/typescript/module/specs/modules/NativeZixflowGeofence.d.ts.map +1 -0
  189. package/lib/typescript/module/specs/modules/NativeZixflowLiveActivities.d.ts +31 -0
  190. package/lib/typescript/module/specs/modules/NativeZixflowLiveActivities.d.ts.map +1 -0
  191. package/lib/typescript/module/specs/modules/NativeZixflowMessagingInApp.d.ts +5 -1
  192. package/lib/typescript/module/specs/modules/NativeZixflowMessagingInApp.d.ts.map +1 -1
  193. package/lib/typescript/module/specs/modules/NativeZixflowMessagingPush.d.ts +1 -1
  194. package/lib/typescript/module/specs/modules/NativeZixflowMessagingPush.d.ts.map +1 -1
  195. package/lib/typescript/module/types/data-pipelines.d.ts +53 -1
  196. package/lib/typescript/module/types/data-pipelines.d.ts.map +1 -1
  197. package/lib/typescript/module/types/in-app.d.ts +22 -0
  198. package/lib/typescript/module/types/in-app.d.ts.map +1 -1
  199. package/lib/typescript/module/types/inbox.d.ts +97 -0
  200. package/lib/typescript/module/types/inbox.d.ts.map +1 -0
  201. package/lib/typescript/module/types/index.d.ts +2 -0
  202. package/lib/typescript/module/types/index.d.ts.map +1 -1
  203. package/lib/typescript/module/types/live-activities.d.ts +161 -0
  204. package/lib/typescript/module/types/live-activities.d.ts.map +1 -0
  205. package/lib/typescript/module/utils/param-validation.d.ts +7 -0
  206. package/lib/typescript/module/utils/param-validation.d.ts.map +1 -1
  207. package/lib/typescript/module/zixflow-cdp.d.ts +38 -0
  208. package/lib/typescript/module/zixflow-cdp.d.ts.map +1 -1
  209. package/lib/typescript/module/zixflow-geofence.d.ts +36 -0
  210. package/lib/typescript/module/zixflow-geofence.d.ts.map +1 -0
  211. package/lib/typescript/module/zixflow-inapp.d.ts +36 -2
  212. package/lib/typescript/module/zixflow-inapp.d.ts.map +1 -1
  213. package/lib/typescript/module/zixflow-liveactivities.d.ts +66 -0
  214. package/lib/typescript/module/zixflow-liveactivities.d.ts.map +1 -0
  215. package/package.json +11 -2
  216. package/src/components/NotificationInboxBellView.tsx +55 -0
  217. package/src/components/NotificationInboxView.tsx +30 -0
  218. package/src/components/index.ts +6 -0
  219. package/src/index.ts +8 -3
  220. package/src/notification-inbox.ts +1 -1
  221. package/src/specs/components/NotificationInboxBellNativeComponent.ts +24 -0
  222. package/src/specs/components/NotificationInboxViewNativeComponent.ts +22 -0
  223. package/src/specs/modules/NativeZixflow.ts +9 -1
  224. package/src/specs/modules/NativeZixflowGeofence.ts +14 -0
  225. package/src/specs/modules/NativeZixflowLiveActivities.ts +39 -0
  226. package/src/specs/modules/NativeZixflowMessagingInApp.ts +12 -1
  227. package/src/specs/modules/NativeZixflowMessagingPush.ts +3 -1
  228. package/src/types/data-pipelines.ts +54 -1
  229. package/src/types/in-app.ts +23 -0
  230. package/src/types/inbox.ts +110 -0
  231. package/src/types/index.ts +2 -0
  232. package/src/types/live-activities.ts +170 -0
  233. package/src/utils/param-validation.ts +103 -0
  234. package/src/zixflow-cdp.ts +117 -1
  235. package/src/zixflow-geofence.ts +56 -0
  236. package/src/zixflow-inapp.ts +125 -2
  237. package/src/zixflow-liveactivities.ts +86 -0
  238. package/zixflow-reactnative-richpush.podspec +4 -1
  239. package/zixflow-reactnative.podspec +26 -0
@@ -10,12 +10,17 @@ import com.zixflow.messaginginapp.di.inAppMessaging
10
10
  import com.zixflow.messaginginapp.gist.data.model.InboxMessage
11
11
  import com.zixflow.messaginginapp.gist.data.model.response.InboxMessageFactory
12
12
  import com.zixflow.messaginginapp.inbox.NotificationInbox
13
+ import com.zixflow.messaginginapp.type.ColorScheme
14
+ import com.zixflow.messaginginapp.type.NotificationInboxAccessibilityLabels
13
15
  import com.zixflow.reactnative.sdk.NativeZixflowMessagingInAppSpec
16
+ import com.zixflow.reactnative.sdk.constant.Keys
17
+ import com.zixflow.reactnative.sdk.extension.getTypedValue
14
18
  import com.zixflow.reactnative.sdk.extension.toMap
15
19
  import com.zixflow.sdk.Zixflow
16
20
  import com.zixflow.sdk.ZixflowBuilder
17
21
  import com.zixflow.sdk.core.di.SDKComponent
18
22
  import com.zixflow.sdk.core.util.Logger
23
+ import com.zixflow.sdk.data.model.Region
19
24
 
20
25
  /**
21
26
  * React Native module implementation for Zixflow In-App Messaging Native SDK
@@ -30,6 +35,7 @@ class NativeMessagingInAppModule(
30
35
 
31
36
  private val inAppEventListener = ReactInAppEventListener.instance
32
37
  private val inboxChangeListener = ReactNotificationInboxChangeListener.instance
38
+ private val inboxEventListener = ReactInboxEventListener.instance
33
39
 
34
40
  // Dedicated lock for inbox listener setup to avoid blocking other operations
35
41
  private val inboxListenerLock = Any()
@@ -60,6 +66,7 @@ class NativeMessagingInAppModule(
60
66
  override fun invalidate() {
61
67
  inAppEventListener.clearEventEmitter()
62
68
  clearInboxChangeListener()
69
+ clearInboxEventListener()
63
70
  super.invalidate()
64
71
  }
65
72
 
@@ -67,10 +74,76 @@ class NativeMessagingInAppModule(
67
74
  inAppMessagingModule?.dismissMessage()
68
75
  }
69
76
 
77
+ // Nullable like every other argument-taking override here, and for the same reason: Codegen
78
+ // declares the parameter non-null, so a non-null Kotlin type would throw
79
+ // `Intrinsics.checkNotNullParameter` before the body runs when JavaScript passes null — which
80
+ // is what an untyped caller reading a stored theme sends on first launch.
81
+ override fun setColorScheme(colorScheme: String?) {
82
+ val resolved = colorSchemeFromRawValue(colorScheme)
83
+ if (resolved == null) {
84
+ // Leave the current scheme alone rather than resetting it to AUTO, so a bad value
85
+ // cannot quietly undo a scheme the app set correctly earlier.
86
+ logger.error(
87
+ "Unrecognized in-app colorScheme '$colorScheme', expected one of auto, light, " +
88
+ "dark. Leaving the color scheme unchanged."
89
+ )
90
+ return
91
+ }
92
+ val module = inAppMessagingModule
93
+ if (module == null) {
94
+ // Reachable when the host calls this before Zixflow.initialize, or without the
95
+ // in-app module configured. Logged rather than ignored: the scheme is silently not
96
+ // applied, and nothing else surfaces that.
97
+ logger.error(
98
+ "In-app messaging is not available, so the color scheme was not applied. " +
99
+ "Ensure Zixflow SDK is initialized with the inApp configuration."
100
+ )
101
+ return
102
+ }
103
+ module.setColorScheme(resolved)
104
+ }
105
+
70
106
  override fun setupInboxListener() {
71
107
  setupInboxChangeListener()
72
108
  }
73
109
 
110
+ /**
111
+ * Registers the native inbox event forwarder with the SDK and wires it to the React Native
112
+ * event emitter. Called when a JS inbox event listener is registered.
113
+ */
114
+ override fun registerInboxEventListener() {
115
+ inboxEventListener.setEventEmitter { data ->
116
+ emitOnInboxEventReceived(data)
117
+ }
118
+ val module = inAppMessagingModule
119
+ if (module == null) {
120
+ // Without this the failure is invisible: the JS subscription reports success while the SDK
121
+ // never forwards anything, so inbox callbacks silently never arrive. Matches the guidance
122
+ // used by getMessages() for the same situation.
123
+ logger.error(
124
+ "Cannot register inbox event listener: in-app messaging is not available. " +
125
+ "Ensure Zixflow SDK is initialized before registering the listener."
126
+ )
127
+ return
128
+ }
129
+ module.setInboxEventListener(inboxEventListener)
130
+ }
131
+
132
+ /**
133
+ * Unregisters the native inbox event forwarder by installing a no-op listener (the native API is
134
+ * non-null), restoring the SDK's default action handling. Called when the JS inbox event
135
+ * listener is removed.
136
+ */
137
+ override fun unregisterInboxEventListener() {
138
+ inAppMessagingModule?.setInboxEventListener(NoOpInboxEventListener)
139
+ inboxEventListener.clearEventEmitter()
140
+ }
141
+
142
+ private fun clearInboxEventListener() {
143
+ inAppMessagingModule?.setInboxEventListener(NoOpInboxEventListener)
144
+ inboxEventListener.clearEventEmitter()
145
+ }
146
+
74
147
  override fun getMessages(topic: String?, promise: Promise?) {
75
148
  try {
76
149
  val inbox = requireInboxInstance() ?: run {
@@ -196,9 +269,86 @@ class NativeMessagingInAppModule(
196
269
  val module = ModuleMessagingInApp(
197
270
  MessagingInAppModuleConfig.Builder().apply {
198
271
  setEventListener(eventListener = ReactInAppEventListener.instance)
272
+ colorSchemeFromConfig(config)?.let { colorScheme ->
273
+ setColorScheme(colorScheme)
274
+ }
275
+ inboxAccessibilityLabelsFromConfig(config)?.let { labels ->
276
+ setNotificationInboxAccessibilityLabels(labels)
277
+ }
199
278
  }.build(),
200
279
  )
201
280
  builder.addZixflowModule(module)
202
281
  }
282
+
283
+ /**
284
+ * Maps the wrapper's `colorScheme` value onto the native [ColorScheme], or null when the
285
+ * value is absent or unrecognized.
286
+ *
287
+ * The accepted values are lowercase because that is the wire contract the JavaScript
288
+ * `ZixflowColorScheme` enum serializes to and the one iOS already matches. Kept free of
289
+ * logging so each caller can report a bad value in its own terms: at initialization an
290
+ * unrecognized value falls back to AUTO, while the runtime setter leaves the scheme the
291
+ * app already chose untouched.
292
+ */
293
+ internal fun colorSchemeFromRawValue(rawValue: String?): ColorScheme? = when (rawValue) {
294
+ "auto" -> ColorScheme.AUTO
295
+ "light" -> ColorScheme.LIGHT
296
+ "dark" -> ColorScheme.DARK
297
+ else -> null
298
+ }
299
+
300
+ private fun colorSchemeFromConfig(config: Map<String, Any>): ColorScheme? {
301
+ // Absent is not a mistake — the SDK's own AUTO default stands — so only a value the
302
+ // host actually provided is worth reporting.
303
+ val rawValue = config.getTypedValue<String>(Keys.Config.COLOR_SCHEME) ?: return null
304
+
305
+ return colorSchemeFromRawValue(rawValue).also { resolved ->
306
+ if (resolved == null) {
307
+ SDKComponent.logger.error(
308
+ "Unrecognized in-app colorScheme '$rawValue', expected one of auto, " +
309
+ "light, dark. Falling back to the device appearance."
310
+ )
311
+ }
312
+ }
313
+ }
314
+
315
+ /**
316
+ * Builds the host's inbox accessibility labels from the wrapper configuration, or null when
317
+ * the app provided none — in which case the SDK keeps its default of emitting no labels at
318
+ * all rather than falling back to English.
319
+ *
320
+ * `bellWithUnreadCount` arrives as a template string because the bridge carries data but not
321
+ * functions; it is converted here into the `(Int) -> String` the native SDK expects. A
322
+ * template without the placeholder is returned verbatim for every count; the JavaScript
323
+ * layer warns about that case, where the developer can actually see it.
324
+ */
325
+ private fun inboxAccessibilityLabelsFromConfig(
326
+ config: Map<String, Any>
327
+ ): NotificationInboxAccessibilityLabels? {
328
+ val labels = config.getTypedValue<Map<String, Any>>(
329
+ Keys.Config.NOTIFICATION_INBOX_ACCESSIBILITY_LABELS
330
+ ) ?: return null
331
+
332
+ val unreadCountTemplate = labels.getTypedValue<String>(
333
+ Keys.InboxAccessibilityLabels.BELL_WITH_UNREAD_COUNT
334
+ )
335
+ return NotificationInboxAccessibilityLabels(
336
+ bell = labels.getTypedValue<String>(Keys.InboxAccessibilityLabels.BELL),
337
+ bellWithUnreadCount = unreadCountTemplate?.let { template ->
338
+ { count: Int ->
339
+ template.replace(
340
+ Keys.InboxAccessibilityLabels.COUNT_PLACEHOLDER,
341
+ count.toString()
342
+ )
343
+ }
344
+ },
345
+ loadingIndicator = labels.getTypedValue<String>(
346
+ Keys.InboxAccessibilityLabels.LOADING_INDICATOR
347
+ ),
348
+ emptyState = labels.getTypedValue<String>(
349
+ Keys.InboxAccessibilityLabels.EMPTY_STATE
350
+ )
351
+ )
352
+ }
203
353
  }
204
354
  }
@@ -0,0 +1,99 @@
1
+ package com.zixflow.reactnative.sdk.messaginginapp
2
+
3
+ import com.facebook.react.bridge.Arguments
4
+ import com.facebook.react.bridge.ReadableMap
5
+ import com.zixflow.messaginginapp.gist.data.model.InboxMessage
6
+ import com.zixflow.messaginginapp.type.InboxEventListener
7
+
8
+ /**
9
+ * React Native bridge for Zixflow Visual Notification Inbox events.
10
+ *
11
+ * Registered on the SDK (via [com.zixflow.messaginginapp.ModuleMessagingInApp.setInboxEventListener])
12
+ * only while a JS listener is registered. Because the New-Arch event emitter is one-way we cannot
13
+ * round-trip a bool back from JS, so [messageActionTaken] forwards the event fire-and-forget and
14
+ * RETURNS `true` — telling the SDK the host handled the action so the SDK suppresses its default
15
+ * navigation. The JS host owns action handling while a listener is registered. Observational
16
+ * callbacks forward fire-and-forget.
17
+ */
18
+ class ReactInboxEventListener private constructor() : InboxEventListener {
19
+ // Event emitter function to send events to React Native layer
20
+ private var eventEmitter: ((ReadableMap) -> Unit)? = null
21
+
22
+ // Sets the event emitter function
23
+ internal fun setEventEmitter(emitter: ((ReadableMap) -> Unit)?) {
24
+ this.eventEmitter = emitter
25
+ }
26
+
27
+ // Clears the event emitter to prevent memory leaks
28
+ internal fun clearEventEmitter() {
29
+ this.eventEmitter = null
30
+ }
31
+
32
+ // Emits an inbox message event to React Native with a serialized message payload
33
+ private fun emitInboxEvent(
34
+ eventType: String,
35
+ message: InboxMessage,
36
+ actionName: String? = null,
37
+ actionValue: String? = null,
38
+ ) {
39
+ // Get the emitter, return early if not set
40
+ val emitter = eventEmitter ?: return
41
+
42
+ val data = Arguments.createMap().apply {
43
+ putString("eventType", eventType)
44
+ putMap("message", message.toWritableMap())
45
+ actionName?.let { putString("actionName", it) }
46
+ actionValue?.let { putString("actionValue", it) }
47
+ }
48
+
49
+ emitter.invoke(data)
50
+ }
51
+
52
+ override fun messageActionTaken(
53
+ message: InboxMessage,
54
+ actionName: String,
55
+ actionValue: String,
56
+ ): Boolean {
57
+ emitInboxEvent(
58
+ eventType = "messageActionTaken",
59
+ message = message,
60
+ actionName = actionName,
61
+ actionValue = actionValue,
62
+ )
63
+ // Host (React Native) owns action handling while a listener is registered.
64
+ return true
65
+ }
66
+
67
+ override fun messageShown(message: InboxMessage) = emitInboxEvent(
68
+ eventType = "messageShown",
69
+ message = message,
70
+ )
71
+
72
+ override fun messageOpened(message: InboxMessage) = emitInboxEvent(
73
+ eventType = "messageOpened",
74
+ message = message,
75
+ )
76
+
77
+ override fun messageDismissed(message: InboxMessage) = emitInboxEvent(
78
+ eventType = "messageDismissed",
79
+ message = message,
80
+ )
81
+
82
+ companion object {
83
+ // Singleton instance with public visibility for direct access by Expo plugin
84
+ val instance: ReactInboxEventListener by lazy { ReactInboxEventListener() }
85
+ }
86
+ }
87
+
88
+ /**
89
+ * No-op inbox listener used to clear the forwarder from the SDK. Returning `false` from
90
+ * [messageActionTaken] restores the SDK's default action handling. The native
91
+ * `setInboxEventListener` API is non-null, so a no-op is installed rather than clearing.
92
+ */
93
+ internal object NoOpInboxEventListener : InboxEventListener {
94
+ override fun messageActionTaken(
95
+ message: InboxMessage,
96
+ actionName: String,
97
+ actionValue: String,
98
+ ): Boolean = false
99
+ }
@@ -0,0 +1,38 @@
1
+ package com.zixflow.reactnative.sdk.messaginginbox
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.viewmanagers.NotificationInboxBellNativeManagerDelegate
8
+ import com.facebook.react.viewmanagers.NotificationInboxBellNativeManagerInterface
9
+
10
+ /**
11
+ * View manager for the Visual Notification Inbox bell (just the bell; host opens its own UI).
12
+ *
13
+ * Registers the `onTap` direct event so taps reach the JS wrapper.
14
+ */
15
+ @ReactModule(name = NotificationInboxBellViewManager.NAME)
16
+ class NotificationInboxBellViewManager :
17
+ NotificationInboxBellNativeManagerInterface<ReactNotificationInboxBellView>,
18
+ SimpleViewManager<ReactNotificationInboxBellView>() {
19
+ private val delegate = NotificationInboxBellNativeManagerDelegate(this)
20
+
21
+ override fun getName() = NAME
22
+ override fun getDelegate(): ViewManagerDelegate<ReactNotificationInboxBellView> = delegate
23
+
24
+ override fun createViewInstance(
25
+ reactContext: ThemedReactContext
26
+ ): ReactNotificationInboxBellView = ReactNotificationInboxBellView(reactContext)
27
+
28
+ override fun getExportedCustomDirectEventTypeConstants(): MutableMap<String, Any> {
29
+ val customEvents = super.getExportedCustomDirectEventTypeConstants() ?: mutableMapOf()
30
+ customEvents[ReactNotificationInboxBellView.ON_TAP] =
31
+ mapOf("registrationName" to ReactNotificationInboxBellView.ON_TAP)
32
+ return customEvents
33
+ }
34
+
35
+ companion object {
36
+ internal const val NAME = "NotificationInboxBellNative"
37
+ }
38
+ }
@@ -0,0 +1,30 @@
1
+ package com.zixflow.reactnative.sdk.messaginginbox
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.viewmanagers.NotificationInboxViewNativeManagerDelegate
8
+ import com.facebook.react.viewmanagers.NotificationInboxViewNativeManagerInterface
9
+
10
+ /**
11
+ * View manager for the Visual Notification Inbox message list (the Jist-rendered list,
12
+ * embeddable in the host's own screen). No props or events; sizing comes from the JS style.
13
+ */
14
+ @ReactModule(name = NotificationInboxViewManager.NAME)
15
+ class NotificationInboxViewManager :
16
+ NotificationInboxViewNativeManagerInterface<ReactNotificationInboxView>,
17
+ SimpleViewManager<ReactNotificationInboxView>() {
18
+ private val delegate = NotificationInboxViewNativeManagerDelegate(this)
19
+
20
+ override fun getName() = NAME
21
+ override fun getDelegate(): ViewManagerDelegate<ReactNotificationInboxView> = delegate
22
+
23
+ override fun createViewInstance(
24
+ reactContext: ThemedReactContext
25
+ ): ReactNotificationInboxView = ReactNotificationInboxView(reactContext)
26
+
27
+ companion object {
28
+ internal const val NAME = "NotificationInboxViewNative"
29
+ }
30
+ }
@@ -0,0 +1,96 @@
1
+ package com.zixflow.reactnative.sdk.messaginginbox
2
+
3
+ import android.content.Context
4
+ import android.view.Choreographer
5
+ import android.view.View
6
+ import android.widget.FrameLayout
7
+ import androidx.compose.runtime.Composable
8
+ import androidx.compose.ui.platform.ComposeView
9
+ import com.facebook.react.bridge.WritableMap
10
+ import com.zixflow.reactnative.sdk.extension.sendUIEventToReactJS
11
+
12
+ /**
13
+ * Base React Native view that hosts a Jetpack Compose [content] inside a [ComposeView].
14
+ *
15
+ * Mirrors the role that the native SDK's `WrapperInlineView` plays for inline in-app
16
+ * messages, but the Visual Notification Inbox components are plain `@Composable`s, so we
17
+ * host them directly in a [ComposeView] rather than going through an inline-message wrapper.
18
+ *
19
+ * Subclasses provide the composable via [content] and emit events with [emitEvent].
20
+ *
21
+ * Layout note: React Native (Yoga) lays this view out, so the [ComposeView] is sized to the
22
+ * bounds RN assigns. Because RN children measured by native code don't always re-trigger a
23
+ * layout pass, we schedule a manual measure/layout via the [Choreographer] whenever the view
24
+ * is attached, matching how other RN-hosted native views keep themselves laid out.
25
+ */
26
+ abstract class ReactComposeHostView(context: Context) : FrameLayout(context) {
27
+
28
+ private val composeView: ComposeView = ComposeView(context).apply {
29
+ layoutParams = LayoutParams(
30
+ LayoutParams.MATCH_PARENT,
31
+ LayoutParams.MATCH_PARENT
32
+ )
33
+ setContent { content() }
34
+ }
35
+
36
+ /** The Compose UI hosted by this view. Implemented by each concrete inbox component. */
37
+ @Composable
38
+ protected abstract fun content()
39
+
40
+ /**
41
+ * The Compose child is attached here rather than in `init`, gating setup on attachment the same
42
+ * way [com.zixflow.messaginginapp.ui.core.BaseInlineInAppMessageView] gates its subscription.
43
+ *
44
+ * Fabric measures a newly created view before the mount batch's INSERT attaches it to the
45
+ * window ([com.facebook.react.fabric.mounting.SurfaceMountingManager.updateLayout]), and
46
+ * `AbstractComposeView.onMeasure` unconditionally creates its composition, which needs a window
47
+ * to resolve the recomposer. Adding the child in `init` therefore threw
48
+ * `IllegalStateException: Cannot locate windowRecomposer` during that measure; the mount batch
49
+ * aborted and the half-mounted hierarchy crashed the host app.
50
+ */
51
+ override fun onAttachedToWindow() {
52
+ super.onAttachedToWindow()
53
+ if (composeView.parent == null) {
54
+ addView(composeView)
55
+ }
56
+ }
57
+
58
+ /**
59
+ * Dispatches a UI event back to the JS side using the React Native event dispatcher.
60
+ *
61
+ * @param eventName name registered in the view manager's
62
+ * `getExportedCustomDirectEventTypeConstants`.
63
+ * @param payload optional event data.
64
+ */
65
+ protected fun emitEvent(eventName: String, payload: WritableMap? = null) {
66
+ sendUIEventToReactJS(eventName = eventName, payload = payload)
67
+ }
68
+
69
+ /**
70
+ * React Native lays out views off the main Android layout pass, so manually re-run
71
+ * measure + layout against the bounds RN assigned. Without this, native children of
72
+ * RN-managed views can render with a zero size.
73
+ */
74
+ override fun requestLayout() {
75
+ super.requestLayout()
76
+ post(measureAndLayout)
77
+ }
78
+
79
+ private val measureAndLayout = Runnable {
80
+ // The callback is posted for the next frame, by which point the view may have been detached
81
+ // (Fabric recycles these). Measuring the Compose child without a window throws, so skip it —
82
+ // a later attach re-runs layout anyway.
83
+ if (!isAttachedToWindow) {
84
+ return@Runnable
85
+ }
86
+ measure(
87
+ MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
88
+ MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)
89
+ )
90
+ layout(left, top, right, bottom)
91
+ }
92
+
93
+ private fun View.post(action: Runnable) {
94
+ Choreographer.getInstance().postFrameCallback { action.run() }
95
+ }
96
+ }
@@ -0,0 +1,48 @@
1
+ package com.zixflow.reactnative.sdk.messaginginbox
2
+
3
+ import android.content.Context
4
+ import android.view.MotionEvent
5
+ import androidx.compose.runtime.Composable
6
+ import com.facebook.react.bridge.Arguments
7
+ import com.zixflow.messaginginbox.NotificationInboxOverlay
8
+
9
+ /**
10
+ * React Native host for the Visual Notification Inbox bell.
11
+ *
12
+ * Hosts the native [NotificationInboxOverlay] composable rather than `NotificationInboxBell`: only the
13
+ * overlay ties the bell to the SDK's own inbox panel, and the wrapper deliberately does not reimplement
14
+ * panel presentation. Sized to the frame React Native assigns, that composition *is* a bell that opens
15
+ * the inbox — the component wrappers expose.
16
+ *
17
+ * Remote branding still styles the bell (colors, icon). Branding's bell *position* has no effect here:
18
+ * alignment resolves inside this view's bounds, so the JS host owns placement via `style`.
19
+ *
20
+ * [ON_TAP] is observational — the SDK opens the panel itself, so the host has nothing to do in response.
21
+ */
22
+ class ReactNotificationInboxBellView(context: Context) : ReactComposeHostView(context) {
23
+ @Composable
24
+ override fun content() {
25
+ NotificationInboxOverlay()
26
+ }
27
+
28
+ /**
29
+ * Reports taps without consuming them.
30
+ *
31
+ * `dispatchTouchEvent` rather than `onTouchEvent`: the Compose child consumes the bell tap, so a
32
+ * parent `onTouchEvent` would never run. Dispatching to super first keeps the gesture flowing to
33
+ * Compose (which opens the panel); we only observe the outcome. Reporting on ACTION_UP and only
34
+ * when the touch was consumed approximates "the bell took this tap" rather than firing for taps
35
+ * that landed on the transparent area around it.
36
+ */
37
+ override fun dispatchTouchEvent(event: MotionEvent): Boolean {
38
+ val handled = super.dispatchTouchEvent(event)
39
+ if (handled && event.actionMasked == MotionEvent.ACTION_UP) {
40
+ emitEvent(ON_TAP, Arguments.createMap())
41
+ }
42
+ return handled
43
+ }
44
+
45
+ companion object {
46
+ const val ON_TAP = "onTap"
47
+ }
48
+ }
@@ -0,0 +1,17 @@
1
+ package com.zixflow.reactnative.sdk.messaginginbox
2
+
3
+ import android.content.Context
4
+ import androidx.compose.runtime.Composable
5
+ import com.zixflow.messaginginbox.NotificationInboxView
6
+
7
+ /**
8
+ * React Native host for the native [NotificationInboxView] composable (the Jist-rendered
9
+ * message list). Sizing is driven by the JS `style` prop. Message actions are handled by the
10
+ * existing global InboxEventListener, so this component emits no per-message events.
11
+ */
12
+ class ReactNotificationInboxView(context: Context) : ReactComposeHostView(context) {
13
+ @Composable
14
+ override fun content() {
15
+ NotificationInboxView()
16
+ }
17
+ }
@@ -23,6 +23,7 @@ import com.zixflow.reactnative.sdk.NativeZixflowMessagingPushSpec
23
23
  import com.zixflow.reactnative.sdk.constant.Keys
24
24
  import com.zixflow.reactnative.sdk.extension.getTypedValue
25
25
  import com.zixflow.reactnative.sdk.extension.takeIfNotBlank
26
+ import com.zixflow.reactnative.sdk.liveactivities.NativeLiveActivitiesModule
26
27
  import com.zixflow.reactnative.sdk.util.unsupportedOnAndroid
27
28
  import com.zixflow.sdk.Zixflow
28
29
  import com.zixflow.sdk.ZixflowBuilder
@@ -257,7 +258,8 @@ class NativeMessagingPushModule(
257
258
  */
258
259
  internal fun addNativeModuleFromConfig(
259
260
  builder: ZixflowBuilder,
260
- config: Map<String, Any>
261
+ config: Map<String, Any>,
262
+ liveNotificationsConfig: Map<String, Any>? = null,
261
263
  ) {
262
264
  val androidConfig =
263
265
  config.getTypedValue<Map<String, Any>>(key = "android") ?: emptyMap()
@@ -275,6 +277,14 @@ class NativeMessagingPushModule(
275
277
  val module = ModuleMessagingPushFCM(
276
278
  moduleConfig = MessagingPushModuleConfig.Builder().apply {
277
279
  setPushClickBehavior(pushClickBehavior = pushClickBehavior)
280
+ // Live Notifications are hosted by the FCM push module, so their config is
281
+ // applied to the same MessagingPushModuleConfig.
282
+ liveNotificationsConfig?.let { liveConfig ->
283
+ NativeLiveActivitiesModule.applyLiveActivitiesConfig(
284
+ builder = this,
285
+ config = liveConfig,
286
+ )
287
+ }
278
288
  }.build(),
279
289
  )
280
290
  builder.addZixflowModule(module)
@@ -9,5 +9,5 @@
9
9
  This will be updated by update-version script with React Native package version
10
10
  whenever new version of React Native package is released
11
11
  -->
12
- <string name="zixflow_react_native_sdk_client_version">1.1.0</string>
12
+ <string name="zixflow_react_native_sdk_client_version">1.1.5</string>
13
13
  </resources>
@@ -1,12 +1,25 @@
1
1
  dependencies {
2
+ // The real published Maven Central group id is "com.zixflow.com.android" (not
3
+ // "com.zixflow.android") -- a known artifact-id quirk in how the native Android SDK
4
+ // is published. Using the "corrected-looking" coordinate fails dependency resolution.
2
5
  api "com.zixflow.com.android:datapipelines:$zixflowAndroidSDKVersion"
3
6
  api "com.zixflow.com.android:messaging-push-fcm:$zixflowAndroidSDKVersion"
4
7
  api "com.zixflow.com.android:messaging-in-app:$zixflowAndroidSDKVersion"
8
+ // Visual Notification Inbox UI (Compose-based).
9
+ api "com.zixflow.com.android:messaging-inbox:$zixflowAndroidSDKVersion"
5
10
  // Location module is optional - customers enable it by adding
6
- // zixflow_location_enabled=true in their gradle.properties
7
- if (project.zixflowLocationEnabled) {
11
+ // zixflow_location_enabled=true in their gradle.properties.
12
+ // Geofence implies Location: enabling geofence pulls in location too.
13
+ if (project.zixflowLocationEnabled || project.zixflowGeofenceEnabled) {
8
14
  api "com.zixflow.com.android:location:$zixflowAndroidSDKVersion"
9
15
  } else {
10
16
  compileOnly "com.zixflow.com.android:location:$zixflowAndroidSDKVersion"
11
17
  }
18
+ // Geofence module is optional - customers enable it by adding
19
+ // zixflow_geofence_enabled=true in their gradle.properties
20
+ if (project.zixflowGeofenceEnabled) {
21
+ api "com.zixflow.com.android:geofence:$zixflowAndroidSDKVersion"
22
+ } else {
23
+ compileOnly "com.zixflow.com.android:geofence:$zixflowAndroidSDKVersion"
24
+ }
12
25
  }