@bubblsdk/react-native-sdk 4.1.7 → 5.0.0-alpha.2

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 (176) hide show
  1. package/BubblReactNativeSdk.podspec +29 -9
  2. package/CHANGELOG.md +52 -1
  3. package/LICENSE +202 -1
  4. package/README.md +172 -83
  5. package/android/build.gradle +33 -30
  6. package/android/src/main/AndroidManifest.xml +1 -0
  7. package/android/src/main/java/tech/bubbl/reactnative/BubblJson.kt +135 -0
  8. package/android/src/main/java/tech/bubbl/reactnative/BubblSdkModule.kt +277 -0
  9. package/android/src/main/java/tech/bubbl/reactnative/BubblSdkPackage.kt +26 -0
  10. package/app.plugin.js +2 -0
  11. package/ios/BubblPush.swift +44 -0
  12. package/ios/BubblSdk.h +7 -0
  13. package/ios/BubblSdk.mm +252 -0
  14. package/ios/BubblSdkImpl.swift +335 -0
  15. package/ios-extension/BubblReactNativeNotificationService.podspec +44 -0
  16. package/ios-extension/Sources/BubblCore/API/ApiResponse.swift +90 -0
  17. package/ios-extension/Sources/BubblCore/API/CredentialStore.swift +116 -0
  18. package/ios-extension/Sources/BubblCore/API/DeviceApiClient.swift +239 -0
  19. package/ios-extension/Sources/BubblCore/API/ErrorActions.swift +68 -0
  20. package/ios-extension/Sources/BubblCore/API/Http.swift +39 -0
  21. package/ios-extension/Sources/BubblCore/API/ServerClock.swift +69 -0
  22. package/ios-extension/Sources/BubblCore/BubblVersion.swift +5 -0
  23. package/ios-extension/Sources/BubblCore/Device/ConfigSync.swift +216 -0
  24. package/ios-extension/Sources/BubblCore/Device/DeviceSync.swift +160 -0
  25. package/ios-extension/Sources/BubblCore/Device/ProvisioningProfile.swift +24 -0
  26. package/ios-extension/Sources/BubblCore/Engine/EngineCore.swift +523 -0
  27. package/ios-extension/Sources/BubblCore/Engine/Geofencing.swift +170 -0
  28. package/ios-extension/Sources/BubblCore/Engine/Permissions.swift +90 -0
  29. package/ios-extension/Sources/BubblCore/Engine/Privacy.swift +64 -0
  30. package/ios-extension/Sources/BubblCore/Engine/PrivacyControls.swift +184 -0
  31. package/ios-extension/Sources/BubblCore/Engine/Pushes.swift +61 -0
  32. package/ios-extension/Sources/BubblCore/Engine/Sandbox.swift +149 -0
  33. package/ios-extension/Sources/BubblCore/Events/EventQueue.swift +207 -0
  34. package/ios-extension/Sources/BubblCore/Events/EventStore.swift +159 -0
  35. package/ios-extension/Sources/BubblCore/Geofence/Geofence.swift +160 -0
  36. package/ios-extension/Sources/BubblCore/Geofence/GeofenceEngine.swift +488 -0
  37. package/ios-extension/Sources/BubblCore/Geofence/GeofenceState.swift +103 -0
  38. package/ios-extension/Sources/BubblCore/Geofence/RegionBudget.swift +62 -0
  39. package/ios-extension/Sources/BubblCore/Notification/BubblNotification.swift +137 -0
  40. package/ios-extension/Sources/BubblCore/Notification/NotificationEvents.swift +160 -0
  41. package/ios-extension/Sources/BubblCore/Notification/Push.swift +134 -0
  42. package/ios-extension/Sources/BubblCore/Notification/SurveyForm.swift +185 -0
  43. package/ios-extension/Sources/BubblCore/RequestSigner.swift +56 -0
  44. package/ios-extension/Sources/BubblCore/Support/AsyncMutex.swift +39 -0
  45. package/ios-extension/Sources/BubblCore/Support/BubblLog.swift +52 -0
  46. package/ios-extension/Sources/BubblCore/Support/JSON.swift +31 -0
  47. package/ios-extension/Sources/BubblCore/Support/JSONValue.swift +94 -0
  48. package/ios-extension/Sources/BubblCore/Support/Locking.swift +11 -0
  49. package/ios-extension/Sources/BubblCore/Support/ValueStore.swift +109 -0
  50. package/ios-extension/Sources/BubblNotificationService/BubblNotificationService.swift +124 -0
  51. package/ios-sdk/BubblCore/API/ApiResponse.swift +90 -0
  52. package/ios-sdk/BubblCore/API/CredentialStore.swift +116 -0
  53. package/ios-sdk/BubblCore/API/DeviceApiClient.swift +239 -0
  54. package/ios-sdk/BubblCore/API/ErrorActions.swift +68 -0
  55. package/ios-sdk/BubblCore/API/Http.swift +39 -0
  56. package/ios-sdk/BubblCore/API/ServerClock.swift +69 -0
  57. package/ios-sdk/BubblCore/BubblVersion.swift +5 -0
  58. package/ios-sdk/BubblCore/Device/ConfigSync.swift +216 -0
  59. package/ios-sdk/BubblCore/Device/DeviceSync.swift +160 -0
  60. package/ios-sdk/BubblCore/Device/ProvisioningProfile.swift +24 -0
  61. package/ios-sdk/BubblCore/Engine/EngineCore.swift +523 -0
  62. package/ios-sdk/BubblCore/Engine/Geofencing.swift +170 -0
  63. package/ios-sdk/BubblCore/Engine/Permissions.swift +90 -0
  64. package/ios-sdk/BubblCore/Engine/Privacy.swift +64 -0
  65. package/ios-sdk/BubblCore/Engine/PrivacyControls.swift +184 -0
  66. package/ios-sdk/BubblCore/Engine/Pushes.swift +61 -0
  67. package/ios-sdk/BubblCore/Engine/Sandbox.swift +149 -0
  68. package/ios-sdk/BubblCore/Events/EventQueue.swift +207 -0
  69. package/ios-sdk/BubblCore/Events/EventStore.swift +159 -0
  70. package/ios-sdk/BubblCore/Geofence/Geofence.swift +160 -0
  71. package/ios-sdk/BubblCore/Geofence/GeofenceEngine.swift +488 -0
  72. package/ios-sdk/BubblCore/Geofence/GeofenceState.swift +103 -0
  73. package/ios-sdk/BubblCore/Geofence/RegionBudget.swift +62 -0
  74. package/ios-sdk/BubblCore/Notification/BubblNotification.swift +137 -0
  75. package/ios-sdk/BubblCore/Notification/NotificationEvents.swift +160 -0
  76. package/ios-sdk/BubblCore/Notification/Push.swift +134 -0
  77. package/ios-sdk/BubblCore/Notification/SurveyForm.swift +185 -0
  78. package/ios-sdk/BubblCore/RequestSigner.swift +56 -0
  79. package/ios-sdk/BubblCore/Support/AsyncMutex.swift +39 -0
  80. package/ios-sdk/BubblCore/Support/BubblLog.swift +52 -0
  81. package/ios-sdk/BubblCore/Support/JSON.swift +31 -0
  82. package/ios-sdk/BubblCore/Support/JSONValue.swift +94 -0
  83. package/ios-sdk/BubblCore/Support/Locking.swift +11 -0
  84. package/ios-sdk/BubblCore/Support/ValueStore.swift +109 -0
  85. package/ios-sdk/BubblLaunch/BubblLaunch.m +45 -0
  86. package/ios-sdk/BubblLaunch/include/BubblLaunch.h +5 -0
  87. package/ios-sdk/BubblSDK/Bubbl.swift +308 -0
  88. package/ios-sdk/BubblSDK/BubblBackend.swift +118 -0
  89. package/ios-sdk/BubblSDK/BubblCredential.swift +30 -0
  90. package/ios-sdk/BubblSDK/BubblMessage.swift +151 -0
  91. package/ios-sdk/BubblSDK/BubblOptions.swift +39 -0
  92. package/ios-sdk/BubblSDK/BubblPermissions.swift +79 -0
  93. package/ios-sdk/BubblSDK/BubblTestDeviceResult.swift +10 -0
  94. package/ios-sdk/BubblSDK/Engine/BackgroundRefresh.swift +92 -0
  95. package/ios-sdk/BubblSDK/Engine/EngineHost+Geofences.swift +177 -0
  96. package/ios-sdk/BubblSDK/Engine/EngineHost+Privacy.swift +65 -0
  97. package/ios-sdk/BubblSDK/Engine/EngineHost+Push.swift +154 -0
  98. package/ios-sdk/BubblSDK/Engine/EngineHost.swift +356 -0
  99. package/ios-sdk/BubblSDK/Engine/SupportedBubbl.swift +320 -0
  100. package/ios-sdk/BubblSDK/Engine/SystemLog.swift +27 -0
  101. package/ios-sdk/BubblSDK/Engine/WorkRunner.swift +107 -0
  102. package/ios-sdk/BubblSDK/Notification/Look.swift +78 -0
  103. package/ios-sdk/BubblSDK/Notification/NotificationMedia.swift +329 -0
  104. package/ios-sdk/BubblSDK/Notification/NotificationModel.swift +172 -0
  105. package/ios-sdk/BubblSDK/Notification/NotificationScreen.swift +428 -0
  106. package/ios-sdk/BubblSDK/Notification/ScreenPresenter.swift +148 -0
  107. package/ios-sdk/BubblSDK/Permissions/PermissionFlow.swift +169 -0
  108. package/ios-sdk/BubblSDK/Permissions/PrivacyView.swift +110 -0
  109. package/ios-sdk/BubblSDK/Platform/AppleDevicePlatform.swift +95 -0
  110. package/ios-sdk/BubblSDK/Platform/KeychainCredentialStore.swift +114 -0
  111. package/ios-sdk/BubblSDK/Platform/LocationService.swift +418 -0
  112. package/ios-sdk/BubblSDK/Platform/PushIntegration.swift +288 -0
  113. package/ios-sdk/BubblSDK/Platform/URLSessionHttpClient.swift +69 -0
  114. package/ios-sdk/BubblSDK/PrivacyInfo.xcprivacy +76 -0
  115. package/jest/index.js +75 -0
  116. package/lib/commonjs/BubblModule.js +14 -0
  117. package/lib/commonjs/BubblModule.js.map +1 -0
  118. package/lib/commonjs/BubblModule.web.js +13 -0
  119. package/lib/commonjs/BubblModule.web.js.map +1 -0
  120. package/lib/commonjs/NativeBubblSdk.js +20 -0
  121. package/lib/commonjs/NativeBubblSdk.js.map +1 -0
  122. package/lib/commonjs/index.js +336 -0
  123. package/lib/commonjs/index.js.map +1 -0
  124. package/lib/commonjs/package.json +1 -0
  125. package/lib/commonjs/types.js +2 -0
  126. package/lib/commonjs/types.js.map +1 -0
  127. package/lib/module/BubblModule.js +5 -0
  128. package/lib/module/BubblModule.js.map +1 -0
  129. package/lib/module/BubblModule.web.js +9 -0
  130. package/lib/module/BubblModule.web.js.map +1 -0
  131. package/lib/module/NativeBubblSdk.js +18 -0
  132. package/lib/module/NativeBubblSdk.js.map +1 -0
  133. package/lib/module/index.js +331 -0
  134. package/lib/module/index.js.map +1 -0
  135. package/lib/module/package.json +1 -0
  136. package/lib/module/types.js +2 -0
  137. package/lib/module/types.js.map +1 -0
  138. package/lib/typescript/commonjs/package.json +1 -0
  139. package/lib/typescript/commonjs/src/BubblModule.d.ts +3 -0
  140. package/lib/typescript/commonjs/src/BubblModule.d.ts.map +1 -0
  141. package/lib/typescript/commonjs/src/BubblModule.web.d.ts +8 -0
  142. package/lib/typescript/commonjs/src/BubblModule.web.d.ts.map +1 -0
  143. package/lib/typescript/commonjs/src/NativeBubblSdk.d.ts +59 -0
  144. package/lib/typescript/commonjs/src/NativeBubblSdk.d.ts.map +1 -0
  145. package/lib/typescript/commonjs/src/index.d.ts +111 -0
  146. package/lib/typescript/commonjs/src/index.d.ts.map +1 -0
  147. package/lib/typescript/commonjs/src/types.d.ts +192 -0
  148. package/lib/typescript/commonjs/src/types.d.ts.map +1 -0
  149. package/lib/typescript/module/package.json +1 -0
  150. package/lib/typescript/module/src/BubblModule.d.ts +3 -0
  151. package/lib/typescript/module/src/BubblModule.d.ts.map +1 -0
  152. package/lib/typescript/module/src/BubblModule.web.d.ts +8 -0
  153. package/lib/typescript/module/src/BubblModule.web.d.ts.map +1 -0
  154. package/lib/typescript/module/src/NativeBubblSdk.d.ts +59 -0
  155. package/lib/typescript/module/src/NativeBubblSdk.d.ts.map +1 -0
  156. package/lib/typescript/module/src/index.d.ts +111 -0
  157. package/lib/typescript/module/src/index.d.ts.map +1 -0
  158. package/lib/typescript/module/src/types.d.ts +192 -0
  159. package/lib/typescript/module/src/types.d.ts.map +1 -0
  160. package/package.json +105 -24
  161. package/plugin/build/imageNotifications.d.ts +35 -0
  162. package/plugin/build/imageNotifications.js +198 -0
  163. package/plugin/build/index.d.ts +84 -0
  164. package/plugin/build/index.js +176 -0
  165. package/src/BubblModule.ts +2 -0
  166. package/src/BubblModule.web.ts +9 -0
  167. package/src/NativeBubblSdk.ts +67 -0
  168. package/src/index.ts +338 -282
  169. package/src/types.ts +182 -0
  170. package/android/src/main/kotlin/tech/bubbl/reactnative/BubblSdkModule.kt +0 -680
  171. package/android/src/main/kotlin/tech/bubbl/reactnative/BubblSdkNotificationIntents.kt +0 -32
  172. package/android/src/main/kotlin/tech/bubbl/reactnative/BubblSdkPackage.kt +0 -14
  173. package/ios/BubblSdk.swift +0 -802
  174. package/ios/BubblSdkBridge.m +0 -86
  175. package/react-native.config.js +0 -11
  176. package/src/specs/NativeBubblSdk.ts +0 -54
@@ -1,680 +0,0 @@
1
- package tech.bubbl.reactnative
2
-
3
- import com.facebook.react.bridge.Arguments
4
- import com.facebook.react.bridge.Promise
5
- import com.facebook.react.bridge.ReactApplicationContext
6
- import com.facebook.react.bridge.ReactContextBaseJavaModule
7
- import com.facebook.react.bridge.ReactMethod
8
- import com.facebook.react.bridge.ReadableArray
9
- import com.facebook.react.bridge.ReadableMap
10
- import com.facebook.react.bridge.WritableArray
11
- import com.facebook.react.bridge.WritableMap
12
- import com.facebook.react.modules.core.DeviceEventManagerModule
13
- import kotlinx.coroutines.CoroutineScope
14
- import kotlinx.coroutines.Dispatchers
15
- import kotlinx.coroutines.Job
16
- import kotlinx.coroutines.SupervisorJob
17
- import kotlinx.coroutines.cancel
18
- import kotlinx.coroutines.flow.collectLatest
19
- import kotlinx.coroutines.launch
20
- import kotlinx.coroutines.withContext
21
- import tech.bubbl.sdk.BubblBootResult
22
- import tech.bubbl.sdk.BubblConfig
23
- import tech.bubbl.sdk.BubblConfiguration
24
- import tech.bubbl.sdk.BubblDiagnostics
25
- import tech.bubbl.sdk.BubblEnvironment
26
- import tech.bubbl.sdk.BubblEvent
27
- import tech.bubbl.sdk.BubblFlushResult
28
- import tech.bubbl.sdk.BubblGeofenceCircle
29
- import tech.bubbl.sdk.BubblGeofencePolygon
30
- import tech.bubbl.sdk.BubblGeofenceSnapshot
31
- import tech.bubbl.sdk.BubblGeofenceTransition
32
- import tech.bubbl.sdk.BubblGeofenceTransitionType
33
- import tech.bubbl.sdk.BubblLocation
34
- import tech.bubbl.sdk.BubblLogLevel
35
- import tech.bubbl.sdk.BubblNotificationCta
36
- import tech.bubbl.sdk.BubblNotificationDisplayResult
37
- import tech.bubbl.sdk.BubblNotificationMedia
38
- import tech.bubbl.sdk.BubblNotificationModalStyle
39
- import tech.bubbl.sdk.BubblNotificationModalTheme
40
- import tech.bubbl.sdk.BubblNotificationPayload
41
- import tech.bubbl.sdk.BubblNotificationRenderingMode
42
- import tech.bubbl.sdk.BubblNotificationSource
43
- import tech.bubbl.sdk.BubblNotificationSurvey
44
- import tech.bubbl.sdk.BubblNotificationTap
45
- import tech.bubbl.sdk.BubblSdk
46
- import tech.bubbl.sdk.BubblSurveyAnswer
47
- import tech.bubbl.sdk.BubblSurveyChoice
48
- import tech.bubbl.sdk.BubblSurveyQuestion
49
- import tech.bubbl.sdk.BubblSurveyResponse
50
- import tech.bubbl.sdk.BubblTrackEvent
51
-
52
- class BubblSdkModule(
53
- private val reactContext: ReactApplicationContext
54
- ) : ReactContextBaseJavaModule(reactContext) {
55
- private var scope = CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)
56
- private var eventJob: Job? = null
57
- private var listenerCount = 0
58
-
59
- init {
60
- BubblSdk.install(reactContext)
61
- }
62
-
63
- override fun getName(): String = NAME
64
-
65
- override fun invalidate() {
66
- eventJob?.cancel()
67
- scope.cancel()
68
- scope = CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)
69
- super.invalidate()
70
- }
71
-
72
- @ReactMethod
73
- fun addListener(eventName: String) {
74
- listenerCount += 1
75
- if (eventName == EVENT_NAME && eventJob == null) {
76
- eventJob = scope.launch {
77
- BubblSdk.events.collectLatest { event ->
78
- emitEvent(event.toWritableMap())
79
- }
80
- }
81
- BubblSdk.drainPendingNotificationTaps().forEach { tap ->
82
- emitEvent(tap.toWritableMap())
83
- }
84
- }
85
- }
86
-
87
- @ReactMethod
88
- fun removeListeners(count: Int) {
89
- listenerCount = (listenerCount - count).coerceAtLeast(0)
90
- if (listenerCount == 0) {
91
- eventJob?.cancel()
92
- eventJob = null
93
- }
94
- }
95
-
96
- @ReactMethod
97
- fun boot(config: ReadableMap, promise: Promise) = resolve(promise) {
98
- BubblSdk.boot(config.toConfig()).toWritableMap()
99
- }
100
-
101
- @ReactMethod
102
- fun shutdown(promise: Promise) = resolve(promise) {
103
- BubblSdk.shutdown()
104
- null
105
- }
106
-
107
- @ReactMethod
108
- fun startLocationTracking(promise: Promise) = resolve(promise) {
109
- BubblSdk.startLocationTracking(reactContext)
110
- null
111
- }
112
-
113
- @ReactMethod
114
- fun stopLocationTracking(promise: Promise) = resolve(promise) {
115
- BubblSdk.stopLocationTracking(reactContext)
116
- null
117
- }
118
-
119
- @ReactMethod
120
- fun refresh(promise: Promise) = resolve(promise) {
121
- BubblSdk.refresh()
122
- null
123
- }
124
-
125
- @ReactMethod
126
- fun refreshGeofence(latitude: Double, longitude: Double, promise: Promise) = resolve(promise) {
127
- BubblSdk.refreshGeofence(BubblLocation(latitude, longitude))
128
- null
129
- }
130
-
131
- @ReactMethod
132
- fun handleLocationUpdate(latitude: Double, longitude: Double, promise: Promise) = resolve(promise) {
133
- BubblSdk.handleLocationUpdate(BubblLocation(latitude, longitude))
134
- null
135
- }
136
-
137
- @ReactMethod
138
- fun refreshPush(promise: Promise) = resolve(promise) {
139
- BubblSdk.refreshPush()
140
- null
141
- }
142
-
143
- @ReactMethod
144
- fun getConfiguration(promise: Promise) = resolve(promise) {
145
- BubblSdk.getConfiguration()?.toWritableMap()
146
- }
147
-
148
- @ReactMethod
149
- fun getPrivacyText(promise: Promise) = resolve(promise) {
150
- BubblSdk.getPrivacyText()
151
- }
152
-
153
- @ReactMethod
154
- fun updateSegments(tags: ReadableArray, promise: Promise) = resolve(promise) {
155
- BubblSdk.updateSegments(tags.stringList())
156
- null
157
- }
158
-
159
- @ReactMethod
160
- fun setCorrelationId(value: String, promise: Promise) = resolve(promise) {
161
- BubblSdk.setCorrelationId(value)
162
- null
163
- }
164
-
165
- @ReactMethod
166
- fun clearCorrelationId(promise: Promise) = resolve(promise) {
167
- BubblSdk.clearCorrelationId()
168
- null
169
- }
170
-
171
- @ReactMethod
172
- fun setDefaultNotificationModalEnabled(enabled: Boolean, promise: Promise) = resolve(promise) {
173
- BubblSdk.setDefaultNotificationModalEnabled(enabled)
174
- null
175
- }
176
-
177
- @ReactMethod
178
- fun setDefaultNotificationModalStyle(style: ReadableMap?, promise: Promise) = resolve(promise) {
179
- BubblSdk.setDefaultNotificationModalStyle(style?.toNotificationModalStyle())
180
- null
181
- }
182
-
183
- @ReactMethod
184
- fun registerPushToken(token: String, promise: Promise) = resolve(promise) {
185
- BubblSdk.registerPushToken(token)
186
- BubblSdk.flush()
187
- null
188
- }
189
-
190
- @ReactMethod
191
- fun handleFirebasePayload(payload: ReadableMap, promise: Promise) = resolve(promise) {
192
- BubblSdk.handleFirebasePayload(payload.stringMap())?.toWritableMap()
193
- }
194
-
195
- @ReactMethod
196
- fun showNotification(payload: ReadableMap, promise: Promise) = resolve(promise) {
197
- BubblSdk.showNotification(payload.toNotificationPayload()).toWritableMap()
198
- }
199
-
200
- @ReactMethod
201
- fun handleNotificationPayload(payload: ReadableMap, promise: Promise) = resolve(promise) {
202
- BubblSdk.handleNotificationPayload(payload.toNotificationPayload()).toWritableMap()
203
- }
204
-
205
- @ReactMethod
206
- fun handleNotificationOpen(payload: ReadableMap, action: String?, promise: Promise) = resolve(promise) {
207
- BubblSdk.handleNotificationOpen(payload.toNotificationPayload(), action)
208
- null
209
- }
210
-
211
- @ReactMethod
212
- fun openNotificationModal(payload: ReadableMap, action: String?, promise: Promise) = resolve(promise) {
213
- BubblSdk.openNotificationModal(reactContext, payload.toNotificationPayload(), action)
214
- }
215
-
216
- @ReactMethod
217
- fun handleNotificationCta(payload: ReadableMap, action: String?, promise: Promise) = resolve(promise) {
218
- BubblSdk.handleNotificationCta(payload.toNotificationPayload(), action)
219
- null
220
- }
221
-
222
- @ReactMethod
223
- fun handleNotificationMediaViewed(payload: ReadableMap, promise: Promise) = resolve(promise) {
224
- BubblSdk.handleNotificationMediaViewed(payload.toNotificationPayload())
225
- null
226
- }
227
-
228
- @ReactMethod
229
- fun handleNotificationSurveyRequested(payload: ReadableMap, promise: Promise) = resolve(promise) {
230
- BubblSdk.handleNotificationSurveyRequested(payload.toNotificationPayload())
231
- null
232
- }
233
-
234
- @ReactMethod
235
- fun track(event: ReadableMap, promise: Promise) = resolve(promise) {
236
- BubblSdk.track(event.toTrackEvent())
237
- null
238
- }
239
-
240
- @ReactMethod
241
- fun submitSurveyResponse(response: ReadableMap, promise: Promise) = resolve(promise) {
242
- BubblSdk.submitSurveyResponse(response.toSurveyResponse())
243
- null
244
- }
245
-
246
- @ReactMethod
247
- fun flush(promise: Promise) = resolve(promise) {
248
- BubblSdk.flush().toWritableMap()
249
- }
250
-
251
- @ReactMethod
252
- fun diagnostics(promise: Promise) = resolve(promise) {
253
- BubblSdk.diagnostics().copy(platform = "react-native").toWritableMap()
254
- }
255
-
256
- private fun resolve(promise: Promise, block: suspend () -> Any?) {
257
- scope.launch {
258
- try {
259
- val value = withContext(Dispatchers.IO) { block() }
260
- promise.resolve(value)
261
- } catch (error: IllegalArgumentException) {
262
- promise.reject("invalid_argument", error.message, error)
263
- } catch (error: Throwable) {
264
- promise.reject("bubbl_error", error.message ?: error.toString(), error)
265
- }
266
- }
267
- }
268
-
269
- private fun emitEvent(body: WritableMap) {
270
- if (!reactContext.hasActiveReactInstance()) return
271
-
272
- reactContext
273
- .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
274
- .emit(EVENT_NAME, body)
275
- }
276
-
277
- private fun ReadableMap.toConfig(): BubblConfig =
278
- BubblConfig(
279
- apiKey = requiredString("apiKey"),
280
- environment = enumValue(string("environment"), BubblEnvironment.Staging) {
281
- BubblEnvironment.valueOf(it.replaceFirstChar(Char::uppercaseChar))
282
- },
283
- runtimeBaseUrl = string("runtimeBaseUrl"),
284
- transmissionBaseUrl = string("transmissionBaseUrl"),
285
- ingestBaseUrl = string("ingestBaseUrl"),
286
- segments = stringList("segments"),
287
- correlationId = string("correlationId"),
288
- defaultDistanceMeters = int("defaultDistanceMeters", 10),
289
- refreshIntervalSeconds = int("refreshIntervalSeconds", 300),
290
- enablePushHandling = bool("enablePushHandling", true),
291
- enableLocationTracking = bool("enableLocationTracking", false),
292
- notificationRenderingMode = enumValue(string("notificationRenderingMode"), BubblNotificationRenderingMode.SdkDefault) {
293
- when (it) {
294
- "hostRendered" -> BubblNotificationRenderingMode.HostRendered
295
- "eventOnly" -> BubblNotificationRenderingMode.EventOnly
296
- else -> BubblNotificationRenderingMode.SdkDefault
297
- }
298
- },
299
- enableDefaultNotificationModal = bool("enableDefaultNotificationModal", true),
300
- defaultNotificationModalStyle = map("defaultNotificationModalStyle")?.toNotificationModalStyle(),
301
- enableDefaultSurveyUi = bool("enableDefaultSurveyUi", true),
302
- logLevel = enumValue(string("logLevel"), BubblLogLevel.Warn) {
303
- BubblLogLevel.valueOf(it.replaceFirstChar(Char::uppercaseChar))
304
- }
305
- )
306
-
307
- private fun ReadableMap.toNotificationModalStyle(): BubblNotificationModalStyle =
308
- BubblNotificationModalStyle(
309
- theme = enumValue(string("theme"), BubblNotificationModalTheme.Light) {
310
- if (it == "dark") BubblNotificationModalTheme.Dark else BubblNotificationModalTheme.Light
311
- },
312
- transparentBackdrop = bool("transparentBackdrop", true),
313
- backdropColor = string("backdropColor"),
314
- cardBackgroundColor = string("cardBackgroundColor"),
315
- cardBorderColor = string("cardBorderColor"),
316
- titleColor = string("titleColor"),
317
- bodyColor = string("bodyColor"),
318
- accentColor = string("accentColor"),
319
- iconBackgroundColor = string("iconBackgroundColor"),
320
- iconTextColor = string("iconTextColor"),
321
- primaryButtonBackgroundColor = string("primaryButtonBackgroundColor"),
322
- primaryButtonTextColor = string("primaryButtonTextColor"),
323
- secondaryButtonBackgroundColor = string("secondaryButtonBackgroundColor"),
324
- secondaryButtonTextColor = string("secondaryButtonTextColor"),
325
- textButtonColor = string("textButtonColor"),
326
- surveyBackgroundColor = string("surveyBackgroundColor"),
327
- inputBackgroundColor = string("inputBackgroundColor"),
328
- inputTextColor = string("inputTextColor"),
329
- inputBorderColor = string("inputBorderColor"),
330
- cornerRadius = nullableDouble("cornerRadius"),
331
- buttonCornerRadius = nullableDouble("buttonCornerRadius")
332
- )
333
-
334
- private fun ReadableMap.toTrackEvent(): BubblTrackEvent =
335
- BubblTrackEvent(
336
- type = requiredString("type"),
337
- activity = requiredString("activity"),
338
- locationId = string("locationId"),
339
- curatedNotificationId = string("curatedNotificationId"),
340
- latitude = nullableDouble("latitude"),
341
- longitude = nullableDouble("longitude")
342
- )
343
-
344
- private fun ReadableMap.toSurveyResponse(): BubblSurveyResponse =
345
- BubblSurveyResponse(
346
- curatedNotificationId = requiredString("curatedNotificationId"),
347
- locationId = string("locationId"),
348
- answers = mapList("answers").map { it.toSurveyAnswer() }
349
- )
350
-
351
- private fun ReadableMap.toSurveyAnswer(): BubblSurveyAnswer =
352
- BubblSurveyAnswer(
353
- questionId = requiredString("questionId"),
354
- type = requiredString("type"),
355
- value = string("value"),
356
- choiceIds = stringList("choiceIds")
357
- )
358
-
359
- private fun ReadableMap.toNotificationPayload(): BubblNotificationPayload =
360
- BubblNotificationPayload(
361
- id = requiredString("id"),
362
- title = requiredString("title"),
363
- body = requiredString("body"),
364
- source = enumValue(string("source"), BubblNotificationSource.Manual) {
365
- when (it) {
366
- "firebase" -> BubblNotificationSource.Firebase
367
- "apns" -> BubblNotificationSource.Apns
368
- "runtime" -> BubblNotificationSource.Runtime
369
- "geofence" -> BubblNotificationSource.Geofence
370
- else -> BubblNotificationSource.Manual
371
- }
372
- },
373
- locationId = string("locationId"),
374
- curatedNotificationId = string("curatedNotificationId"),
375
- correlationId = string("correlationId"),
376
- media = map("media")?.toNotificationMedia(),
377
- cta = map("cta")?.toNotificationCta(),
378
- survey = map("survey")?.toNotificationSurvey(),
379
- raw = map("raw")?.stringMap().orEmpty()
380
- )
381
-
382
- private fun ReadableMap.toNotificationMedia(): BubblNotificationMedia =
383
- BubblNotificationMedia(url = requiredString("url"), type = string("type"), altText = string("altText"))
384
-
385
- private fun ReadableMap.toNotificationCta(): BubblNotificationCta =
386
- BubblNotificationCta(label = requiredString("label"), url = string("url"), action = string("action"))
387
-
388
- private fun ReadableMap.toNotificationSurvey(): BubblNotificationSurvey =
389
- BubblNotificationSurvey(questions = mapList("questions").map { it.toSurveyQuestion() })
390
-
391
- private fun ReadableMap.toSurveyQuestion(): BubblSurveyQuestion =
392
- BubblSurveyQuestion(
393
- id = requiredString("id"),
394
- title = requiredString("title"),
395
- type = requiredString("type"),
396
- choices = mapList("choices").map { it.toSurveyChoice() }
397
- )
398
-
399
- private fun ReadableMap.toSurveyChoice(): BubblSurveyChoice =
400
- BubblSurveyChoice(id = requiredString("id"), label = requiredString("label"))
401
-
402
- private fun BubblBootResult.toWritableMap(): WritableMap = Arguments.createMap().apply {
403
- putBoolean("ready", ready)
404
- putBoolean("fromCache", fromCache)
405
- putBoolean("deviceRegistered", deviceRegistered)
406
- putArray("requiresPermission", requiresPermission.toWritableStringArray())
407
- putArray("warnings", warnings.toWritableStringArray())
408
- }
409
-
410
- private fun BubblConfiguration.toWritableMap(): WritableMap = Arguments.createMap().apply {
411
- putInt("notificationsCount", notificationsCount)
412
- putInt("daysCount", daysCount)
413
- putInt("batteryCount", batteryCount)
414
- putString("privacyText", privacyText)
415
- }
416
-
417
- private fun BubblDiagnostics.toWritableMap(): WritableMap = Arguments.createMap().apply {
418
- putString("sdkVersion", sdkVersion)
419
- putString("platform", platform)
420
- putBoolean("booted", booted)
421
- putInt("pendingIngestCount", pendingIngestCount)
422
- putNullableString("pushTokenSuffix", pushTokenSuffix)
423
- }
424
-
425
- private fun BubblFlushResult.toWritableMap(): WritableMap = Arguments.createMap().apply {
426
- putInt("pendingCount", pendingCount)
427
- }
428
-
429
- private fun BubblNotificationDisplayResult.toWritableMap(): WritableMap = Arguments.createMap().apply {
430
- putBoolean("displayed", displayed)
431
- putNullableString("reason", reason)
432
- }
433
-
434
- private fun BubblLocation.toWritableMap(): WritableMap = Arguments.createMap().apply {
435
- putDouble("latitude", latitude)
436
- putDouble("longitude", longitude)
437
- }
438
-
439
- private fun BubblGeofenceTransition.toWritableMap(): WritableMap = Arguments.createMap().apply {
440
- putString(
441
- "type",
442
- when (type) {
443
- BubblGeofenceTransitionType.Enter -> "enter"
444
- BubblGeofenceTransitionType.Exit -> "exit"
445
- }
446
- )
447
- putNullableString("campaignId", campaignId)
448
- putNullableString("locationId", locationId)
449
- putMap("location", location.toWritableMap())
450
- }
451
-
452
- private fun BubblNotificationPayload.toWritableMap(): WritableMap = Arguments.createMap().apply {
453
- putString("id", id)
454
- putString("title", title)
455
- putString("body", body)
456
- putString(
457
- "source",
458
- when (source) {
459
- BubblNotificationSource.Firebase -> "firebase"
460
- BubblNotificationSource.Apns -> "apns"
461
- BubblNotificationSource.Runtime -> "runtime"
462
- BubblNotificationSource.Geofence -> "geofence"
463
- BubblNotificationSource.Manual -> "manual"
464
- }
465
- )
466
- putNullableString("locationId", locationId)
467
- putNullableString("curatedNotificationId", curatedNotificationId)
468
- putNullableString("correlationId", correlationId)
469
- putNullableMap("media", media?.toWritableMap())
470
- putNullableMap("cta", cta?.toWritableMap())
471
- putNullableMap("survey", survey?.toWritableMap())
472
- putMap("raw", raw.toWritableMap())
473
- }
474
-
475
- private fun BubblNotificationMedia.toWritableMap(): WritableMap = Arguments.createMap().apply {
476
- putString("url", url)
477
- putNullableString("type", type)
478
- putNullableString("altText", altText)
479
- }
480
-
481
- private fun BubblNotificationCta.toWritableMap(): WritableMap = Arguments.createMap().apply {
482
- putString("label", label)
483
- putNullableString("url", url)
484
- putNullableString("action", action)
485
- }
486
-
487
- private fun BubblNotificationSurvey.toWritableMap(): WritableMap = Arguments.createMap().apply {
488
- putArray("questions", questions.map { it.toWritableMap() }.toWritableMapArray())
489
- }
490
-
491
- private fun BubblSurveyQuestion.toWritableMap(): WritableMap = Arguments.createMap().apply {
492
- putString("id", id)
493
- putString("title", title)
494
- putString("type", type)
495
- putArray("choices", choices.map { it.toWritableMap() }.toWritableMapArray())
496
- }
497
-
498
- private fun BubblSurveyChoice.toWritableMap(): WritableMap = Arguments.createMap().apply {
499
- putString("id", id)
500
- putString("label", label)
501
- }
502
-
503
- private fun BubblEvent.toWritableMap(): WritableMap = when (this) {
504
- BubblEvent.Ready -> Arguments.createMap().apply { putString("type", "ready") }
505
- is BubblEvent.Diagnostic -> Arguments.createMap().apply {
506
- putString("type", "diagnostic")
507
- putMap("diagnostics", diagnostics.copy(platform = "react-native").toWritableMap())
508
- }
509
- is BubblEvent.NotificationReceived -> eventPayload("notificationReceived", payload)
510
- is BubblEvent.NotificationDisplayed -> eventPayload("notificationDisplayed", payload)
511
- is BubblEvent.NotificationTapped -> eventPayload("notificationTapped", payload, action)
512
- is BubblEvent.NotificationCtaTapped -> eventPayload("notificationCtaTapped", payload, action)
513
- is BubblEvent.NotificationMediaViewed -> eventPayload("notificationMediaViewed", payload)
514
- is BubblEvent.NotificationSurveyRequested -> eventPayload("notificationSurveyRequested", payload)
515
- is BubblEvent.LocationUpdated -> Arguments.createMap().apply {
516
- putString("type", "locationUpdated")
517
- putMap("location", location.toWritableMap())
518
- }
519
- is BubblEvent.GeofenceSnapshot -> Arguments.createMap().apply {
520
- putString("type", "geofenceSnapshot")
521
- putMap("snapshot", snapshot.toWritableMap())
522
- }
523
- is BubblEvent.GeofenceEntered -> Arguments.createMap().apply {
524
- putString("type", "geofenceEntered")
525
- putMap("transition", transition.toWritableMap())
526
- }
527
- is BubblEvent.GeofenceExited -> Arguments.createMap().apply {
528
- putString("type", "geofenceExited")
529
- putMap("transition", transition.toWritableMap())
530
- }
531
- is BubblEvent.Error -> Arguments.createMap().apply {
532
- putString("type", "error")
533
- putString("code", code)
534
- putString("message", message)
535
- }
536
- }
537
-
538
- private fun BubblNotificationTap.toWritableMap(): WritableMap =
539
- eventPayload("notificationTapped", payload, action)
540
-
541
- private fun eventPayload(
542
- type: String,
543
- payload: BubblNotificationPayload,
544
- action: String? = null
545
- ): WritableMap = Arguments.createMap().apply {
546
- putString("type", type)
547
- putMap("payload", payload.toWritableMap())
548
- if (action == null) {
549
- putNull("action")
550
- } else {
551
- putString("action", action)
552
- }
553
- }
554
-
555
- private fun BubblGeofenceSnapshot.toWritableMap(): WritableMap = Arguments.createMap().apply {
556
- val statsMap = Arguments.createMap().apply {
557
- putInt("campaignsTotal", stats.campaignsTotal)
558
- putInt("polygonsTotal", stats.polygonsTotal)
559
- }
560
- putMap("stats", statsMap)
561
- putArray("polygons", polygons.map { it.toWritableMap() }.toWritableMapArray())
562
- putArray("circles", circles.map { it.toWritableMap() }.toWritableMapArray())
563
- }
564
-
565
- private fun BubblGeofencePolygon.toWritableMap(): WritableMap = Arguments.createMap().apply {
566
- putNullableId("campaignId", campaignId)
567
- putNullableString("campaignName", campaignName)
568
- putNullableId("locationId", locationId)
569
- putArray(
570
- "vertices",
571
- vertices.map { vertex ->
572
- Arguments.createMap().apply {
573
- putDouble("latitude", vertex.latitude)
574
- putDouble("longitude", vertex.longitude)
575
- }
576
- }.toWritableMapArray()
577
- )
578
- }
579
-
580
- private fun BubblGeofenceCircle.toWritableMap(): WritableMap = Arguments.createMap().apply {
581
- putNullableId("campaignId", campaignId)
582
- putNullableString("campaignName", campaignName)
583
- putNullableId("locationId", locationId)
584
- putMap(
585
- "center",
586
- Arguments.createMap().apply {
587
- putDouble("latitude", center.latitude)
588
- putDouble("longitude", center.longitude)
589
- }
590
- )
591
- putDouble("radius", radiusMeters)
592
- }
593
-
594
- private fun ReadableMap.requiredString(key: String): String =
595
- string(key)?.takeIf { it.isNotBlank() } ?: throw IllegalArgumentException("$key is required")
596
-
597
- private fun ReadableMap.string(key: String): String? =
598
- if (hasKey(key) && !isNull(key)) getString(key) else null
599
-
600
- private fun ReadableMap.bool(key: String, default: Boolean): Boolean =
601
- if (hasKey(key) && !isNull(key)) getBoolean(key) else default
602
-
603
- private fun ReadableMap.int(key: String, default: Int): Int =
604
- if (hasKey(key) && !isNull(key)) getDouble(key).toInt() else default
605
-
606
- private fun ReadableMap.nullableDouble(key: String): Double? =
607
- if (hasKey(key) && !isNull(key)) getDouble(key) else null
608
-
609
- private fun ReadableMap.map(key: String): ReadableMap? =
610
- if (hasKey(key) && !isNull(key)) getMap(key) else null
611
-
612
- private fun ReadableMap.stringList(key: String): List<String> =
613
- if (hasKey(key) && !isNull(key)) getArray(key)?.stringList().orEmpty() else emptyList()
614
-
615
- private fun ReadableMap.mapList(key: String): List<ReadableMap> =
616
- if (hasKey(key) && !isNull(key)) getArray(key)?.mapList().orEmpty() else emptyList()
617
-
618
- private fun ReadableMap.stringMap(): Map<String, String> {
619
- val output = mutableMapOf<String, String>()
620
- val iterator = keySetIterator()
621
- while (iterator.hasNextKey()) {
622
- val key = iterator.nextKey()
623
- if (!isNull(key)) {
624
- output[key] = when (getType(key).name) {
625
- "Boolean" -> getBoolean(key).toString()
626
- "Number" -> getDouble(key).toString()
627
- "String" -> getString(key).orEmpty()
628
- else -> getDynamic(key).toString()
629
- }
630
- }
631
- }
632
- return output
633
- }
634
-
635
- private fun ReadableArray.stringList(): List<String> =
636
- (0 until size()).mapNotNull { index ->
637
- if (isNull(index)) null else getString(index)
638
- }
639
-
640
- private fun ReadableArray.mapList(): List<ReadableMap> =
641
- (0 until size()).mapNotNull { index ->
642
- if (isNull(index)) null else getMap(index)
643
- }
644
-
645
- private fun List<String>.toWritableStringArray(): WritableArray = Arguments.createArray().also { array ->
646
- forEach { array.pushString(it) }
647
- }
648
-
649
- private fun List<WritableMap>.toWritableMapArray(): WritableArray = Arguments.createArray().also { array ->
650
- forEach { array.pushMap(it) }
651
- }
652
-
653
- private fun Map<String, String>.toWritableMap(): WritableMap = Arguments.createMap().apply {
654
- forEach { (key, value) -> putString(key, value) }
655
- }
656
-
657
- private fun WritableMap.putNullableString(key: String, value: String?) {
658
- if (value == null) putNull(key) else putString(key, value)
659
- }
660
-
661
- private fun WritableMap.putNullableMap(key: String, value: WritableMap?) {
662
- if (value == null) putNull(key) else putMap(key, value)
663
- }
664
-
665
- private fun WritableMap.putNullableId(key: String, value: String?) {
666
- when {
667
- value == null -> putNull(key)
668
- value.toIntOrNull() != null -> putInt(key, value.toInt())
669
- else -> putString(key, value)
670
- }
671
- }
672
-
673
- private fun <T> enumValue(value: String?, default: T, block: (String) -> T): T =
674
- value?.let { runCatching { block(it) }.getOrNull() } ?: default
675
-
676
- companion object {
677
- const val NAME = "BubblSdk"
678
- private const val EVENT_NAME = "BubblSdkEvent"
679
- }
680
- }