react-native-marketap-sdk 0.1.0-beta.9 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/build.gradle +1 -1
- package/android/src/main/AndroidManifest.xml +1 -10
- package/android/src/main/java/com/marketapsdk/MarketapSdkModule.kt +284 -77
- package/android/src/main/java/com/marketapsdk/ReactNativeBridgeRegistry.kt +110 -0
- package/ios/MarketapSdk.m +30 -23
- package/ios/MarketapSdk.swift +232 -162
- package/lib/commonjs/MarketapWebBridge.js +205 -15
- package/lib/commonjs/MarketapWebBridge.js.map +1 -1
- package/lib/commonjs/core/MarketapCore.js +233 -0
- package/lib/commonjs/core/MarketapCore.js.map +1 -0
- package/lib/commonjs/index.js +20 -165
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/internal/marketapCore.js +9 -0
- package/lib/commonjs/internal/marketapCore.js.map +1 -0
- package/lib/commonjs/internal/marketapPlugin.js +40 -0
- package/lib/commonjs/internal/marketapPlugin.js.map +1 -0
- package/lib/commonjs/version.js +1 -1
- package/lib/commonjs/version.js.map +1 -1
- package/lib/module/MarketapWebBridge.js +204 -15
- package/lib/module/MarketapWebBridge.js.map +1 -1
- package/lib/module/core/MarketapCore.js +226 -0
- package/lib/module/core/MarketapCore.js.map +1 -0
- package/lib/module/index.js +20 -164
- package/lib/module/index.js.map +1 -1
- package/lib/module/internal/marketapCore.js +3 -0
- package/lib/module/internal/marketapCore.js.map +1 -0
- package/lib/module/internal/marketapPlugin.js +35 -0
- package/lib/module/internal/marketapPlugin.js.map +1 -0
- package/lib/module/version.js +1 -1
- package/lib/module/version.js.map +1 -1
- package/lib/typescript/MarketapWebBridge.d.ts +33 -6
- package/lib/typescript/MarketapWebBridge.d.ts.map +1 -1
- package/lib/typescript/core/MarketapCore.d.ts +54 -0
- package/lib/typescript/core/MarketapCore.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +2 -41
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/internal/marketapCore.d.ts +3 -0
- package/lib/typescript/internal/marketapCore.d.ts.map +1 -0
- package/lib/typescript/internal/marketapPlugin.d.ts +10 -0
- package/lib/typescript/internal/marketapPlugin.d.ts.map +1 -0
- package/lib/typescript/types.d.ts +1 -2
- package/lib/typescript/types.d.ts.map +1 -1
- package/lib/typescript/version.d.ts +1 -1
- package/lib/typescript/version.d.ts.map +1 -1
- package/package.json +1 -1
- package/react-native-marketap-sdk.podspec +1 -1
package/android/build.gradle
CHANGED
|
@@ -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.
|
|
102
|
+
implementation('com.github.marketap-dev:marketap-android-sdk:1.3.3') {
|
|
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
|
-
|
|
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,6 +13,8 @@ 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
|
|
17
19
|
import com.marketap.sdk.model.external.MarketapLogLevel
|
|
18
20
|
import com.marketap.sdk.client.CurrentActivityHolder
|
|
@@ -22,36 +24,50 @@ private fun ReadableMap?.toNonNullableMap(): Map<String, Any>? {
|
|
|
22
24
|
}
|
|
23
25
|
|
|
24
26
|
class MarketapSdkModule(reactContext: ReactApplicationContext) :
|
|
25
|
-
ReactContextBaseJavaModule(reactContext), LifecycleEventListener {
|
|
27
|
+
ReactContextBaseJavaModule(reactContext), LifecycleEventListener, ReactNativeBridgeTarget {
|
|
26
28
|
|
|
27
29
|
companion object {
|
|
28
30
|
const val NAME = "MarketapSdk"
|
|
29
31
|
private const val CLICK_EVENT = "MarketapClickEvent"
|
|
30
|
-
|
|
31
|
-
|
|
32
|
+
private const val IN_APP_MESSAGE_EVENT = "MarketapInAppMessageEvent"
|
|
33
|
+
|
|
34
|
+
private var isExternalInAppCallbackRegistered = false
|
|
32
35
|
}
|
|
33
36
|
|
|
34
37
|
private var hasListeners = false
|
|
35
|
-
private var isHostResumed = false
|
|
36
38
|
private var isInitialized = false
|
|
37
39
|
private var initializedProjectId: String? = null
|
|
40
|
+
private var clickHandlerRegistered = false
|
|
41
|
+
private var isModuleActive = true
|
|
38
42
|
|
|
39
43
|
init {
|
|
40
44
|
reactApplicationContext.addLifecycleEventListener(this)
|
|
45
|
+
ReactNativeBridgeRegistry.register(this)
|
|
46
|
+
registerExternalInAppCallback()
|
|
41
47
|
}
|
|
42
48
|
|
|
43
49
|
override fun getName(): String {
|
|
44
50
|
return NAME
|
|
45
51
|
}
|
|
46
52
|
|
|
53
|
+
override val isAttachedToReact: Boolean
|
|
54
|
+
get() = isModuleActive
|
|
55
|
+
|
|
56
|
+
override val isClickHandlerRegistered: Boolean
|
|
57
|
+
get() = clickHandlerRegistered
|
|
58
|
+
|
|
59
|
+
override val isReactReady: Boolean
|
|
60
|
+
get() = isModuleActive && hasListeners && isReactInstanceReady()
|
|
61
|
+
|
|
47
62
|
@ReactMethod
|
|
48
|
-
fun initialize(
|
|
63
|
+
fun initialize(payload: ReadableMap?, promise: Promise) {
|
|
49
64
|
try {
|
|
65
|
+
val projectId = payload?.getString("projectId") ?: ""
|
|
50
66
|
if (!isMainProcess()) {
|
|
51
67
|
promise.resolve(null)
|
|
52
68
|
return
|
|
53
69
|
}
|
|
54
|
-
|
|
70
|
+
|
|
55
71
|
if (isInitialized) {
|
|
56
72
|
if (initializedProjectId == projectId) {
|
|
57
73
|
promise.resolve(null)
|
|
@@ -62,7 +78,7 @@ class MarketapSdkModule(reactContext: ReactApplicationContext) :
|
|
|
62
78
|
return
|
|
63
79
|
}
|
|
64
80
|
}
|
|
65
|
-
|
|
81
|
+
|
|
66
82
|
// Initialize MarketapSDK with projectId
|
|
67
83
|
val application = reactApplicationContext.applicationContext as Application
|
|
68
84
|
CurrentActivityHolder.applyToApplication(application)
|
|
@@ -76,29 +92,48 @@ class MarketapSdkModule(reactContext: ReactApplicationContext) :
|
|
|
76
92
|
}
|
|
77
93
|
|
|
78
94
|
@ReactMethod
|
|
79
|
-
fun setLogLevel(
|
|
95
|
+
fun setLogLevel(payload: ReadableMap?) {
|
|
96
|
+
val logLevel =
|
|
97
|
+
if (payload != null && payload.hasKey("logLevel") && !payload.isNull("logLevel")) {
|
|
98
|
+
payload.getInt("logLevel")
|
|
99
|
+
} else {
|
|
100
|
+
0
|
|
101
|
+
}
|
|
80
102
|
val resolvedLevel = MarketapLogLevel.values().firstOrNull { level ->
|
|
81
103
|
level.value == logLevel
|
|
82
104
|
} ?: MarketapLogLevel.NONE
|
|
83
105
|
Marketap.setLogLevel(resolvedLevel)
|
|
84
106
|
}
|
|
85
|
-
|
|
107
|
+
|
|
86
108
|
private fun isMainProcess(): Boolean {
|
|
87
109
|
val am = reactApplicationContext.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
|
|
88
110
|
return am.runningAppProcesses?.find { it.pid == android.os.Process.myPid() }?.processName == reactApplicationContext.packageName
|
|
89
111
|
}
|
|
90
112
|
|
|
91
113
|
@ReactMethod
|
|
92
|
-
fun signup(
|
|
93
|
-
userId: String,
|
|
94
|
-
userProperties: ReadableMap?,
|
|
95
|
-
eventProperties: ReadableMap?,
|
|
96
|
-
persistUser: Boolean?,
|
|
97
|
-
promise: Promise
|
|
98
|
-
) {
|
|
114
|
+
fun signup(payload: ReadableMap?, promise: Promise) {
|
|
99
115
|
try {
|
|
116
|
+
val userId = payload?.getString("userId") ?: ""
|
|
117
|
+
val userProperties =
|
|
118
|
+
if (payload != null && payload.hasKey("userProperties") && !payload.isNull("userProperties")) {
|
|
119
|
+
payload.getMap("userProperties")
|
|
120
|
+
} else {
|
|
121
|
+
null
|
|
122
|
+
}
|
|
123
|
+
val eventProperties =
|
|
124
|
+
if (payload != null && payload.hasKey("eventProperties") && !payload.isNull("eventProperties")) {
|
|
125
|
+
payload.getMap("eventProperties")
|
|
126
|
+
} else {
|
|
127
|
+
null
|
|
128
|
+
}
|
|
129
|
+
val persistUser =
|
|
130
|
+
if (payload != null && payload.hasKey("persistUser") && !payload.isNull("persistUser")) {
|
|
131
|
+
payload.getBoolean("persistUser")
|
|
132
|
+
} else {
|
|
133
|
+
true
|
|
134
|
+
}
|
|
100
135
|
// Call MarketapSDK signup method
|
|
101
|
-
Marketap.signup(userId, userProperties.toNonNullableMap(), eventProperties.toNonNullableMap(), persistUser
|
|
136
|
+
Marketap.signup(userId, userProperties.toNonNullableMap(), eventProperties.toNonNullableMap(), persistUser)
|
|
102
137
|
promise.resolve(null)
|
|
103
138
|
} catch (e: Exception) {
|
|
104
139
|
promise.reject("SIGNUP_ERROR", e.message, e)
|
|
@@ -106,13 +141,21 @@ class MarketapSdkModule(reactContext: ReactApplicationContext) :
|
|
|
106
141
|
}
|
|
107
142
|
|
|
108
143
|
@ReactMethod
|
|
109
|
-
fun login(
|
|
110
|
-
userId: String,
|
|
111
|
-
userProperties: ReadableMap?,
|
|
112
|
-
eventProperties: ReadableMap?,
|
|
113
|
-
promise: Promise
|
|
114
|
-
) {
|
|
144
|
+
fun login(payload: ReadableMap?, promise: Promise) {
|
|
115
145
|
try {
|
|
146
|
+
val userId = payload?.getString("userId") ?: ""
|
|
147
|
+
val userProperties =
|
|
148
|
+
if (payload != null && payload.hasKey("userProperties") && !payload.isNull("userProperties")) {
|
|
149
|
+
payload.getMap("userProperties")
|
|
150
|
+
} else {
|
|
151
|
+
null
|
|
152
|
+
}
|
|
153
|
+
val eventProperties =
|
|
154
|
+
if (payload != null && payload.hasKey("eventProperties") && !payload.isNull("eventProperties")) {
|
|
155
|
+
payload.getMap("eventProperties")
|
|
156
|
+
} else {
|
|
157
|
+
null
|
|
158
|
+
}
|
|
116
159
|
// Call MarketapSDK login method
|
|
117
160
|
Marketap.login(userId, userProperties.toNonNullableMap(), eventProperties.toNonNullableMap())
|
|
118
161
|
promise.resolve(null)
|
|
@@ -122,8 +165,14 @@ class MarketapSdkModule(reactContext: ReactApplicationContext) :
|
|
|
122
165
|
}
|
|
123
166
|
|
|
124
167
|
@ReactMethod
|
|
125
|
-
fun logout(
|
|
168
|
+
fun logout(payload: ReadableMap?, promise: Promise) {
|
|
126
169
|
try {
|
|
170
|
+
val eventProperties =
|
|
171
|
+
if (payload != null && payload.hasKey("eventProperties") && !payload.isNull("eventProperties")) {
|
|
172
|
+
payload.getMap("eventProperties")
|
|
173
|
+
} else {
|
|
174
|
+
null
|
|
175
|
+
}
|
|
127
176
|
// Call MarketapSDK logout method
|
|
128
177
|
Marketap.logout(eventProperties.toNonNullableMap())
|
|
129
178
|
promise.resolve(null)
|
|
@@ -133,8 +182,15 @@ class MarketapSdkModule(reactContext: ReactApplicationContext) :
|
|
|
133
182
|
}
|
|
134
183
|
|
|
135
184
|
@ReactMethod
|
|
136
|
-
fun track(
|
|
185
|
+
fun track(payload: ReadableMap?, promise: Promise) {
|
|
137
186
|
try {
|
|
187
|
+
val eventName = payload?.getString("eventName") ?: ""
|
|
188
|
+
val eventProperties =
|
|
189
|
+
if (payload != null && payload.hasKey("eventProperties") && !payload.isNull("eventProperties")) {
|
|
190
|
+
payload.getMap("eventProperties")
|
|
191
|
+
} else {
|
|
192
|
+
null
|
|
193
|
+
}
|
|
138
194
|
// Call MarketapSDK track method
|
|
139
195
|
Marketap.track(eventName, eventProperties.toNonNullableMap())
|
|
140
196
|
promise.resolve(null)
|
|
@@ -144,8 +200,20 @@ class MarketapSdkModule(reactContext: ReactApplicationContext) :
|
|
|
144
200
|
}
|
|
145
201
|
|
|
146
202
|
@ReactMethod
|
|
147
|
-
fun trackPurchase(
|
|
203
|
+
fun trackPurchase(payload: ReadableMap?, promise: Promise) {
|
|
148
204
|
try {
|
|
205
|
+
val revenue =
|
|
206
|
+
if (payload != null && payload.hasKey("revenue") && !payload.isNull("revenue")) {
|
|
207
|
+
payload.getDouble("revenue")
|
|
208
|
+
} else {
|
|
209
|
+
0.0
|
|
210
|
+
}
|
|
211
|
+
val eventProperties =
|
|
212
|
+
if (payload != null && payload.hasKey("eventProperties") && !payload.isNull("eventProperties")) {
|
|
213
|
+
payload.getMap("eventProperties")
|
|
214
|
+
} else {
|
|
215
|
+
null
|
|
216
|
+
}
|
|
149
217
|
// Call MarketapSDK trackPurchase method
|
|
150
218
|
Marketap.trackPurchase(revenue, eventProperties.toNonNullableMap())
|
|
151
219
|
promise.resolve(null)
|
|
@@ -155,13 +223,21 @@ class MarketapSdkModule(reactContext: ReactApplicationContext) :
|
|
|
155
223
|
}
|
|
156
224
|
|
|
157
225
|
@ReactMethod
|
|
158
|
-
fun trackRevenue(
|
|
159
|
-
eventName: String,
|
|
160
|
-
revenue: Double,
|
|
161
|
-
eventProperties: ReadableMap?,
|
|
162
|
-
promise: Promise
|
|
163
|
-
) {
|
|
226
|
+
fun trackRevenue(payload: ReadableMap?, promise: Promise) {
|
|
164
227
|
try {
|
|
228
|
+
val eventName = payload?.getString("eventName") ?: ""
|
|
229
|
+
val revenue =
|
|
230
|
+
if (payload != null && payload.hasKey("revenue") && !payload.isNull("revenue")) {
|
|
231
|
+
payload.getDouble("revenue")
|
|
232
|
+
} else {
|
|
233
|
+
0.0
|
|
234
|
+
}
|
|
235
|
+
val eventProperties =
|
|
236
|
+
if (payload != null && payload.hasKey("eventProperties") && !payload.isNull("eventProperties")) {
|
|
237
|
+
payload.getMap("eventProperties")
|
|
238
|
+
} else {
|
|
239
|
+
null
|
|
240
|
+
}
|
|
165
241
|
// Call MarketapSDK trackRevenue method
|
|
166
242
|
Marketap.trackRevenue(eventName, revenue, eventProperties.toNonNullableMap())
|
|
167
243
|
promise.resolve(null)
|
|
@@ -171,8 +247,14 @@ class MarketapSdkModule(reactContext: ReactApplicationContext) :
|
|
|
171
247
|
}
|
|
172
248
|
|
|
173
249
|
@ReactMethod
|
|
174
|
-
fun trackPageView(
|
|
250
|
+
fun trackPageView(payload: ReadableMap?, promise: Promise) {
|
|
175
251
|
try {
|
|
252
|
+
val eventProperties =
|
|
253
|
+
if (payload != null && payload.hasKey("eventProperties") && !payload.isNull("eventProperties")) {
|
|
254
|
+
payload.getMap("eventProperties")
|
|
255
|
+
} else {
|
|
256
|
+
null
|
|
257
|
+
}
|
|
176
258
|
// Call MarketapSDK trackPageView method
|
|
177
259
|
Marketap.trackPageView(eventProperties.toNonNullableMap())
|
|
178
260
|
promise.resolve(null)
|
|
@@ -182,8 +264,15 @@ class MarketapSdkModule(reactContext: ReactApplicationContext) :
|
|
|
182
264
|
}
|
|
183
265
|
|
|
184
266
|
@ReactMethod
|
|
185
|
-
fun identify(
|
|
267
|
+
fun identify(payload: ReadableMap?, promise: Promise) {
|
|
186
268
|
try {
|
|
269
|
+
val userId = payload?.getString("userId") ?: ""
|
|
270
|
+
val userProperties =
|
|
271
|
+
if (payload != null && payload.hasKey("userProperties") && !payload.isNull("userProperties")) {
|
|
272
|
+
payload.getMap("userProperties")
|
|
273
|
+
} else {
|
|
274
|
+
null
|
|
275
|
+
}
|
|
187
276
|
// Call MarketapSDK identify method
|
|
188
277
|
Marketap.identify(userId, userProperties.toNonNullableMap())
|
|
189
278
|
promise.resolve(null)
|
|
@@ -206,14 +295,14 @@ class MarketapSdkModule(reactContext: ReactApplicationContext) :
|
|
|
206
295
|
@ReactMethod
|
|
207
296
|
fun setClickHandler(promise: Promise) {
|
|
208
297
|
try {
|
|
209
|
-
|
|
298
|
+
clickHandlerRegistered = true
|
|
210
299
|
Marketap.setClickHandler { event ->
|
|
211
300
|
val clickData = convertClickEventToMap(event)
|
|
212
|
-
|
|
213
|
-
|
|
301
|
+
|
|
302
|
+
ReactNativeBridgeRegistry.deliverClick(clickData)
|
|
214
303
|
}
|
|
215
304
|
|
|
216
|
-
|
|
305
|
+
ReactNativeBridgeRegistry.flushIfPending()
|
|
217
306
|
promise.resolve(null)
|
|
218
307
|
} catch (e: Exception) {
|
|
219
308
|
promise.reject("SET_CLICK_HANDLER_ERROR", e.message, e)
|
|
@@ -234,35 +323,139 @@ class MarketapSdkModule(reactContext: ReactApplicationContext) :
|
|
|
234
323
|
}
|
|
235
324
|
}
|
|
236
325
|
|
|
326
|
+
// 웹브릿지 인앱 메시지 관련 메서드
|
|
237
327
|
@ReactMethod
|
|
238
|
-
fun
|
|
328
|
+
fun trackFromWebBridge(payload: ReadableMap?, promise: Promise) {
|
|
329
|
+
try {
|
|
330
|
+
val eventName = payload?.getString("eventName") ?: ""
|
|
331
|
+
val eventProperties =
|
|
332
|
+
if (payload != null && payload.hasKey("eventProperties") && !payload.isNull("eventProperties")) {
|
|
333
|
+
payload.getMap("eventProperties")
|
|
334
|
+
} else {
|
|
335
|
+
null
|
|
336
|
+
}
|
|
337
|
+
val handleInAppInReactNative =
|
|
338
|
+
if (payload != null && payload.hasKey("handleInAppInReactNative") && !payload.isNull("handleInAppInReactNative")) {
|
|
339
|
+
payload.getBoolean("handleInAppInReactNative")
|
|
340
|
+
} else {
|
|
341
|
+
false
|
|
342
|
+
}
|
|
343
|
+
if (handleInAppInReactNative) {
|
|
344
|
+
ReactNativeBridgeRegistry.setWebBridgeSourceTarget(this)
|
|
345
|
+
MarketapWebBridge.setExternalWebBridgeActive(true)
|
|
346
|
+
} else {
|
|
347
|
+
ReactNativeBridgeRegistry.clearWebBridgeSourceTarget()
|
|
348
|
+
MarketapWebBridge.setExternalWebBridgeActive(false)
|
|
349
|
+
}
|
|
350
|
+
MarketapPlugin.trackEvent(eventName, eventProperties.toNonNullableMap())
|
|
351
|
+
promise.resolve(null)
|
|
352
|
+
} catch (e: Exception) {
|
|
353
|
+
promise.reject("TRACK_FROM_WEB_BRIDGE_ERROR", e.message, e)
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
@ReactMethod
|
|
358
|
+
fun setUserProperties(payload: ReadableMap?, promise: Promise) {
|
|
239
359
|
try {
|
|
240
|
-
|
|
360
|
+
val userProperties =
|
|
361
|
+
if (payload != null && payload.hasKey("userProperties") && !payload.isNull("userProperties")) {
|
|
362
|
+
payload.getMap("userProperties")
|
|
363
|
+
} else {
|
|
364
|
+
null
|
|
365
|
+
}
|
|
366
|
+
val props = userProperties.toNonNullableMap()
|
|
367
|
+
if (props == null) {
|
|
368
|
+
promise.reject("ARG_ERROR", "Missing userProperties", null)
|
|
369
|
+
return
|
|
370
|
+
}
|
|
371
|
+
MarketapPlugin.setUserProperties(props)
|
|
241
372
|
promise.resolve(null)
|
|
242
373
|
} catch (e: Exception) {
|
|
243
|
-
promise.reject("
|
|
374
|
+
promise.reject("SET_USER_PROPERTIES_ERROR", e.message, e)
|
|
244
375
|
}
|
|
245
376
|
}
|
|
246
|
-
|
|
377
|
+
|
|
247
378
|
@ReactMethod
|
|
248
|
-
fun
|
|
379
|
+
fun trackInAppImpression(payload: ReadableMap?, promise: Promise) {
|
|
249
380
|
try {
|
|
250
|
-
val
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
381
|
+
val campaignId = payload?.getString("campaignId")
|
|
382
|
+
val messageId = payload?.getString("messageId")
|
|
383
|
+
val layoutSubType = payload?.getString("layoutSubType")
|
|
384
|
+
if (campaignId == null || messageId == null) {
|
|
385
|
+
android.util.Log.w(
|
|
386
|
+
NAME,
|
|
387
|
+
"trackInAppImpression: missing required params (campaignId=$campaignId, messageId=$messageId)"
|
|
388
|
+
)
|
|
255
389
|
promise.resolve(null)
|
|
390
|
+
return
|
|
256
391
|
}
|
|
392
|
+
MarketapPlugin.trackInAppImpression(campaignId, messageId, layoutSubType)
|
|
393
|
+
promise.resolve(null)
|
|
257
394
|
} catch (e: Exception) {
|
|
258
|
-
promise.reject("
|
|
395
|
+
promise.reject("TRACK_INAPP_IMPRESSION_ERROR", e.message, e)
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
@ReactMethod
|
|
400
|
+
fun trackInAppClick(payload: ReadableMap?, promise: Promise) {
|
|
401
|
+
try {
|
|
402
|
+
val campaignId = payload?.getString("campaignId")
|
|
403
|
+
val messageId = payload?.getString("messageId")
|
|
404
|
+
val locationId = payload?.getString("locationId")
|
|
405
|
+
val url = payload?.getString("url")
|
|
406
|
+
val layoutSubType = payload?.getString("layoutSubType")
|
|
407
|
+
if (campaignId == null || messageId == null || locationId == null) {
|
|
408
|
+
android.util.Log.w(
|
|
409
|
+
NAME,
|
|
410
|
+
"trackInAppClick: missing required params (campaignId=$campaignId, messageId=$messageId, locationId=$locationId)"
|
|
411
|
+
)
|
|
412
|
+
promise.resolve(null)
|
|
413
|
+
return
|
|
414
|
+
}
|
|
415
|
+
MarketapPlugin.trackInAppClick(campaignId, messageId, locationId, url, layoutSubType)
|
|
416
|
+
promise.resolve(null)
|
|
417
|
+
} catch (e: Exception) {
|
|
418
|
+
promise.reject("TRACK_INAPP_CLICK_ERROR", e.message, e)
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
@ReactMethod
|
|
423
|
+
fun hideCampaign(payload: ReadableMap?, promise: Promise) {
|
|
424
|
+
try {
|
|
425
|
+
val campaignId = payload?.getString("campaignId")
|
|
426
|
+
val hideType = payload?.getString("hideType")
|
|
427
|
+
if (campaignId == null) {
|
|
428
|
+
android.util.Log.w(NAME, "hideCampaign: missing campaignId")
|
|
429
|
+
promise.resolve(null)
|
|
430
|
+
return
|
|
431
|
+
}
|
|
432
|
+
MarketapPlugin.hideInAppMessage(campaignId, hideType)
|
|
433
|
+
promise.resolve(null)
|
|
434
|
+
} catch (e: Exception) {
|
|
435
|
+
promise.reject("HIDE_CAMPAIGN_ERROR", e.message, e)
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
@ReactMethod
|
|
440
|
+
fun setDeviceOptIn(payload: ReadableMap?, promise: Promise) {
|
|
441
|
+
try {
|
|
442
|
+
val optIn: Boolean? =
|
|
443
|
+
if (payload != null && payload.hasKey("optIn") && !payload.isNull("optIn")) {
|
|
444
|
+
payload.getBoolean("optIn")
|
|
445
|
+
} else {
|
|
446
|
+
null
|
|
447
|
+
}
|
|
448
|
+
Marketap.setDeviceOptIn(optIn)
|
|
449
|
+
promise.resolve(null)
|
|
450
|
+
} catch (e: Exception) {
|
|
451
|
+
promise.reject("SET_DEVICE_OPT_IN_ERROR", e.message, e)
|
|
259
452
|
}
|
|
260
453
|
}
|
|
261
454
|
|
|
262
455
|
@ReactMethod
|
|
263
456
|
fun addListener(eventName: String) {
|
|
264
457
|
hasListeners = true
|
|
265
|
-
|
|
458
|
+
ReactNativeBridgeRegistry.flushIfPending()
|
|
266
459
|
}
|
|
267
460
|
|
|
268
461
|
@ReactMethod
|
|
@@ -271,7 +464,7 @@ class MarketapSdkModule(reactContext: ReactApplicationContext) :
|
|
|
271
464
|
}
|
|
272
465
|
|
|
273
466
|
private fun sendEvent(eventName: String, params: WritableMap?): Boolean {
|
|
274
|
-
if (!hasListeners || !
|
|
467
|
+
if (!hasListeners || !isReactInstanceReady()) {
|
|
275
468
|
return false
|
|
276
469
|
}
|
|
277
470
|
reactApplicationContext.runOnJSQueueThread {
|
|
@@ -282,28 +475,7 @@ class MarketapSdkModule(reactContext: ReactApplicationContext) :
|
|
|
282
475
|
return true
|
|
283
476
|
}
|
|
284
477
|
|
|
285
|
-
private fun
|
|
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 {
|
|
478
|
+
private fun isReactInstanceReady(): Boolean {
|
|
307
479
|
return reactApplicationContext.hasActiveCatalystInstance() &&
|
|
308
480
|
reactApplicationContext.hasActiveReactInstance()
|
|
309
481
|
}
|
|
@@ -321,17 +493,52 @@ class MarketapSdkModule(reactContext: ReactApplicationContext) :
|
|
|
321
493
|
return map
|
|
322
494
|
}
|
|
323
495
|
|
|
496
|
+
override fun sendInAppMessage(
|
|
497
|
+
campaign: Map<String, Any?>,
|
|
498
|
+
messageId: String,
|
|
499
|
+
hasCustomClickHandler: Boolean
|
|
500
|
+
) {
|
|
501
|
+
val args = Arguments.createMap()
|
|
502
|
+
args.putMap("campaign", Arguments.makeNativeMap(campaign))
|
|
503
|
+
args.putString("messageId", messageId)
|
|
504
|
+
args.putBoolean("hasCustomClickHandler", hasCustomClickHandler)
|
|
505
|
+
sendEvent(IN_APP_MESSAGE_EVENT, args)
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
override fun sendClick(clickData: WritableMap) {
|
|
509
|
+
sendEvent(CLICK_EVENT, clickData)
|
|
510
|
+
}
|
|
511
|
+
|
|
324
512
|
override fun onHostResume() {
|
|
325
|
-
|
|
326
|
-
|
|
513
|
+
val activity = getCurrentActivity() ?: return
|
|
514
|
+
CurrentActivityHolder.set(activity)
|
|
515
|
+
ReactNativeBridgeRegistry.flushIfPending()
|
|
327
516
|
}
|
|
328
517
|
|
|
329
518
|
override fun onHostPause() {
|
|
330
|
-
isHostResumed = false
|
|
331
519
|
}
|
|
332
520
|
|
|
333
521
|
override fun onHostDestroy() {
|
|
334
|
-
|
|
522
|
+
isModuleActive = false
|
|
523
|
+
ReactNativeBridgeRegistry.unregister(this)
|
|
524
|
+
reactApplicationContext.removeLifecycleEventListener(this)
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
override fun invalidate() {
|
|
528
|
+
isModuleActive = false
|
|
529
|
+
ReactNativeBridgeRegistry.unregister(this)
|
|
335
530
|
reactApplicationContext.removeLifecycleEventListener(this)
|
|
531
|
+
super.invalidate()
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
private fun registerExternalInAppCallback() {
|
|
535
|
+
if (isExternalInAppCallbackRegistered) {
|
|
536
|
+
return
|
|
537
|
+
}
|
|
538
|
+
isExternalInAppCallbackRegistered = true
|
|
539
|
+
|
|
540
|
+
MarketapWebBridge.setExternalInAppMessageCallback { campaign, messageId, hasCustomClickHandler ->
|
|
541
|
+
ReactNativeBridgeRegistry.sendInAppMessage(campaign, messageId, hasCustomClickHandler)
|
|
542
|
+
}
|
|
336
543
|
}
|
|
337
544
|
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
package com.marketapsdk
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.WritableMap
|
|
4
|
+
|
|
5
|
+
internal interface ReactNativeBridgeTarget {
|
|
6
|
+
val isAttachedToReact: Boolean
|
|
7
|
+
val isClickHandlerRegistered: Boolean
|
|
8
|
+
val isReactReady: Boolean
|
|
9
|
+
|
|
10
|
+
fun sendInAppMessage(
|
|
11
|
+
campaign: Map<String, Any?>,
|
|
12
|
+
messageId: String,
|
|
13
|
+
hasCustomClickHandler: Boolean
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
fun sendClick(clickData: WritableMap)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
internal object ReactNativeBridgeRegistry {
|
|
20
|
+
private val activeTargets: MutableList<ReactNativeBridgeTarget> = mutableListOf()
|
|
21
|
+
|
|
22
|
+
private val clickHandlerTargets: List<ReactNativeBridgeTarget>
|
|
23
|
+
get() = activeTargets.filter { it.isClickHandlerRegistered && it.isAttachedToReact }
|
|
24
|
+
private val attachedTargets: List<ReactNativeBridgeTarget>
|
|
25
|
+
get() = activeTargets.filter { it.isAttachedToReact }
|
|
26
|
+
|
|
27
|
+
private var lastPendingClick: WritableMap? = null
|
|
28
|
+
|
|
29
|
+
// trackFromWebBridge를 호출한 타겟 (인앱 메시지 전달 대상)
|
|
30
|
+
private var webBridgeSourceTarget: ReactNativeBridgeTarget? = null
|
|
31
|
+
|
|
32
|
+
fun register(target: ReactNativeBridgeTarget) {
|
|
33
|
+
log("Register target: $target")
|
|
34
|
+
activeTargets.add(target)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
fun unregister(target: ReactNativeBridgeTarget) {
|
|
38
|
+
log("Unregister target: $target")
|
|
39
|
+
activeTargets.remove(target)
|
|
40
|
+
if (webBridgeSourceTarget == target) {
|
|
41
|
+
webBridgeSourceTarget = null
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* trackFromWebBridge 호출 시 소스 타겟 설정
|
|
47
|
+
*/
|
|
48
|
+
fun setWebBridgeSourceTarget(target: ReactNativeBridgeTarget) {
|
|
49
|
+
webBridgeSourceTarget = target
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* 소스 타겟 초기화
|
|
54
|
+
*/
|
|
55
|
+
fun clearWebBridgeSourceTarget() {
|
|
56
|
+
webBridgeSourceTarget = null
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* 네이티브 SDK에서 RN으로 인앱 메시지 전달
|
|
61
|
+
* trackFromWebBridge를 호출한 타겟에만 전달
|
|
62
|
+
*/
|
|
63
|
+
fun sendInAppMessage(
|
|
64
|
+
campaign: Map<String, Any?>,
|
|
65
|
+
messageId: String,
|
|
66
|
+
hasCustomClickHandler: Boolean
|
|
67
|
+
) {
|
|
68
|
+
val target = webBridgeSourceTarget
|
|
69
|
+
webBridgeSourceTarget = null
|
|
70
|
+
|
|
71
|
+
if (target != null && target.isAttachedToReact && target.isReactReady) {
|
|
72
|
+
target.sendInAppMessage(campaign, messageId, hasCustomClickHandler)
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
fun flushIfPending() {
|
|
77
|
+
log("flush called, $lastPendingClick")
|
|
78
|
+
lastPendingClick?.let { clickData ->
|
|
79
|
+
log("Flush pending click on new instance: $clickData")
|
|
80
|
+
deliverClick(clickData)
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
fun deliverClick(clickData: WritableMap) {
|
|
85
|
+
log("Deliver click: $clickData")
|
|
86
|
+
val readyTargets = clickHandlerTargets.filter { it.isReactReady }
|
|
87
|
+
if (readyTargets.isNotEmpty()) {
|
|
88
|
+
log("There are ${readyTargets.size} click handler targets available; delivery click: $clickData")
|
|
89
|
+
readyTargets.forEach { target ->
|
|
90
|
+
log("Deliver click to $target: $clickData")
|
|
91
|
+
target.sendClick(clickData)
|
|
92
|
+
}
|
|
93
|
+
lastPendingClick = null
|
|
94
|
+
} else {
|
|
95
|
+
log("Targets not ready; store click: $clickData")
|
|
96
|
+
lastPendingClick = clickData
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
fun popPendingClick(): WritableMap? {
|
|
101
|
+
val pending = lastPendingClick
|
|
102
|
+
lastPendingClick = null
|
|
103
|
+
return pending
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
private fun log(message: String) {
|
|
107
|
+
// TODO: route to Marketap logger when available in RN layer
|
|
108
|
+
android.util.Log.d("MarketapBridgeRegistry", message)
|
|
109
|
+
}
|
|
110
|
+
}
|