react-native-marketap-sdk 0.1.0-beta.8 → 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 +299 -62
- 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 -150
- 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 -149
- 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 -40
- 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,31 +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
38
|
private var isInitialized = false
|
|
36
39
|
private var initializedProjectId: String? = null
|
|
40
|
+
private var clickHandlerRegistered = false
|
|
41
|
+
private var isModuleActive = true
|
|
42
|
+
|
|
43
|
+
init {
|
|
44
|
+
reactApplicationContext.addLifecycleEventListener(this)
|
|
45
|
+
ReactNativeBridgeRegistry.register(this)
|
|
46
|
+
registerExternalInAppCallback()
|
|
47
|
+
}
|
|
37
48
|
|
|
38
49
|
override fun getName(): String {
|
|
39
50
|
return NAME
|
|
40
51
|
}
|
|
41
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
|
+
|
|
42
62
|
@ReactMethod
|
|
43
|
-
fun initialize(
|
|
63
|
+
fun initialize(payload: ReadableMap?, promise: Promise) {
|
|
44
64
|
try {
|
|
65
|
+
val projectId = payload?.getString("projectId") ?: ""
|
|
45
66
|
if (!isMainProcess()) {
|
|
46
67
|
promise.resolve(null)
|
|
47
68
|
return
|
|
48
69
|
}
|
|
49
|
-
|
|
70
|
+
|
|
50
71
|
if (isInitialized) {
|
|
51
72
|
if (initializedProjectId == projectId) {
|
|
52
73
|
promise.resolve(null)
|
|
@@ -57,7 +78,7 @@ class MarketapSdkModule(reactContext: ReactApplicationContext) :
|
|
|
57
78
|
return
|
|
58
79
|
}
|
|
59
80
|
}
|
|
60
|
-
|
|
81
|
+
|
|
61
82
|
// Initialize MarketapSDK with projectId
|
|
62
83
|
val application = reactApplicationContext.applicationContext as Application
|
|
63
84
|
CurrentActivityHolder.applyToApplication(application)
|
|
@@ -71,29 +92,48 @@ class MarketapSdkModule(reactContext: ReactApplicationContext) :
|
|
|
71
92
|
}
|
|
72
93
|
|
|
73
94
|
@ReactMethod
|
|
74
|
-
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
|
+
}
|
|
75
102
|
val resolvedLevel = MarketapLogLevel.values().firstOrNull { level ->
|
|
76
103
|
level.value == logLevel
|
|
77
104
|
} ?: MarketapLogLevel.NONE
|
|
78
105
|
Marketap.setLogLevel(resolvedLevel)
|
|
79
106
|
}
|
|
80
|
-
|
|
107
|
+
|
|
81
108
|
private fun isMainProcess(): Boolean {
|
|
82
109
|
val am = reactApplicationContext.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
|
|
83
110
|
return am.runningAppProcesses?.find { it.pid == android.os.Process.myPid() }?.processName == reactApplicationContext.packageName
|
|
84
111
|
}
|
|
85
112
|
|
|
86
113
|
@ReactMethod
|
|
87
|
-
fun signup(
|
|
88
|
-
userId: String,
|
|
89
|
-
userProperties: ReadableMap?,
|
|
90
|
-
eventProperties: ReadableMap?,
|
|
91
|
-
persistUser: Boolean?,
|
|
92
|
-
promise: Promise
|
|
93
|
-
) {
|
|
114
|
+
fun signup(payload: ReadableMap?, promise: Promise) {
|
|
94
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
|
+
}
|
|
95
135
|
// Call MarketapSDK signup method
|
|
96
|
-
Marketap.signup(userId, userProperties.toNonNullableMap(), eventProperties.toNonNullableMap(), persistUser
|
|
136
|
+
Marketap.signup(userId, userProperties.toNonNullableMap(), eventProperties.toNonNullableMap(), persistUser)
|
|
97
137
|
promise.resolve(null)
|
|
98
138
|
} catch (e: Exception) {
|
|
99
139
|
promise.reject("SIGNUP_ERROR", e.message, e)
|
|
@@ -101,13 +141,21 @@ class MarketapSdkModule(reactContext: ReactApplicationContext) :
|
|
|
101
141
|
}
|
|
102
142
|
|
|
103
143
|
@ReactMethod
|
|
104
|
-
fun login(
|
|
105
|
-
userId: String,
|
|
106
|
-
userProperties: ReadableMap?,
|
|
107
|
-
eventProperties: ReadableMap?,
|
|
108
|
-
promise: Promise
|
|
109
|
-
) {
|
|
144
|
+
fun login(payload: ReadableMap?, promise: Promise) {
|
|
110
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
|
+
}
|
|
111
159
|
// Call MarketapSDK login method
|
|
112
160
|
Marketap.login(userId, userProperties.toNonNullableMap(), eventProperties.toNonNullableMap())
|
|
113
161
|
promise.resolve(null)
|
|
@@ -117,8 +165,14 @@ class MarketapSdkModule(reactContext: ReactApplicationContext) :
|
|
|
117
165
|
}
|
|
118
166
|
|
|
119
167
|
@ReactMethod
|
|
120
|
-
fun logout(
|
|
168
|
+
fun logout(payload: ReadableMap?, promise: Promise) {
|
|
121
169
|
try {
|
|
170
|
+
val eventProperties =
|
|
171
|
+
if (payload != null && payload.hasKey("eventProperties") && !payload.isNull("eventProperties")) {
|
|
172
|
+
payload.getMap("eventProperties")
|
|
173
|
+
} else {
|
|
174
|
+
null
|
|
175
|
+
}
|
|
122
176
|
// Call MarketapSDK logout method
|
|
123
177
|
Marketap.logout(eventProperties.toNonNullableMap())
|
|
124
178
|
promise.resolve(null)
|
|
@@ -128,8 +182,15 @@ class MarketapSdkModule(reactContext: ReactApplicationContext) :
|
|
|
128
182
|
}
|
|
129
183
|
|
|
130
184
|
@ReactMethod
|
|
131
|
-
fun track(
|
|
185
|
+
fun track(payload: ReadableMap?, promise: Promise) {
|
|
132
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
|
+
}
|
|
133
194
|
// Call MarketapSDK track method
|
|
134
195
|
Marketap.track(eventName, eventProperties.toNonNullableMap())
|
|
135
196
|
promise.resolve(null)
|
|
@@ -139,8 +200,20 @@ class MarketapSdkModule(reactContext: ReactApplicationContext) :
|
|
|
139
200
|
}
|
|
140
201
|
|
|
141
202
|
@ReactMethod
|
|
142
|
-
fun trackPurchase(
|
|
203
|
+
fun trackPurchase(payload: ReadableMap?, promise: Promise) {
|
|
143
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
|
+
}
|
|
144
217
|
// Call MarketapSDK trackPurchase method
|
|
145
218
|
Marketap.trackPurchase(revenue, eventProperties.toNonNullableMap())
|
|
146
219
|
promise.resolve(null)
|
|
@@ -150,13 +223,21 @@ class MarketapSdkModule(reactContext: ReactApplicationContext) :
|
|
|
150
223
|
}
|
|
151
224
|
|
|
152
225
|
@ReactMethod
|
|
153
|
-
fun trackRevenue(
|
|
154
|
-
eventName: String,
|
|
155
|
-
revenue: Double,
|
|
156
|
-
eventProperties: ReadableMap?,
|
|
157
|
-
promise: Promise
|
|
158
|
-
) {
|
|
226
|
+
fun trackRevenue(payload: ReadableMap?, promise: Promise) {
|
|
159
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
|
+
}
|
|
160
241
|
// Call MarketapSDK trackRevenue method
|
|
161
242
|
Marketap.trackRevenue(eventName, revenue, eventProperties.toNonNullableMap())
|
|
162
243
|
promise.resolve(null)
|
|
@@ -166,8 +247,14 @@ class MarketapSdkModule(reactContext: ReactApplicationContext) :
|
|
|
166
247
|
}
|
|
167
248
|
|
|
168
249
|
@ReactMethod
|
|
169
|
-
fun trackPageView(
|
|
250
|
+
fun trackPageView(payload: ReadableMap?, promise: Promise) {
|
|
170
251
|
try {
|
|
252
|
+
val eventProperties =
|
|
253
|
+
if (payload != null && payload.hasKey("eventProperties") && !payload.isNull("eventProperties")) {
|
|
254
|
+
payload.getMap("eventProperties")
|
|
255
|
+
} else {
|
|
256
|
+
null
|
|
257
|
+
}
|
|
171
258
|
// Call MarketapSDK trackPageView method
|
|
172
259
|
Marketap.trackPageView(eventProperties.toNonNullableMap())
|
|
173
260
|
promise.resolve(null)
|
|
@@ -177,8 +264,15 @@ class MarketapSdkModule(reactContext: ReactApplicationContext) :
|
|
|
177
264
|
}
|
|
178
265
|
|
|
179
266
|
@ReactMethod
|
|
180
|
-
fun identify(
|
|
267
|
+
fun identify(payload: ReadableMap?, promise: Promise) {
|
|
181
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
|
+
}
|
|
182
276
|
// Call MarketapSDK identify method
|
|
183
277
|
Marketap.identify(userId, userProperties.toNonNullableMap())
|
|
184
278
|
promise.resolve(null)
|
|
@@ -201,22 +295,14 @@ class MarketapSdkModule(reactContext: ReactApplicationContext) :
|
|
|
201
295
|
@ReactMethod
|
|
202
296
|
fun setClickHandler(promise: Promise) {
|
|
203
297
|
try {
|
|
298
|
+
clickHandlerRegistered = true
|
|
204
299
|
Marketap.setClickHandler { event ->
|
|
205
300
|
val clickData = convertClickEventToMap(event)
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
sendEvent(CLICK_EVENT, clickData)
|
|
209
|
-
pendingClickEvent = null
|
|
210
|
-
} else {
|
|
211
|
-
pendingClickEvent = clickData
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
pendingClickEvent?.let { pendingEvent ->
|
|
216
|
-
sendEvent(CLICK_EVENT, pendingEvent)
|
|
217
|
-
pendingClickEvent = null
|
|
301
|
+
|
|
302
|
+
ReactNativeBridgeRegistry.deliverClick(clickData)
|
|
218
303
|
}
|
|
219
|
-
|
|
304
|
+
|
|
305
|
+
ReactNativeBridgeRegistry.flushIfPending()
|
|
220
306
|
promise.resolve(null)
|
|
221
307
|
} catch (e: Exception) {
|
|
222
308
|
promise.reject("SET_CLICK_HANDLER_ERROR", e.message, e)
|
|
@@ -237,34 +323,139 @@ class MarketapSdkModule(reactContext: ReactApplicationContext) :
|
|
|
237
323
|
}
|
|
238
324
|
}
|
|
239
325
|
|
|
326
|
+
// 웹브릿지 인앱 메시지 관련 메서드
|
|
327
|
+
@ReactMethod
|
|
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) {
|
|
359
|
+
try {
|
|
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)
|
|
372
|
+
promise.resolve(null)
|
|
373
|
+
} catch (e: Exception) {
|
|
374
|
+
promise.reject("SET_USER_PROPERTIES_ERROR", e.message, e)
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
240
378
|
@ReactMethod
|
|
241
|
-
fun
|
|
379
|
+
fun trackInAppImpression(payload: ReadableMap?, promise: Promise) {
|
|
242
380
|
try {
|
|
243
|
-
|
|
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
|
+
)
|
|
389
|
+
promise.resolve(null)
|
|
390
|
+
return
|
|
391
|
+
}
|
|
392
|
+
MarketapPlugin.trackInAppImpression(campaignId, messageId, layoutSubType)
|
|
244
393
|
promise.resolve(null)
|
|
245
394
|
} catch (e: Exception) {
|
|
246
|
-
promise.reject("
|
|
395
|
+
promise.reject("TRACK_INAPP_IMPRESSION_ERROR", e.message, e)
|
|
247
396
|
}
|
|
248
397
|
}
|
|
249
|
-
|
|
398
|
+
|
|
250
399
|
@ReactMethod
|
|
251
|
-
fun
|
|
400
|
+
fun trackInAppClick(payload: ReadableMap?, promise: Promise) {
|
|
252
401
|
try {
|
|
253
|
-
val
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
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
|
+
)
|
|
258
412
|
promise.resolve(null)
|
|
413
|
+
return
|
|
259
414
|
}
|
|
415
|
+
MarketapPlugin.trackInAppClick(campaignId, messageId, locationId, url, layoutSubType)
|
|
416
|
+
promise.resolve(null)
|
|
260
417
|
} catch (e: Exception) {
|
|
261
|
-
promise.reject("
|
|
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)
|
|
262
452
|
}
|
|
263
453
|
}
|
|
264
454
|
|
|
265
455
|
@ReactMethod
|
|
266
456
|
fun addListener(eventName: String) {
|
|
267
457
|
hasListeners = true
|
|
458
|
+
ReactNativeBridgeRegistry.flushIfPending()
|
|
268
459
|
}
|
|
269
460
|
|
|
270
461
|
@ReactMethod
|
|
@@ -272,12 +463,21 @@ class MarketapSdkModule(reactContext: ReactApplicationContext) :
|
|
|
272
463
|
hasListeners = false
|
|
273
464
|
}
|
|
274
465
|
|
|
275
|
-
private fun sendEvent(eventName: String, params: WritableMap?) {
|
|
276
|
-
if (hasListeners) {
|
|
466
|
+
private fun sendEvent(eventName: String, params: WritableMap?): Boolean {
|
|
467
|
+
if (!hasListeners || !isReactInstanceReady()) {
|
|
468
|
+
return false
|
|
469
|
+
}
|
|
470
|
+
reactApplicationContext.runOnJSQueueThread {
|
|
277
471
|
reactApplicationContext
|
|
278
472
|
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
|
279
473
|
.emit(eventName, params)
|
|
280
474
|
}
|
|
475
|
+
return true
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
private fun isReactInstanceReady(): Boolean {
|
|
479
|
+
return reactApplicationContext.hasActiveCatalystInstance() &&
|
|
480
|
+
reactApplicationContext.hasActiveReactInstance()
|
|
281
481
|
}
|
|
282
482
|
|
|
283
483
|
private fun convertClickEventToMap(event: com.marketap.sdk.model.external.MarketapClickEvent): WritableMap {
|
|
@@ -293,15 +493,52 @@ class MarketapSdkModule(reactContext: ReactApplicationContext) :
|
|
|
293
493
|
return map
|
|
294
494
|
}
|
|
295
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
|
+
|
|
296
512
|
override fun onHostResume() {
|
|
297
|
-
|
|
513
|
+
val activity = getCurrentActivity() ?: return
|
|
514
|
+
CurrentActivityHolder.set(activity)
|
|
515
|
+
ReactNativeBridgeRegistry.flushIfPending()
|
|
298
516
|
}
|
|
299
517
|
|
|
300
518
|
override fun onHostPause() {
|
|
301
|
-
// Handle app pause
|
|
302
519
|
}
|
|
303
520
|
|
|
304
521
|
override fun onHostDestroy() {
|
|
305
|
-
|
|
522
|
+
isModuleActive = false
|
|
523
|
+
ReactNativeBridgeRegistry.unregister(this)
|
|
524
|
+
reactApplicationContext.removeLifecycleEventListener(this)
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
override fun invalidate() {
|
|
528
|
+
isModuleActive = false
|
|
529
|
+
ReactNativeBridgeRegistry.unregister(this)
|
|
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
|
+
}
|
|
306
543
|
}
|
|
307
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
|
+
}
|