react-native-marketap-sdk 0.1.0-beta.9 → 1.1.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.
Files changed (46) hide show
  1. package/android/build.gradle +1 -1
  2. package/android/src/main/AndroidManifest.xml +1 -10
  3. package/android/src/main/java/com/marketapsdk/MarketapSdkModule.kt +318 -78
  4. package/android/src/main/java/com/marketapsdk/ReactNativeBridgeRegistry.kt +110 -0
  5. package/ios/MarketapSdk.m +37 -23
  6. package/ios/MarketapSdk.swift +254 -162
  7. package/lib/commonjs/MarketapWebBridge.js +211 -16
  8. package/lib/commonjs/MarketapWebBridge.js.map +1 -1
  9. package/lib/commonjs/core/MarketapCore.js +247 -0
  10. package/lib/commonjs/core/MarketapCore.js.map +1 -0
  11. package/lib/commonjs/index.js +20 -165
  12. package/lib/commonjs/index.js.map +1 -1
  13. package/lib/commonjs/internal/marketapCore.js +9 -0
  14. package/lib/commonjs/internal/marketapCore.js.map +1 -0
  15. package/lib/commonjs/internal/marketapPlugin.js +46 -0
  16. package/lib/commonjs/internal/marketapPlugin.js.map +1 -0
  17. package/lib/commonjs/version.js +1 -1
  18. package/lib/commonjs/version.js.map +1 -1
  19. package/lib/module/MarketapWebBridge.js +210 -16
  20. package/lib/module/MarketapWebBridge.js.map +1 -1
  21. package/lib/module/core/MarketapCore.js +240 -0
  22. package/lib/module/core/MarketapCore.js.map +1 -0
  23. package/lib/module/index.js +20 -164
  24. package/lib/module/index.js.map +1 -1
  25. package/lib/module/internal/marketapCore.js +3 -0
  26. package/lib/module/internal/marketapCore.js.map +1 -0
  27. package/lib/module/internal/marketapPlugin.js +41 -0
  28. package/lib/module/internal/marketapPlugin.js.map +1 -0
  29. package/lib/module/version.js +1 -1
  30. package/lib/module/version.js.map +1 -1
  31. package/lib/typescript/MarketapWebBridge.d.ts +33 -6
  32. package/lib/typescript/MarketapWebBridge.d.ts.map +1 -1
  33. package/lib/typescript/core/MarketapCore.d.ts +57 -0
  34. package/lib/typescript/core/MarketapCore.d.ts.map +1 -0
  35. package/lib/typescript/index.d.ts +2 -41
  36. package/lib/typescript/index.d.ts.map +1 -1
  37. package/lib/typescript/internal/marketapCore.d.ts +3 -0
  38. package/lib/typescript/internal/marketapCore.d.ts.map +1 -0
  39. package/lib/typescript/internal/marketapPlugin.d.ts +12 -0
  40. package/lib/typescript/internal/marketapPlugin.d.ts.map +1 -0
  41. package/lib/typescript/types.d.ts +1 -2
  42. package/lib/typescript/types.d.ts.map +1 -1
  43. package/lib/typescript/version.d.ts +1 -1
  44. package/lib/typescript/version.d.ts.map +1 -1
  45. package/package.json +1 -1
  46. package/react-native-marketap-sdk.podspec +1 -1
@@ -99,7 +99,7 @@ dependencies {
99
99
  implementation "com.facebook.react:react-native:+"
100
100
 
101
101
  // MarketapSDK dependency with forced version constraints
102
- implementation('com.github.marketap-dev:marketap-android-sdk:1.1.7') {
102
+ implementation('com.github.marketap-dev:marketap-android-sdk:1.4.0') {
103
103
  exclude group: 'androidx.appcompat', module: 'appcompat'
104
104
  exclude group: 'androidx.core', module: 'core-ktx'
105
105
  }
@@ -1,12 +1,3 @@
1
1
  <manifest xmlns:android="http://schemas.android.com/apk/res/android"
2
2
  package="com.marketapsdk">
3
- <application>
4
- <service
5
- android:name="com.marketap.sdk.client.push.MarketapFirebaseMessagingService"
6
- android:exported="false">
7
- <intent-filter>
8
- <action android:name="com.google.firebase.MESSAGING_EVENT" />
9
- </intent-filter>
10
- </service>
11
- </application>
12
- </manifest>
3
+ </manifest>
@@ -13,7 +13,10 @@ import com.facebook.react.bridge.Arguments
13
13
  import com.facebook.react.modules.core.DeviceEventManagerModule
14
14
  import com.facebook.react.bridge.LifecycleEventListener
15
15
  import com.marketap.sdk.Marketap
16
+ import com.marketap.sdk.MarketapPlugin
17
+ import com.marketap.sdk.MarketapWebBridge
16
18
  import com.marketap.sdk.model.external.MarketapCampaignType
19
+ import com.marketap.sdk.model.external.MarketapIntegrationInfo
17
20
  import com.marketap.sdk.model.external.MarketapLogLevel
18
21
  import com.marketap.sdk.client.CurrentActivityHolder
19
22
 
@@ -22,36 +25,50 @@ private fun ReadableMap?.toNonNullableMap(): Map<String, Any>? {
22
25
  }
23
26
 
24
27
  class MarketapSdkModule(reactContext: ReactApplicationContext) :
25
- ReactContextBaseJavaModule(reactContext), LifecycleEventListener {
28
+ ReactContextBaseJavaModule(reactContext), LifecycleEventListener, ReactNativeBridgeTarget {
26
29
 
27
30
  companion object {
28
31
  const val NAME = "MarketapSdk"
29
32
  private const val CLICK_EVENT = "MarketapClickEvent"
30
-
31
- private var pendingClickEvent: WritableMap? = null
33
+ private const val IN_APP_MESSAGE_EVENT = "MarketapInAppMessageEvent"
34
+
35
+ private var isExternalInAppCallbackRegistered = false
32
36
  }
33
37
 
34
38
  private var hasListeners = false
35
- private var isHostResumed = false
36
39
  private var isInitialized = false
37
40
  private var initializedProjectId: String? = null
41
+ private var clickHandlerRegistered = false
42
+ private var isModuleActive = true
38
43
 
39
44
  init {
40
45
  reactApplicationContext.addLifecycleEventListener(this)
46
+ ReactNativeBridgeRegistry.register(this)
47
+ registerExternalInAppCallback()
41
48
  }
42
49
 
43
50
  override fun getName(): String {
44
51
  return NAME
45
52
  }
46
53
 
54
+ override val isAttachedToReact: Boolean
55
+ get() = isModuleActive
56
+
57
+ override val isClickHandlerRegistered: Boolean
58
+ get() = clickHandlerRegistered
59
+
60
+ override val isReactReady: Boolean
61
+ get() = isModuleActive && hasListeners && isReactInstanceReady()
62
+
47
63
  @ReactMethod
48
- fun initialize(projectId: String, promise: Promise) {
64
+ fun initialize(payload: ReadableMap?, promise: Promise) {
49
65
  try {
66
+ val projectId = payload?.getString("projectId") ?: ""
50
67
  if (!isMainProcess()) {
51
68
  promise.resolve(null)
52
69
  return
53
70
  }
54
-
71
+
55
72
  if (isInitialized) {
56
73
  if (initializedProjectId == projectId) {
57
74
  promise.resolve(null)
@@ -62,11 +79,17 @@ class MarketapSdkModule(reactContext: ReactApplicationContext) :
62
79
  return
63
80
  }
64
81
  }
65
-
82
+
66
83
  // Initialize MarketapSDK with projectId
67
84
  val application = reactApplicationContext.applicationContext as Application
85
+ val sdkType = payload?.getString("sdkType") ?: "react_native"
86
+ val sdkVersion = payload?.getString("sdkVersion") ?: "unknown"
68
87
  CurrentActivityHolder.applyToApplication(application)
69
- Marketap.initialize(application, projectId)
88
+ MarketapPlugin.initialize(
89
+ application,
90
+ projectId,
91
+ MarketapIntegrationInfo(sdkType = sdkType, sdkVersion = sdkVersion)
92
+ )
70
93
  isInitialized = true
71
94
  initializedProjectId = projectId
72
95
  promise.resolve(null)
@@ -76,29 +99,48 @@ class MarketapSdkModule(reactContext: ReactApplicationContext) :
76
99
  }
77
100
 
78
101
  @ReactMethod
79
- fun setLogLevel(logLevel: Int) {
102
+ fun setLogLevel(payload: ReadableMap?) {
103
+ val logLevel =
104
+ if (payload != null && payload.hasKey("logLevel") && !payload.isNull("logLevel")) {
105
+ payload.getInt("logLevel")
106
+ } else {
107
+ 0
108
+ }
80
109
  val resolvedLevel = MarketapLogLevel.values().firstOrNull { level ->
81
110
  level.value == logLevel
82
111
  } ?: MarketapLogLevel.NONE
83
112
  Marketap.setLogLevel(resolvedLevel)
84
113
  }
85
-
114
+
86
115
  private fun isMainProcess(): Boolean {
87
116
  val am = reactApplicationContext.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
88
117
  return am.runningAppProcesses?.find { it.pid == android.os.Process.myPid() }?.processName == reactApplicationContext.packageName
89
118
  }
90
119
 
91
120
  @ReactMethod
92
- fun signup(
93
- userId: String,
94
- userProperties: ReadableMap?,
95
- eventProperties: ReadableMap?,
96
- persistUser: Boolean?,
97
- promise: Promise
98
- ) {
121
+ fun signup(payload: ReadableMap?, promise: Promise) {
99
122
  try {
123
+ val userId = payload?.getString("userId") ?: ""
124
+ val userProperties =
125
+ if (payload != null && payload.hasKey("userProperties") && !payload.isNull("userProperties")) {
126
+ payload.getMap("userProperties")
127
+ } else {
128
+ null
129
+ }
130
+ val eventProperties =
131
+ if (payload != null && payload.hasKey("eventProperties") && !payload.isNull("eventProperties")) {
132
+ payload.getMap("eventProperties")
133
+ } else {
134
+ null
135
+ }
136
+ val persistUser =
137
+ if (payload != null && payload.hasKey("persistUser") && !payload.isNull("persistUser")) {
138
+ payload.getBoolean("persistUser")
139
+ } else {
140
+ true
141
+ }
100
142
  // Call MarketapSDK signup method
101
- Marketap.signup(userId, userProperties.toNonNullableMap(), eventProperties.toNonNullableMap(), persistUser ?: true)
143
+ Marketap.signup(userId, userProperties.toNonNullableMap(), eventProperties.toNonNullableMap(), persistUser)
102
144
  promise.resolve(null)
103
145
  } catch (e: Exception) {
104
146
  promise.reject("SIGNUP_ERROR", e.message, e)
@@ -106,13 +148,21 @@ class MarketapSdkModule(reactContext: ReactApplicationContext) :
106
148
  }
107
149
 
108
150
  @ReactMethod
109
- fun login(
110
- userId: String,
111
- userProperties: ReadableMap?,
112
- eventProperties: ReadableMap?,
113
- promise: Promise
114
- ) {
151
+ fun login(payload: ReadableMap?, promise: Promise) {
115
152
  try {
153
+ val userId = payload?.getString("userId") ?: ""
154
+ val userProperties =
155
+ if (payload != null && payload.hasKey("userProperties") && !payload.isNull("userProperties")) {
156
+ payload.getMap("userProperties")
157
+ } else {
158
+ null
159
+ }
160
+ val eventProperties =
161
+ if (payload != null && payload.hasKey("eventProperties") && !payload.isNull("eventProperties")) {
162
+ payload.getMap("eventProperties")
163
+ } else {
164
+ null
165
+ }
116
166
  // Call MarketapSDK login method
117
167
  Marketap.login(userId, userProperties.toNonNullableMap(), eventProperties.toNonNullableMap())
118
168
  promise.resolve(null)
@@ -122,8 +172,14 @@ class MarketapSdkModule(reactContext: ReactApplicationContext) :
122
172
  }
123
173
 
124
174
  @ReactMethod
125
- fun logout(eventProperties: ReadableMap?, promise: Promise) {
175
+ fun logout(payload: ReadableMap?, promise: Promise) {
126
176
  try {
177
+ val eventProperties =
178
+ if (payload != null && payload.hasKey("eventProperties") && !payload.isNull("eventProperties")) {
179
+ payload.getMap("eventProperties")
180
+ } else {
181
+ null
182
+ }
127
183
  // Call MarketapSDK logout method
128
184
  Marketap.logout(eventProperties.toNonNullableMap())
129
185
  promise.resolve(null)
@@ -133,8 +189,15 @@ class MarketapSdkModule(reactContext: ReactApplicationContext) :
133
189
  }
134
190
 
135
191
  @ReactMethod
136
- fun track(eventName: String, eventProperties: ReadableMap?, promise: Promise) {
192
+ fun track(payload: ReadableMap?, promise: Promise) {
137
193
  try {
194
+ val eventName = payload?.getString("eventName") ?: ""
195
+ val eventProperties =
196
+ if (payload != null && payload.hasKey("eventProperties") && !payload.isNull("eventProperties")) {
197
+ payload.getMap("eventProperties")
198
+ } else {
199
+ null
200
+ }
138
201
  // Call MarketapSDK track method
139
202
  Marketap.track(eventName, eventProperties.toNonNullableMap())
140
203
  promise.resolve(null)
@@ -144,8 +207,20 @@ class MarketapSdkModule(reactContext: ReactApplicationContext) :
144
207
  }
145
208
 
146
209
  @ReactMethod
147
- fun trackPurchase(revenue: Double, eventProperties: ReadableMap?, promise: Promise) {
210
+ fun trackPurchase(payload: ReadableMap?, promise: Promise) {
148
211
  try {
212
+ val revenue =
213
+ if (payload != null && payload.hasKey("revenue") && !payload.isNull("revenue")) {
214
+ payload.getDouble("revenue")
215
+ } else {
216
+ 0.0
217
+ }
218
+ val eventProperties =
219
+ if (payload != null && payload.hasKey("eventProperties") && !payload.isNull("eventProperties")) {
220
+ payload.getMap("eventProperties")
221
+ } else {
222
+ null
223
+ }
149
224
  // Call MarketapSDK trackPurchase method
150
225
  Marketap.trackPurchase(revenue, eventProperties.toNonNullableMap())
151
226
  promise.resolve(null)
@@ -155,13 +230,21 @@ class MarketapSdkModule(reactContext: ReactApplicationContext) :
155
230
  }
156
231
 
157
232
  @ReactMethod
158
- fun trackRevenue(
159
- eventName: String,
160
- revenue: Double,
161
- eventProperties: ReadableMap?,
162
- promise: Promise
163
- ) {
233
+ fun trackRevenue(payload: ReadableMap?, promise: Promise) {
164
234
  try {
235
+ val eventName = payload?.getString("eventName") ?: ""
236
+ val revenue =
237
+ if (payload != null && payload.hasKey("revenue") && !payload.isNull("revenue")) {
238
+ payload.getDouble("revenue")
239
+ } else {
240
+ 0.0
241
+ }
242
+ val eventProperties =
243
+ if (payload != null && payload.hasKey("eventProperties") && !payload.isNull("eventProperties")) {
244
+ payload.getMap("eventProperties")
245
+ } else {
246
+ null
247
+ }
165
248
  // Call MarketapSDK trackRevenue method
166
249
  Marketap.trackRevenue(eventName, revenue, eventProperties.toNonNullableMap())
167
250
  promise.resolve(null)
@@ -171,8 +254,14 @@ class MarketapSdkModule(reactContext: ReactApplicationContext) :
171
254
  }
172
255
 
173
256
  @ReactMethod
174
- fun trackPageView(eventProperties: ReadableMap?, promise: Promise) {
257
+ fun trackPageView(payload: ReadableMap?, promise: Promise) {
175
258
  try {
259
+ val eventProperties =
260
+ if (payload != null && payload.hasKey("eventProperties") && !payload.isNull("eventProperties")) {
261
+ payload.getMap("eventProperties")
262
+ } else {
263
+ null
264
+ }
176
265
  // Call MarketapSDK trackPageView method
177
266
  Marketap.trackPageView(eventProperties.toNonNullableMap())
178
267
  promise.resolve(null)
@@ -182,8 +271,15 @@ class MarketapSdkModule(reactContext: ReactApplicationContext) :
182
271
  }
183
272
 
184
273
  @ReactMethod
185
- fun identify(userId: String, userProperties: ReadableMap?, promise: Promise) {
274
+ fun identify(payload: ReadableMap?, promise: Promise) {
186
275
  try {
276
+ val userId = payload?.getString("userId") ?: ""
277
+ val userProperties =
278
+ if (payload != null && payload.hasKey("userProperties") && !payload.isNull("userProperties")) {
279
+ payload.getMap("userProperties")
280
+ } else {
281
+ null
282
+ }
187
283
  // Call MarketapSDK identify method
188
284
  Marketap.identify(userId, userProperties.toNonNullableMap())
189
285
  promise.resolve(null)
@@ -206,14 +302,14 @@ class MarketapSdkModule(reactContext: ReactApplicationContext) :
206
302
  @ReactMethod
207
303
  fun setClickHandler(promise: Promise) {
208
304
  try {
209
- hasListeners = true
305
+ clickHandlerRegistered = true
210
306
  Marketap.setClickHandler { event ->
211
307
  val clickData = convertClickEventToMap(event)
212
-
213
- deliverOrStoreClick(clickData)
308
+
309
+ ReactNativeBridgeRegistry.deliverClick(clickData)
214
310
  }
215
311
 
216
- flushPendingClick()
312
+ ReactNativeBridgeRegistry.flushIfPending()
217
313
  promise.resolve(null)
218
314
  } catch (e: Exception) {
219
315
  promise.reject("SET_CLICK_HANDLER_ERROR", e.message, e)
@@ -234,35 +330,165 @@ class MarketapSdkModule(reactContext: ReactApplicationContext) :
234
330
  }
235
331
  }
236
332
 
333
+ // 웹브릿지 인앱 메시지 관련 메서드
334
+ @ReactMethod
335
+ fun trackFromWebBridge(payload: ReadableMap?, promise: Promise) {
336
+ try {
337
+ val eventName = payload?.getString("eventName") ?: ""
338
+ val eventProperties =
339
+ if (payload != null && payload.hasKey("eventProperties") && !payload.isNull("eventProperties")) {
340
+ payload.getMap("eventProperties")
341
+ } else {
342
+ null
343
+ }
344
+ val handleInAppInReactNative =
345
+ if (payload != null && payload.hasKey("handleInAppInReactNative") && !payload.isNull("handleInAppInReactNative")) {
346
+ payload.getBoolean("handleInAppInReactNative")
347
+ } else {
348
+ false
349
+ }
350
+ if (handleInAppInReactNative) {
351
+ ReactNativeBridgeRegistry.setWebBridgeSourceTarget(this)
352
+ MarketapWebBridge.setExternalWebBridgeActive(true)
353
+ } else {
354
+ ReactNativeBridgeRegistry.clearWebBridgeSourceTarget()
355
+ MarketapWebBridge.setExternalWebBridgeActive(false)
356
+ }
357
+ MarketapPlugin.trackEvent(eventName, eventProperties.toNonNullableMap())
358
+ promise.resolve(null)
359
+ } catch (e: Exception) {
360
+ promise.reject("TRACK_FROM_WEB_BRIDGE_ERROR", e.message, e)
361
+ }
362
+ }
363
+
364
+ @ReactMethod
365
+ fun onWebBridgeConnected(payload: ReadableMap?, promise: Promise) {
366
+ try {
367
+ val handleInAppInReactNative =
368
+ if (payload != null && payload.hasKey("handleInAppInReactNative") && !payload.isNull("handleInAppInReactNative")) {
369
+ payload.getBoolean("handleInAppInReactNative")
370
+ } else {
371
+ true
372
+ }
373
+ MarketapPlugin.onWebBridgeConnected(handleInAppInReactNative)
374
+ promise.resolve(null)
375
+ } catch (e: Exception) {
376
+ promise.reject("ON_WEB_BRIDGE_CONNECTED_ERROR", e.message, e)
377
+ }
378
+ }
379
+
237
380
  @ReactMethod
238
- fun setPushToken(token: String, promise: Promise) {
381
+ fun onWebSdkInitialized(promise: Promise) {
239
382
  try {
240
- // Android: setPushToken not available - MarketapFirebaseMessagingService handles tokens automatically
383
+ MarketapPlugin.onWebSdkInitialized()
241
384
  promise.resolve(null)
242
385
  } catch (e: Exception) {
243
- promise.reject("PUSH_TOKEN_ERROR", e.message, e)
386
+ promise.reject("ON_WEB_SDK_INITIALIZED_ERROR", e.message, e)
244
387
  }
245
388
  }
246
-
389
+
247
390
  @ReactMethod
248
- fun getInitialNotification(promise: Promise) {
391
+ fun setUserProperties(payload: ReadableMap?, promise: Promise) {
249
392
  try {
250
- val pendingEvent = pendingClickEvent
251
- if (pendingEvent != null) {
252
- pendingClickEvent = null
253
- promise.resolve(pendingEvent)
254
- } else {
393
+ val userProperties =
394
+ if (payload != null && payload.hasKey("userProperties") && !payload.isNull("userProperties")) {
395
+ payload.getMap("userProperties")
396
+ } else {
397
+ null
398
+ }
399
+ val props = userProperties.toNonNullableMap()
400
+ if (props == null) {
401
+ promise.reject("ARG_ERROR", "Missing userProperties", null)
402
+ return
403
+ }
404
+ MarketapPlugin.setUserProperties(props)
405
+ promise.resolve(null)
406
+ } catch (e: Exception) {
407
+ promise.reject("SET_USER_PROPERTIES_ERROR", e.message, e)
408
+ }
409
+ }
410
+
411
+ @ReactMethod
412
+ fun trackInAppImpression(payload: ReadableMap?, promise: Promise) {
413
+ try {
414
+ val campaignId = payload?.getString("campaignId")
415
+ val messageId = payload?.getString("messageId")
416
+ val layoutSubType = payload?.getString("layoutSubType")
417
+ if (campaignId == null || messageId == null) {
418
+ android.util.Log.w(
419
+ NAME,
420
+ "trackInAppImpression: missing required params (campaignId=$campaignId, messageId=$messageId)"
421
+ )
422
+ promise.resolve(null)
423
+ return
424
+ }
425
+ MarketapPlugin.trackInAppImpression(campaignId, messageId, layoutSubType)
426
+ promise.resolve(null)
427
+ } catch (e: Exception) {
428
+ promise.reject("TRACK_INAPP_IMPRESSION_ERROR", e.message, e)
429
+ }
430
+ }
431
+
432
+ @ReactMethod
433
+ fun trackInAppClick(payload: ReadableMap?, promise: Promise) {
434
+ try {
435
+ val campaignId = payload?.getString("campaignId")
436
+ val messageId = payload?.getString("messageId")
437
+ val locationId = payload?.getString("locationId")
438
+ val url = payload?.getString("url")
439
+ val layoutSubType = payload?.getString("layoutSubType")
440
+ if (campaignId == null || messageId == null || locationId == null) {
441
+ android.util.Log.w(
442
+ NAME,
443
+ "trackInAppClick: missing required params (campaignId=$campaignId, messageId=$messageId, locationId=$locationId)"
444
+ )
255
445
  promise.resolve(null)
446
+ return
256
447
  }
448
+ MarketapPlugin.trackInAppClick(campaignId, messageId, locationId, url, layoutSubType)
449
+ promise.resolve(null)
257
450
  } catch (e: Exception) {
258
- promise.reject("GET_INITIAL_NOTIFICATION_ERROR", e.message, e)
451
+ promise.reject("TRACK_INAPP_CLICK_ERROR", e.message, e)
452
+ }
453
+ }
454
+
455
+ @ReactMethod
456
+ fun hideCampaign(payload: ReadableMap?, promise: Promise) {
457
+ try {
458
+ val campaignId = payload?.getString("campaignId")
459
+ val hideType = payload?.getString("hideType")
460
+ if (campaignId == null) {
461
+ android.util.Log.w(NAME, "hideCampaign: missing campaignId")
462
+ promise.resolve(null)
463
+ return
464
+ }
465
+ MarketapPlugin.hideInAppMessage(campaignId, hideType)
466
+ promise.resolve(null)
467
+ } catch (e: Exception) {
468
+ promise.reject("HIDE_CAMPAIGN_ERROR", e.message, e)
469
+ }
470
+ }
471
+
472
+ @ReactMethod
473
+ fun setDeviceOptIn(payload: ReadableMap?, promise: Promise) {
474
+ try {
475
+ val optIn: Boolean? =
476
+ if (payload != null && payload.hasKey("optIn") && !payload.isNull("optIn")) {
477
+ payload.getBoolean("optIn")
478
+ } else {
479
+ null
480
+ }
481
+ Marketap.setDeviceOptIn(optIn)
482
+ promise.resolve(null)
483
+ } catch (e: Exception) {
484
+ promise.reject("SET_DEVICE_OPT_IN_ERROR", e.message, e)
259
485
  }
260
486
  }
261
487
 
262
488
  @ReactMethod
263
489
  fun addListener(eventName: String) {
264
490
  hasListeners = true
265
- flushPendingClick()
491
+ ReactNativeBridgeRegistry.flushIfPending()
266
492
  }
267
493
 
268
494
  @ReactMethod
@@ -271,7 +497,7 @@ class MarketapSdkModule(reactContext: ReactApplicationContext) :
271
497
  }
272
498
 
273
499
  private fun sendEvent(eventName: String, params: WritableMap?): Boolean {
274
- if (!hasListeners || !isReactReady()) {
500
+ if (!hasListeners || !isReactInstanceReady()) {
275
501
  return false
276
502
  }
277
503
  reactApplicationContext.runOnJSQueueThread {
@@ -282,28 +508,7 @@ class MarketapSdkModule(reactContext: ReactApplicationContext) :
282
508
  return true
283
509
  }
284
510
 
285
- private fun deliverOrStoreClick(clickData: WritableMap) {
286
- if (hasListeners && isHostResumed && isReactReady()) {
287
- if (sendEvent(CLICK_EVENT, clickData)) {
288
- pendingClickEvent = null
289
- } else {
290
- pendingClickEvent = clickData
291
- }
292
- } else {
293
- pendingClickEvent = clickData
294
- }
295
- }
296
-
297
- private fun flushPendingClick() {
298
- val pendingEvent = pendingClickEvent
299
- if (pendingEvent != null && hasListeners && isHostResumed && isReactReady()) {
300
- if (sendEvent(CLICK_EVENT, pendingEvent)) {
301
- pendingClickEvent = null
302
- }
303
- }
304
- }
305
-
306
- private fun isReactReady(): Boolean {
511
+ private fun isReactInstanceReady(): Boolean {
307
512
  return reactApplicationContext.hasActiveCatalystInstance() &&
308
513
  reactApplicationContext.hasActiveReactInstance()
309
514
  }
@@ -321,17 +526,52 @@ class MarketapSdkModule(reactContext: ReactApplicationContext) :
321
526
  return map
322
527
  }
323
528
 
529
+ override fun sendInAppMessage(
530
+ campaign: Map<String, Any?>,
531
+ messageId: String,
532
+ shouldHandleUrlRouting: Boolean
533
+ ) {
534
+ val args = Arguments.createMap()
535
+ args.putMap("campaign", Arguments.makeNativeMap(campaign))
536
+ args.putString("messageId", messageId)
537
+ args.putBoolean("shouldHandleUrlRouting", shouldHandleUrlRouting)
538
+ sendEvent(IN_APP_MESSAGE_EVENT, args)
539
+ }
540
+
541
+ override fun sendClick(clickData: WritableMap) {
542
+ sendEvent(CLICK_EVENT, clickData)
543
+ }
544
+
324
545
  override fun onHostResume() {
325
- isHostResumed = true
326
- flushPendingClick()
546
+ val activity = getCurrentActivity() ?: return
547
+ CurrentActivityHolder.set(activity)
548
+ ReactNativeBridgeRegistry.flushIfPending()
327
549
  }
328
550
 
329
551
  override fun onHostPause() {
330
- isHostResumed = false
331
552
  }
332
553
 
333
554
  override fun onHostDestroy() {
334
- isHostResumed = false
555
+ isModuleActive = false
556
+ ReactNativeBridgeRegistry.unregister(this)
557
+ reactApplicationContext.removeLifecycleEventListener(this)
558
+ }
559
+
560
+ override fun invalidate() {
561
+ isModuleActive = false
562
+ ReactNativeBridgeRegistry.unregister(this)
335
563
  reactApplicationContext.removeLifecycleEventListener(this)
564
+ super.invalidate()
565
+ }
566
+
567
+ private fun registerExternalInAppCallback() {
568
+ if (isExternalInAppCallbackRegistered) {
569
+ return
570
+ }
571
+ isExternalInAppCallbackRegistered = true
572
+
573
+ MarketapWebBridge.setExternalInAppMessageCallback { campaign, messageId, shouldHandleUrlRouting ->
574
+ ReactNativeBridgeRegistry.sendInAppMessage(campaign, messageId, shouldHandleUrlRouting)
575
+ }
336
576
  }
337
577
  }