com-tapp-so-sdk 0.1.0 → 0.1.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.
- package/android/src/main/java/com/comtappsosdk/ComTappSoSdkModule.kt +145 -11
- package/ios/ComTappSoSdk.mm +133 -12
- package/ios/generated/ComTappSoSdkSpec/ComTappSoSdkSpec-generated.mm +28 -0
- package/ios/generated/ComTappSoSdkSpec/ComTappSoSdkSpec.h +5 -0
- package/ios/generated/ComTappSoSdkSpecJSI-generated.cpp +33 -0
- package/ios/generated/ComTappSoSdkSpecJSI.h +36 -0
- package/lib/module/NativeComTappSoSdk.js.map +1 -1
- package/lib/module/events.js +19 -3
- package/lib/module/events.js.map +1 -1
- package/lib/module/index.js +30 -1
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/src/NativeComTappSoSdk.d.ts +4 -0
- package/lib/typescript/src/NativeComTappSoSdk.d.ts.map +1 -1
- package/lib/typescript/src/events.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +10 -0
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/NativeComTappSoSdk.ts +8 -0
- package/src/events.ts +27 -3
- package/src/index.tsx +34 -1
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
package com.comtappsosdk
|
|
2
2
|
|
|
3
|
+
import android.os.Handler
|
|
4
|
+
import android.os.Looper
|
|
3
5
|
import android.util.Log
|
|
4
6
|
import com.example.tapp.Tapp
|
|
5
7
|
import com.example.tapp.models.Affiliate
|
|
@@ -23,6 +25,7 @@ import kotlinx.coroutines.CoroutineScope
|
|
|
23
25
|
import kotlinx.coroutines.Dispatchers
|
|
24
26
|
import kotlinx.coroutines.launch
|
|
25
27
|
import kotlinx.coroutines.withContext
|
|
28
|
+
import java.util.concurrent.ConcurrentLinkedQueue
|
|
26
29
|
|
|
27
30
|
@ReactModule(name = ComTappSoSdkModule.NAME)
|
|
28
31
|
class ComTappSoSdkModule(reactContext: ReactApplicationContext) :
|
|
@@ -30,16 +33,153 @@ class ComTappSoSdkModule(reactContext: ReactApplicationContext) :
|
|
|
30
33
|
|
|
31
34
|
companion object {
|
|
32
35
|
const val NAME = "ComTappSoSdk"
|
|
36
|
+
private const val FLUSH_RETRY_INTERVAL_MS = 100L
|
|
37
|
+
private const val FLUSH_RETRY_MAX_DURATION_MS = 2000L
|
|
33
38
|
}
|
|
34
39
|
|
|
35
40
|
private lateinit var tapp: Tapp
|
|
41
|
+
private var listenerCount = 0
|
|
42
|
+
private val eventQueue = ConcurrentLinkedQueue<Pair<String, WritableMap?>>()
|
|
43
|
+
private val mainHandler = Handler(Looper.getMainLooper())
|
|
44
|
+
private var flushRetryStartTime: Long = 0
|
|
45
|
+
private var isFlushRetryScheduled = false
|
|
36
46
|
|
|
37
47
|
init {
|
|
38
|
-
|
|
48
|
+
// Module initialized
|
|
39
49
|
}
|
|
40
|
-
|
|
41
50
|
override fun getName(): String = NAME
|
|
42
51
|
|
|
52
|
+
// Required by NativeEventEmitter
|
|
53
|
+
@ReactMethod
|
|
54
|
+
fun addListener(eventName: String) {
|
|
55
|
+
listenerCount++
|
|
56
|
+
flushEvents()
|
|
57
|
+
// Schedule retry in case React is not active yet
|
|
58
|
+
scheduleFlushRetry()
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Required by NativeEventEmitter
|
|
62
|
+
@ReactMethod
|
|
63
|
+
fun removeListeners(count: Int) {
|
|
64
|
+
listenerCount -= count
|
|
65
|
+
if (listenerCount < 0) {
|
|
66
|
+
listenerCount = 0
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Check if React Native is active. Prefers hasActiveCatalystInstance(),
|
|
72
|
+
* falls back to hasActiveReactInstance() for newer RN versions.
|
|
73
|
+
*/
|
|
74
|
+
private fun isReactActive(): Boolean {
|
|
75
|
+
return try {
|
|
76
|
+
reactApplicationContext.hasActiveCatalystInstance()
|
|
77
|
+
} catch (e: Exception) {
|
|
78
|
+
try {
|
|
79
|
+
// Fallback for newer React Native versions
|
|
80
|
+
val method = reactApplicationContext.javaClass.getMethod("hasActiveReactInstance")
|
|
81
|
+
method.invoke(reactApplicationContext) as Boolean
|
|
82
|
+
} catch (e2: Exception) {
|
|
83
|
+
false
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Schedule flush retries every 100ms for up to 2 seconds.
|
|
90
|
+
* This ensures buffered events are flushed even if React wasn't active initially.
|
|
91
|
+
*/
|
|
92
|
+
private fun scheduleFlushRetry() {
|
|
93
|
+
if (isFlushRetryScheduled) return
|
|
94
|
+
if (eventQueue.isEmpty()) return
|
|
95
|
+
|
|
96
|
+
isFlushRetryScheduled = true
|
|
97
|
+
flushRetryStartTime = System.currentTimeMillis()
|
|
98
|
+
|
|
99
|
+
mainHandler.postDelayed(object : Runnable {
|
|
100
|
+
override fun run() {
|
|
101
|
+
val elapsed = System.currentTimeMillis() - flushRetryStartTime
|
|
102
|
+
|
|
103
|
+
if (eventQueue.isEmpty() || listenerCount == 0) {
|
|
104
|
+
isFlushRetryScheduled = false
|
|
105
|
+
return
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (elapsed > FLUSH_RETRY_MAX_DURATION_MS) {
|
|
109
|
+
isFlushRetryScheduled = false
|
|
110
|
+
return
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
flushEvents()
|
|
114
|
+
|
|
115
|
+
// Continue retrying if queue still has items
|
|
116
|
+
if (!eventQueue.isEmpty()) {
|
|
117
|
+
mainHandler.postDelayed(this, FLUSH_RETRY_INTERVAL_MS)
|
|
118
|
+
} else {
|
|
119
|
+
isFlushRetryScheduled = false
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}, FLUSH_RETRY_INTERVAL_MS)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
private fun emitOrBuffer(eventName: String, params: WritableMap?) {
|
|
126
|
+
// If we have listeners and the React context is active, emit immediately
|
|
127
|
+
if (listenerCount > 0 && isReactActive()) {
|
|
128
|
+
mainHandler.post {
|
|
129
|
+
emitNow(eventName, params)
|
|
130
|
+
}
|
|
131
|
+
} else {
|
|
132
|
+
// Otherwise buffer
|
|
133
|
+
try {
|
|
134
|
+
eventQueue.add(Pair(eventName, params))
|
|
135
|
+
// Cap buffer size at 10 to avoid memory leaks
|
|
136
|
+
if (eventQueue.size > 10) {
|
|
137
|
+
eventQueue.poll()
|
|
138
|
+
}
|
|
139
|
+
// Start retry scheduler if not already running
|
|
140
|
+
if (listenerCount > 0) {
|
|
141
|
+
scheduleFlushRetry()
|
|
142
|
+
}
|
|
143
|
+
} catch (e: Exception) {
|
|
144
|
+
Log.e(NAME, "Error buffering event: ${e.message}")
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
private fun flushEvents() {
|
|
150
|
+
if (!isReactActive() || listenerCount == 0) {
|
|
151
|
+
return
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
mainHandler.post {
|
|
155
|
+
while (listenerCount > 0 && isReactActive() && !eventQueue.isEmpty()) {
|
|
156
|
+
val event = eventQueue.poll()
|
|
157
|
+
if (event != null) {
|
|
158
|
+
emitNow(event.first, event.second)
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
private fun emitNow(eventName: String, params: WritableMap?) {
|
|
165
|
+
try {
|
|
166
|
+
if (isReactActive()) {
|
|
167
|
+
reactApplicationContext
|
|
168
|
+
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
|
169
|
+
.emit(eventName, params)
|
|
170
|
+
} else {
|
|
171
|
+
// Re-enqueue if React became inactive
|
|
172
|
+
eventQueue.add(Pair(eventName, params))
|
|
173
|
+
scheduleFlushRetry()
|
|
174
|
+
}
|
|
175
|
+
} catch (e: Exception) {
|
|
176
|
+
Log.e(NAME, "Error emitting event $eventName: ${e.message}")
|
|
177
|
+
// Re-enqueue on error
|
|
178
|
+
eventQueue.add(Pair(eventName, params))
|
|
179
|
+
scheduleFlushRetry()
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
43
183
|
|
|
44
184
|
@ReactMethod
|
|
45
185
|
fun start(authToken: String, env: String, tappToken: String) {
|
|
@@ -298,9 +438,7 @@ class ComTappSoSdkModule(reactContext: ReactApplicationContext) :
|
|
|
298
438
|
putString("url", response.url)
|
|
299
439
|
putString("error", response.error.ifEmpty { "" })
|
|
300
440
|
}
|
|
301
|
-
|
|
302
|
-
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
|
303
|
-
.emit("onDidFailResolvingURL", map)
|
|
441
|
+
emitOrBuffer("onDidFailResolvingURL", map)
|
|
304
442
|
}
|
|
305
443
|
|
|
306
444
|
|
|
@@ -322,18 +460,14 @@ class ComTappSoSdkModule(reactContext: ReactApplicationContext) :
|
|
|
322
460
|
}
|
|
323
461
|
putMap("data", dataMap)
|
|
324
462
|
}
|
|
325
|
-
|
|
326
|
-
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
|
327
|
-
.emit("onDeferredLinkReceived", map)
|
|
463
|
+
emitOrBuffer("onDeferredLinkReceived", map)
|
|
328
464
|
}
|
|
329
465
|
|
|
330
466
|
private fun sendTestEvent(test: String) {
|
|
331
467
|
val map: WritableMap = Arguments.createMap().apply {
|
|
332
468
|
putString("test", test)
|
|
333
469
|
}
|
|
334
|
-
|
|
335
|
-
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
|
336
|
-
.emit("onTestListener", map)
|
|
470
|
+
emitOrBuffer("onTestListener", map)
|
|
337
471
|
}
|
|
338
472
|
|
|
339
473
|
private fun convertResponseToMap(response: RequestModels.TappLinkDataResponse): WritableMap {
|
package/ios/ComTappSoSdk.mm
CHANGED
|
@@ -18,28 +18,31 @@
|
|
|
18
18
|
#endif
|
|
19
19
|
|
|
20
20
|
//-------------------------------------------------------------
|
|
21
|
-
// MARK: - Internal
|
|
21
|
+
// MARK: - Internal TappEventEmitter
|
|
22
22
|
// This module sends events from native to JS.
|
|
23
23
|
//-------------------------------------------------------------
|
|
24
|
-
@interface
|
|
24
|
+
@interface TappEventEmitter : RCTEventEmitter <RCTBridgeModule>
|
|
25
25
|
+ (instancetype)shared;
|
|
26
|
+
- (void)emitOrBuffer:(NSString *)eventName body:(id)body;
|
|
26
27
|
@end
|
|
27
28
|
|
|
28
29
|
static NSString * const kOnDeferredLinkReceived = @"onDeferredLinkReceived";
|
|
29
30
|
static NSString * const kOnDidFailResolvingURL = @"onDidFailResolvingURL";
|
|
30
31
|
static NSString * const kOnTestListener = @"onTestListener";
|
|
31
|
-
static
|
|
32
|
+
static TappEventEmitter *sharedInstance = nil;
|
|
32
33
|
|
|
33
|
-
@implementation
|
|
34
|
+
@implementation TappEventEmitter {
|
|
35
|
+
BOOL _hasListeners;
|
|
36
|
+
NSMutableArray<NSDictionary *> *_pendingEvents;
|
|
37
|
+
}
|
|
34
38
|
|
|
35
|
-
RCT_EXPORT_MODULE(
|
|
39
|
+
RCT_EXPORT_MODULE(TappEventEmitter);
|
|
36
40
|
|
|
37
41
|
- (instancetype)init {
|
|
38
42
|
if ((self = [super init])) {
|
|
39
43
|
sharedInstance = self;
|
|
40
|
-
[
|
|
41
|
-
|
|
42
|
-
[self addListener:kOnTestListener];
|
|
44
|
+
_pendingEvents = [NSMutableArray new];
|
|
45
|
+
_hasListeners = NO;
|
|
43
46
|
}
|
|
44
47
|
return self;
|
|
45
48
|
}
|
|
@@ -56,8 +59,38 @@ RCT_EXPORT_MODULE(EventEmitter);
|
|
|
56
59
|
return @[kOnDeferredLinkReceived, kOnDidFailResolvingURL, kOnTestListener];
|
|
57
60
|
}
|
|
58
61
|
|
|
59
|
-
- (void)startObserving {
|
|
60
|
-
|
|
62
|
+
- (void)startObserving {
|
|
63
|
+
_hasListeners = YES;
|
|
64
|
+
[self flushEvents];
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
- (void)stopObserving {
|
|
68
|
+
_hasListeners = NO;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
- (void)emitOrBuffer:(NSString *)eventName body:(id)body {
|
|
72
|
+
// Ensure main thread for safety, as listeners are JS-side
|
|
73
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
74
|
+
if (self->_hasListeners) {
|
|
75
|
+
[self sendEventWithName:eventName body:body];
|
|
76
|
+
} else {
|
|
77
|
+
[self->_pendingEvents addObject:@{@"name": eventName, @"body": body ?: [NSNull null]}];
|
|
78
|
+
// Keep buffer small (last 5 events) to avoid memory issues if listeners never attach
|
|
79
|
+
if (self->_pendingEvents.count > 5) {
|
|
80
|
+
[self->_pendingEvents removeObjectAtIndex:0];
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
- (void)flushEvents {
|
|
87
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
88
|
+
for (NSDictionary *event in self->_pendingEvents) {
|
|
89
|
+
[self sendEventWithName:event[@"name"] body:event[@"body"]];
|
|
90
|
+
}
|
|
91
|
+
[self->_pendingEvents removeAllObjects];
|
|
92
|
+
});
|
|
93
|
+
}
|
|
61
94
|
|
|
62
95
|
@end
|
|
63
96
|
|
|
@@ -273,16 +306,97 @@ RCT_EXPORT_METHOD(simulateTestEvent) {
|
|
|
273
306
|
NSLog(@"[ComTappSoSdk] simulateTestEvent is unsupported on iOS");
|
|
274
307
|
}
|
|
275
308
|
|
|
309
|
+
// DEBUG-only: Simulate a deferred link event for testing
|
|
310
|
+
// This should only be used in development for verifying event delivery
|
|
311
|
+
RCT_EXPORT_METHOD(simulateDeferredLink:(NSDictionary *)payload) {
|
|
312
|
+
#ifdef DEBUG
|
|
313
|
+
// Guard against nil payload from JS
|
|
314
|
+
NSDictionary *safePayload = payload ?: @{};
|
|
315
|
+
NSLog(@"[ComTappSoSdk] simulateDeferredLink called with: %@", safePayload);
|
|
316
|
+
|
|
317
|
+
// Build result on main thread to avoid any thread issues
|
|
318
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
319
|
+
NSDictionary *result = @{
|
|
320
|
+
@"error": @(NO),
|
|
321
|
+
@"message": [NSNull null],
|
|
322
|
+
@"tappUrl": safePayload[@"tappUrl"] ?: @"tapp://simulated",
|
|
323
|
+
@"attrTappUrl": safePayload[@"attrTappUrl"] ?: @"tapp://simulated/attributed",
|
|
324
|
+
@"influencer": safePayload[@"influencer"] ?: @"test_influencer",
|
|
325
|
+
@"data": safePayload[@"data"] ?: @{},
|
|
326
|
+
@"isFirstSession": safePayload[@"isFirstSession"] ?: @(YES)
|
|
327
|
+
};
|
|
328
|
+
|
|
329
|
+
TappEventEmitter *emitter = [TappEventEmitter shared];
|
|
330
|
+
if (emitter) {
|
|
331
|
+
[emitter emitOrBuffer:kOnDeferredLinkReceived body:result];
|
|
332
|
+
NSLog(@"[ComTappSoSdk] simulateDeferredLink emitted successfully");
|
|
333
|
+
} else {
|
|
334
|
+
NSLog(@"[ComTappSoSdk] simulateDeferredLink: No emitter available");
|
|
335
|
+
}
|
|
336
|
+
});
|
|
337
|
+
#else
|
|
338
|
+
NSLog(@"[ComTappSoSdk] simulateDeferredLink is only available in DEBUG builds");
|
|
339
|
+
#endif
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// DEBUG-only: Simulate a fail resolving URL event for testing
|
|
343
|
+
RCT_EXPORT_METHOD(simulateFailResolving:(NSString *)url errorMessage:(NSString *)errorMessage) {
|
|
344
|
+
#ifdef DEBUG
|
|
345
|
+
// Guard against nil values from JS
|
|
346
|
+
NSString *safeUrl = url ?: @"tapp://unknown";
|
|
347
|
+
NSString *safeError = errorMessage ?: @"Simulated error for testing";
|
|
348
|
+
NSLog(@"[ComTappSoSdk] simulateFailResolving called with url: %@, error: %@", safeUrl, safeError);
|
|
349
|
+
|
|
350
|
+
// Build result and emit on main thread
|
|
351
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
352
|
+
NSDictionary *result = @{
|
|
353
|
+
@"url": safeUrl,
|
|
354
|
+
@"error": safeError
|
|
355
|
+
};
|
|
356
|
+
|
|
357
|
+
TappEventEmitter *emitter = [TappEventEmitter shared];
|
|
358
|
+
if (emitter) {
|
|
359
|
+
[emitter emitOrBuffer:kOnDidFailResolvingURL body:result];
|
|
360
|
+
NSLog(@"[ComTappSoSdk] simulateFailResolving emitted successfully");
|
|
361
|
+
} else {
|
|
362
|
+
NSLog(@"[ComTappSoSdk] simulateFailResolving: No emitter available");
|
|
363
|
+
}
|
|
364
|
+
});
|
|
365
|
+
#else
|
|
366
|
+
NSLog(@"[ComTappSoSdk] simulateFailResolving is only available in DEBUG builds");
|
|
367
|
+
#endif
|
|
368
|
+
}
|
|
369
|
+
|
|
276
370
|
// ----------------------------------------------------------------------
|
|
277
371
|
// (Keep all existing methods below unchanged.)
|
|
278
372
|
// ----------------------------------------------------------------------
|
|
279
373
|
|
|
280
374
|
|
|
375
|
+
#pragma mark - TappDelegate Methods
|
|
376
|
+
|
|
377
|
+
// Helper to get the TappEventEmitter shared instance.
|
|
378
|
+
// In New Architecture, we must only use the shared static instance.
|
|
379
|
+
// Using self.bridge or moduleForClass causes EXC_BAD_ACCESS crashes.
|
|
380
|
+
- (TappEventEmitter *)ensureEmitter {
|
|
381
|
+
TappEventEmitter *emitter = [TappEventEmitter shared];
|
|
382
|
+
if (!emitter) {
|
|
383
|
+
NSLog(@"[ComTappSoSdk] WARNING: TappEventEmitter shared instance not yet available");
|
|
384
|
+
}
|
|
385
|
+
return emitter;
|
|
386
|
+
}
|
|
387
|
+
|
|
281
388
|
#pragma mark - TappDelegate Methods
|
|
282
389
|
|
|
283
390
|
- (void)didOpenApplicationWith:(TappDeferredLinkData *)data {
|
|
284
391
|
NSDictionary *result = [self dictionaryFromLinkData:data];
|
|
285
|
-
|
|
392
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
393
|
+
TappEventEmitter *emitter = [self ensureEmitter];
|
|
394
|
+
if (emitter) {
|
|
395
|
+
[emitter emitOrBuffer:kOnDeferredLinkReceived body:result];
|
|
396
|
+
} else {
|
|
397
|
+
NSLog(@"[ComTappSoSdk] ERROR: TappEventEmitter unavailable, event dropped");
|
|
398
|
+
}
|
|
399
|
+
});
|
|
286
400
|
}
|
|
287
401
|
|
|
288
402
|
- (void)didFailResolvingURLWithUrl:(NSURL *)url error:(NSError *)error {
|
|
@@ -290,7 +404,14 @@ RCT_EXPORT_METHOD(simulateTestEvent) {
|
|
|
290
404
|
@"url": url.absoluteString ?: @"",
|
|
291
405
|
@"error": error.localizedDescription ?: @""
|
|
292
406
|
};
|
|
293
|
-
|
|
407
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
408
|
+
TappEventEmitter *emitter = [self ensureEmitter];
|
|
409
|
+
if (emitter) {
|
|
410
|
+
[emitter emitOrBuffer:kOnDidFailResolvingURL body:result];
|
|
411
|
+
} else {
|
|
412
|
+
NSLog(@"[ComTappSoSdk] ERROR: TappEventEmitter unavailable, event dropped");
|
|
413
|
+
}
|
|
414
|
+
});
|
|
294
415
|
}
|
|
295
416
|
|
|
296
417
|
- (NSString *)mapEventAction:(double)eventAction {
|
|
@@ -54,6 +54,22 @@ namespace facebook::react {
|
|
|
54
54
|
return static_cast<ObjCTurboModule&>(turboModule).invokeObjCMethod(rt, VoidKind, "simulateTestEvent", @selector(simulateTestEvent), args, count);
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
+
static facebook::jsi::Value __hostFunction_NativeComTappSoSdkSpecJSI_simulateDeferredLink(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {
|
|
58
|
+
return static_cast<ObjCTurboModule&>(turboModule).invokeObjCMethod(rt, VoidKind, "simulateDeferredLink", @selector(simulateDeferredLink:), args, count);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
static facebook::jsi::Value __hostFunction_NativeComTappSoSdkSpecJSI_simulateFailResolving(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {
|
|
62
|
+
return static_cast<ObjCTurboModule&>(turboModule).invokeObjCMethod(rt, VoidKind, "simulateFailResolving", @selector(simulateFailResolving:errorMessage:), args, count);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
static facebook::jsi::Value __hostFunction_NativeComTappSoSdkSpecJSI_addListener(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {
|
|
66
|
+
return static_cast<ObjCTurboModule&>(turboModule).invokeObjCMethod(rt, VoidKind, "addListener", @selector(addListener:), args, count);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
static facebook::jsi::Value __hostFunction_NativeComTappSoSdkSpecJSI_removeListeners(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {
|
|
70
|
+
return static_cast<ObjCTurboModule&>(turboModule).invokeObjCMethod(rt, VoidKind, "removeListeners", @selector(removeListeners:), args, count);
|
|
71
|
+
}
|
|
72
|
+
|
|
57
73
|
NativeComTappSoSdkSpecJSI::NativeComTappSoSdkSpecJSI(const ObjCTurboModule::InitParams ¶ms)
|
|
58
74
|
: ObjCTurboModule(params) {
|
|
59
75
|
|
|
@@ -77,5 +93,17 @@ namespace facebook::react {
|
|
|
77
93
|
|
|
78
94
|
methodMap_["simulateTestEvent"] = MethodMetadata {0, __hostFunction_NativeComTappSoSdkSpecJSI_simulateTestEvent};
|
|
79
95
|
|
|
96
|
+
|
|
97
|
+
methodMap_["simulateDeferredLink"] = MethodMetadata {1, __hostFunction_NativeComTappSoSdkSpecJSI_simulateDeferredLink};
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
methodMap_["simulateFailResolving"] = MethodMetadata {2, __hostFunction_NativeComTappSoSdkSpecJSI_simulateFailResolving};
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
methodMap_["addListener"] = MethodMetadata {1, __hostFunction_NativeComTappSoSdkSpecJSI_addListener};
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
methodMap_["removeListeners"] = MethodMetadata {1, __hostFunction_NativeComTappSoSdkSpecJSI_removeListeners};
|
|
107
|
+
|
|
80
108
|
}
|
|
81
109
|
} // namespace facebook::react
|
|
@@ -58,6 +58,11 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
58
58
|
- (void)fetchOriginLinkData:(RCTPromiseResolveBlock)resolve
|
|
59
59
|
reject:(RCTPromiseRejectBlock)reject;
|
|
60
60
|
- (void)simulateTestEvent;
|
|
61
|
+
- (void)simulateDeferredLink:(NSDictionary *)payload;
|
|
62
|
+
- (void)simulateFailResolving:(NSString *)url
|
|
63
|
+
errorMessage:(NSString *)errorMessage;
|
|
64
|
+
- (void)addListener:(NSString *)eventName;
|
|
65
|
+
- (void)removeListeners:(double)count;
|
|
61
66
|
|
|
62
67
|
@end
|
|
63
68
|
|
|
@@ -60,6 +60,35 @@ static jsi::Value __hostFunction_NativeComTappSoSdkCxxSpecJSI_simulateTestEvent(
|
|
|
60
60
|
);
|
|
61
61
|
return jsi::Value::undefined();
|
|
62
62
|
}
|
|
63
|
+
static jsi::Value __hostFunction_NativeComTappSoSdkCxxSpecJSI_simulateDeferredLink(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
|
|
64
|
+
static_cast<NativeComTappSoSdkCxxSpecJSI *>(&turboModule)->simulateDeferredLink(
|
|
65
|
+
rt,
|
|
66
|
+
count <= 0 ? throw jsi::JSError(rt, "Expected argument in position 0 to be passed") : args[0].asObject(rt)
|
|
67
|
+
);
|
|
68
|
+
return jsi::Value::undefined();
|
|
69
|
+
}
|
|
70
|
+
static jsi::Value __hostFunction_NativeComTappSoSdkCxxSpecJSI_simulateFailResolving(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
|
|
71
|
+
static_cast<NativeComTappSoSdkCxxSpecJSI *>(&turboModule)->simulateFailResolving(
|
|
72
|
+
rt,
|
|
73
|
+
count <= 0 ? throw jsi::JSError(rt, "Expected argument in position 0 to be passed") : args[0].asString(rt),
|
|
74
|
+
count <= 1 ? throw jsi::JSError(rt, "Expected argument in position 1 to be passed") : args[1].asString(rt)
|
|
75
|
+
);
|
|
76
|
+
return jsi::Value::undefined();
|
|
77
|
+
}
|
|
78
|
+
static jsi::Value __hostFunction_NativeComTappSoSdkCxxSpecJSI_addListener(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
|
|
79
|
+
static_cast<NativeComTappSoSdkCxxSpecJSI *>(&turboModule)->addListener(
|
|
80
|
+
rt,
|
|
81
|
+
count <= 0 ? throw jsi::JSError(rt, "Expected argument in position 0 to be passed") : args[0].asString(rt)
|
|
82
|
+
);
|
|
83
|
+
return jsi::Value::undefined();
|
|
84
|
+
}
|
|
85
|
+
static jsi::Value __hostFunction_NativeComTappSoSdkCxxSpecJSI_removeListeners(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
|
|
86
|
+
static_cast<NativeComTappSoSdkCxxSpecJSI *>(&turboModule)->removeListeners(
|
|
87
|
+
rt,
|
|
88
|
+
count <= 0 ? throw jsi::JSError(rt, "Expected argument in position 0 to be passed") : args[0].asNumber()
|
|
89
|
+
);
|
|
90
|
+
return jsi::Value::undefined();
|
|
91
|
+
}
|
|
63
92
|
|
|
64
93
|
NativeComTappSoSdkCxxSpecJSI::NativeComTappSoSdkCxxSpecJSI(std::shared_ptr<CallInvoker> jsInvoker)
|
|
65
94
|
: TurboModule("ComTappSoSdk", jsInvoker) {
|
|
@@ -70,6 +99,10 @@ NativeComTappSoSdkCxxSpecJSI::NativeComTappSoSdkCxxSpecJSI(std::shared_ptr<CallI
|
|
|
70
99
|
methodMap_["shouldProcess"] = MethodMetadata {1, __hostFunction_NativeComTappSoSdkCxxSpecJSI_shouldProcess};
|
|
71
100
|
methodMap_["fetchOriginLinkData"] = MethodMetadata {0, __hostFunction_NativeComTappSoSdkCxxSpecJSI_fetchOriginLinkData};
|
|
72
101
|
methodMap_["simulateTestEvent"] = MethodMetadata {0, __hostFunction_NativeComTappSoSdkCxxSpecJSI_simulateTestEvent};
|
|
102
|
+
methodMap_["simulateDeferredLink"] = MethodMetadata {1, __hostFunction_NativeComTappSoSdkCxxSpecJSI_simulateDeferredLink};
|
|
103
|
+
methodMap_["simulateFailResolving"] = MethodMetadata {2, __hostFunction_NativeComTappSoSdkCxxSpecJSI_simulateFailResolving};
|
|
104
|
+
methodMap_["addListener"] = MethodMetadata {1, __hostFunction_NativeComTappSoSdkCxxSpecJSI_addListener};
|
|
105
|
+
methodMap_["removeListeners"] = MethodMetadata {1, __hostFunction_NativeComTappSoSdkCxxSpecJSI_removeListeners};
|
|
73
106
|
}
|
|
74
107
|
|
|
75
108
|
|
|
@@ -27,6 +27,10 @@ public:
|
|
|
27
27
|
virtual jsi::Value shouldProcess(jsi::Runtime &rt, jsi::String deepLink) = 0;
|
|
28
28
|
virtual jsi::Value fetchOriginLinkData(jsi::Runtime &rt) = 0;
|
|
29
29
|
virtual void simulateTestEvent(jsi::Runtime &rt) = 0;
|
|
30
|
+
virtual void simulateDeferredLink(jsi::Runtime &rt, jsi::Object payload) = 0;
|
|
31
|
+
virtual void simulateFailResolving(jsi::Runtime &rt, jsi::String url, jsi::String errorMessage) = 0;
|
|
32
|
+
virtual void addListener(jsi::Runtime &rt, jsi::String eventName) = 0;
|
|
33
|
+
virtual void removeListeners(jsi::Runtime &rt, double count) = 0;
|
|
30
34
|
|
|
31
35
|
};
|
|
32
36
|
|
|
@@ -113,6 +117,38 @@ private:
|
|
|
113
117
|
return bridging::callFromJs<void>(
|
|
114
118
|
rt, &T::simulateTestEvent, jsInvoker_, instance_);
|
|
115
119
|
}
|
|
120
|
+
void simulateDeferredLink(jsi::Runtime &rt, jsi::Object payload) override {
|
|
121
|
+
static_assert(
|
|
122
|
+
bridging::getParameterCount(&T::simulateDeferredLink) == 2,
|
|
123
|
+
"Expected simulateDeferredLink(...) to have 2 parameters");
|
|
124
|
+
|
|
125
|
+
return bridging::callFromJs<void>(
|
|
126
|
+
rt, &T::simulateDeferredLink, jsInvoker_, instance_, std::move(payload));
|
|
127
|
+
}
|
|
128
|
+
void simulateFailResolving(jsi::Runtime &rt, jsi::String url, jsi::String errorMessage) override {
|
|
129
|
+
static_assert(
|
|
130
|
+
bridging::getParameterCount(&T::simulateFailResolving) == 3,
|
|
131
|
+
"Expected simulateFailResolving(...) to have 3 parameters");
|
|
132
|
+
|
|
133
|
+
return bridging::callFromJs<void>(
|
|
134
|
+
rt, &T::simulateFailResolving, jsInvoker_, instance_, std::move(url), std::move(errorMessage));
|
|
135
|
+
}
|
|
136
|
+
void addListener(jsi::Runtime &rt, jsi::String eventName) override {
|
|
137
|
+
static_assert(
|
|
138
|
+
bridging::getParameterCount(&T::addListener) == 2,
|
|
139
|
+
"Expected addListener(...) to have 2 parameters");
|
|
140
|
+
|
|
141
|
+
return bridging::callFromJs<void>(
|
|
142
|
+
rt, &T::addListener, jsInvoker_, instance_, std::move(eventName));
|
|
143
|
+
}
|
|
144
|
+
void removeListeners(jsi::Runtime &rt, double count) override {
|
|
145
|
+
static_assert(
|
|
146
|
+
bridging::getParameterCount(&T::removeListeners) == 2,
|
|
147
|
+
"Expected removeListeners(...) to have 2 parameters");
|
|
148
|
+
|
|
149
|
+
return bridging::callFromJs<void>(
|
|
150
|
+
rt, &T::removeListeners, jsInvoker_, instance_, std::move(count));
|
|
151
|
+
}
|
|
116
152
|
|
|
117
153
|
private:
|
|
118
154
|
friend class NativeComTappSoSdkCxxSpec;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["TurboModuleRegistry","getEnforcing"],"sourceRoot":"../../src","sources":["NativeComTappSoSdk.ts"],"mappings":";;AAAA,SAASA,mBAAmB,QAA0B,cAAc;
|
|
1
|
+
{"version":3,"names":["TurboModuleRegistry","getEnforcing"],"sourceRoot":"../../src","sources":["NativeComTappSoSdk.ts"],"mappings":";;AAAA,SAASA,mBAAmB,QAA0B,cAAc;AAqDpE,eAAeA,mBAAmB,CAACC,YAAY,CAAO,cAAc,CAAC","ignoreList":[]}
|
package/lib/module/events.js
CHANGED
|
@@ -1,10 +1,26 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
import { NativeEventEmitter, NativeModules } from 'react-native';
|
|
3
|
+
import { NativeEventEmitter, NativeModules, Platform } from 'react-native';
|
|
4
4
|
const {
|
|
5
|
-
|
|
5
|
+
TappEventEmitter,
|
|
6
|
+
ComTappSoSdk
|
|
6
7
|
} = NativeModules;
|
|
7
|
-
|
|
8
|
+
import ComTappSoSdkTurbo from './NativeComTappSoSdk';
|
|
9
|
+
let eventEmitterModule;
|
|
10
|
+
if (Platform.OS === 'ios') {
|
|
11
|
+
eventEmitterModule = TappEventEmitter;
|
|
12
|
+
} else if (Platform.OS === 'android') {
|
|
13
|
+
// Policy: Prefer NativeModules.ComTappSoSdk because it is consistently wired
|
|
14
|
+
if (ComTappSoSdk && typeof ComTappSoSdk.addListener === 'function') {
|
|
15
|
+
eventEmitterModule = ComTappSoSdk;
|
|
16
|
+
} else if (ComTappSoSdkTurbo && typeof ComTappSoSdkTurbo.addListener === 'function') {
|
|
17
|
+
eventEmitterModule = ComTappSoSdkTurbo;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
if (!eventEmitterModule) {
|
|
21
|
+
console.warn(`[TappSDK] Event emitter module is undefined for platform: ${Platform.OS}. Events will not be received.`);
|
|
22
|
+
}
|
|
23
|
+
const eventEmitter = new NativeEventEmitter(eventEmitterModule);
|
|
8
24
|
export function addDeferredLinkListener(listener) {
|
|
9
25
|
return eventEmitter.addListener('onDeferredLinkReceived', listener);
|
|
10
26
|
}
|
package/lib/module/events.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["NativeEventEmitter","NativeModules","
|
|
1
|
+
{"version":3,"names":["NativeEventEmitter","NativeModules","Platform","TappEventEmitter","ComTappSoSdk","ComTappSoSdkTurbo","eventEmitterModule","OS","addListener","console","warn","eventEmitter","addDeferredLinkListener","listener","addDidFailResolvingURLListener","addTestListener"],"sourceRoot":"../../src","sources":["events.ts"],"mappings":";;AAAA,SAASA,kBAAkB,EAAEC,aAAa,EAAEC,QAAQ,QAAQ,cAAc;AAG1E,MAAM;EAAEC,gBAAgB;EAAEC;AAAa,CAAC,GAAGH,aAAa;AACxD,OAAOI,iBAAiB,MAAM,sBAAsB;AAEpD,IAAIC,kBAAuB;AAE3B,IAAIJ,QAAQ,CAACK,EAAE,KAAK,KAAK,EAAE;EACzBD,kBAAkB,GAAGH,gBAAgB;AACvC,CAAC,MAAM,IAAID,QAAQ,CAACK,EAAE,KAAK,SAAS,EAAE;EACpC;EACA,IAAIH,YAAY,IAAI,OAAOA,YAAY,CAACI,WAAW,KAAK,UAAU,EAAE;IAClEF,kBAAkB,GAAGF,YAAY;EACnC,CAAC,MAAM,IACLC,iBAAiB,IACjB,OAAOA,iBAAiB,CAACG,WAAW,KAAK,UAAU,EACnD;IACAF,kBAAkB,GAAGD,iBAAiB;EACxC;AACF;AAEA,IAAI,CAACC,kBAAkB,EAAE;EACvBG,OAAO,CAACC,IAAI,CACV,6DAA6DR,QAAQ,CAACK,EAAE,gCAC1E,CAAC;AACH;AAEA,MAAMI,YAAY,GAAG,IAAIX,kBAAkB,CAACM,kBAAkB,CAAC;AAE/D,OAAO,SAASM,uBAAuBA,CACrCC,QAAkD,EAClD;EACA,OAAOF,YAAY,CAACH,WAAW,CAAC,wBAAwB,EAAEK,QAAQ,CAAC;AACrE;AAEA,OAAO,SAASC,8BAA8BA,CAC5CD,QAA4D,EAC5D;EACA,OAAOF,YAAY,CAACH,WAAW,CAAC,uBAAuB,EAAEK,QAAQ,CAAC;AACpE;AAEA,OAAO,SAASE,eAAeA,CAACF,QAA0C,EAAE;EAC1E,OAAOF,YAAY,CAACH,WAAW,CAAC,gBAAgB,EAAEK,QAAQ,CAAC;AAC7D","ignoreList":[]}
|
package/lib/module/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
import ComTappSoSdk from './NativeComTappSoSdk';
|
|
4
|
-
import { Platform } from 'react-native';
|
|
4
|
+
import { Platform, NativeModules } from 'react-native';
|
|
5
5
|
import { EventAction } from './Types';
|
|
6
6
|
|
|
7
7
|
// Helper to handle unsupported platforms
|
|
@@ -12,6 +12,15 @@ export function start(config) {
|
|
|
12
12
|
if (Platform.OS === 'web') {
|
|
13
13
|
unsupportedPlatformMessage('start');
|
|
14
14
|
}
|
|
15
|
+
// Force-init the event emitter module to prevent race conditions
|
|
16
|
+
if (Platform.OS === 'ios') {
|
|
17
|
+
const {
|
|
18
|
+
TappEventEmitter
|
|
19
|
+
} = NativeModules;
|
|
20
|
+
if (TappEventEmitter) {
|
|
21
|
+
/* no-op access to trigger init */
|
|
22
|
+
}
|
|
23
|
+
}
|
|
15
24
|
ComTappSoSdk.start(config.authToken, config.env, config.tappToken);
|
|
16
25
|
}
|
|
17
26
|
export function url(influencer, adGroup, creative, data) {
|
|
@@ -53,6 +62,26 @@ export function simulateTestEvent() {
|
|
|
53
62
|
}
|
|
54
63
|
return ComTappSoSdk.simulateTestEvent();
|
|
55
64
|
}
|
|
65
|
+
|
|
66
|
+
// DEBUG-only: Simulate a deferred link event for iOS testing
|
|
67
|
+
// Only works in DEBUG builds on iOS
|
|
68
|
+
export function simulateDeferredLink(payload) {
|
|
69
|
+
if (Platform.OS !== 'ios') {
|
|
70
|
+
console.log('[simulateDeferredLink] Only supported on iOS');
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
ComTappSoSdk.simulateDeferredLink(payload || {});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// DEBUG-only: Simulate a fail resolving URL event for iOS testing
|
|
77
|
+
// Only works in DEBUG builds on iOS
|
|
78
|
+
export function simulateFailResolving(url, error) {
|
|
79
|
+
if (Platform.OS !== 'ios') {
|
|
80
|
+
console.log('[simulateFailResolving] Only supported on iOS');
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
ComTappSoSdk.simulateFailResolving(url, error);
|
|
84
|
+
}
|
|
56
85
|
export * from './Types';
|
|
57
86
|
export * from './events';
|
|
58
87
|
//# sourceMappingURL=index.js.map
|
package/lib/module/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["ComTappSoSdk","Platform","EventAction","unsupportedPlatformMessage","methodName","console","log","OS","start","config","authToken","env","tappToken","url","influencer","adGroup","creative","data","handleTappEvent","event","value","customValue","eventAction","CUSTOM","undefined","metadata","fetchLinkData","deepLink","shouldProcess","fetchOriginLinkData","simulateTestEvent"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,OAAOA,YAAY,MAAM,sBAAsB;AAC/C,SAASC,QAAQ,QAAQ,cAAc;
|
|
1
|
+
{"version":3,"names":["ComTappSoSdk","Platform","NativeModules","EventAction","unsupportedPlatformMessage","methodName","console","log","OS","start","config","TappEventEmitter","authToken","env","tappToken","url","influencer","adGroup","creative","data","handleTappEvent","event","value","customValue","eventAction","CUSTOM","undefined","metadata","fetchLinkData","deepLink","shouldProcess","fetchOriginLinkData","simulateTestEvent","simulateDeferredLink","payload","simulateFailResolving","error"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -31,6 +31,10 @@ export interface Spec extends TurboModule {
|
|
|
31
31
|
isFirstSession?: boolean;
|
|
32
32
|
}>;
|
|
33
33
|
simulateTestEvent(): void;
|
|
34
|
+
simulateDeferredLink(payload: UnsafeObject): void;
|
|
35
|
+
simulateFailResolving(url: string, errorMessage: string): void;
|
|
36
|
+
addListener(eventName: string): void;
|
|
37
|
+
removeListeners(count: number): void;
|
|
34
38
|
}
|
|
35
39
|
declare const _default: Spec;
|
|
36
40
|
export default _default;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NativeComTappSoSdk.d.ts","sourceRoot":"","sources":["../../../src/NativeComTappSoSdk.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AACrE,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,2CAA2C,CAAC;AAE9E,MAAM,WAAW,IAAK,SAAQ,WAAW;IACvC,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAE/D,GAAG,CACD,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,MAAM,EAChB,QAAQ,CAAC,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,GAC/B,OAAO,CAAC,MAAM,CAAC,CAAC;IAEnB,eAAe,CACb,WAAW,EAAE,MAAM,EACnB,WAAW,CAAC,EAAE,MAAM,EACpB,QAAQ,CAAC,EAAE,YAAY,GACtB,OAAO,CAAC,MAAM,CAAC,CAAC;IAEnB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;QACvC,KAAK,EAAE,OAAO,CAAC;QACf,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,IAAI,CAAC,EAAE;YAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;SAAE,CAAC;QACjC,cAAc,CAAC,EAAE,OAAO,CAAC;QACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC,CAAC;IAEH,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAElD,mBAAmB,IAAI,OAAO,CAAC;QAC7B,KAAK,EAAE,OAAO,CAAC;QACf,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,IAAI,CAAC,EAAE;YAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;SAAE,CAAC;QACjC,cAAc,CAAC,EAAE,OAAO,CAAC;KAC1B,CAAC,CAAC;IAEH,iBAAiB,IAAI,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"NativeComTappSoSdk.d.ts","sourceRoot":"","sources":["../../../src/NativeComTappSoSdk.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AACrE,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,2CAA2C,CAAC;AAE9E,MAAM,WAAW,IAAK,SAAQ,WAAW;IACvC,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAE/D,GAAG,CACD,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,MAAM,EAChB,QAAQ,CAAC,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,GAC/B,OAAO,CAAC,MAAM,CAAC,CAAC;IAEnB,eAAe,CACb,WAAW,EAAE,MAAM,EACnB,WAAW,CAAC,EAAE,MAAM,EACpB,QAAQ,CAAC,EAAE,YAAY,GACtB,OAAO,CAAC,MAAM,CAAC,CAAC;IAEnB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;QACvC,KAAK,EAAE,OAAO,CAAC;QACf,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,IAAI,CAAC,EAAE;YAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;SAAE,CAAC;QACjC,cAAc,CAAC,EAAE,OAAO,CAAC;QACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC,CAAC;IAEH,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAElD,mBAAmB,IAAI,OAAO,CAAC;QAC7B,KAAK,EAAE,OAAO,CAAC;QACf,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,IAAI,CAAC,EAAE;YAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;SAAE,CAAC;QACjC,cAAc,CAAC,EAAE,OAAO,CAAC;KAC1B,CAAC,CAAC;IAEH,iBAAiB,IAAI,IAAI,CAAC;IAI1B,oBAAoB,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI,CAAC;IAClD,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAE/D,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtC;;AAED,wBAAsE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../../src/events.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../../src/events.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AA6BpD,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,CAAC,QAAQ,EAAE,oBAAoB,KAAK,IAAI,8CAGnD;AAED,wBAAgB,8BAA8B,CAC5C,QAAQ,EAAE,CAAC,QAAQ,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,KAAK,IAAI,8CAG7D;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,KAAK,IAAI,8CAEzE"}
|
|
@@ -8,6 +8,16 @@ export declare function fetchLinkData(deepLink: string): Promise<TappLinkDataRes
|
|
|
8
8
|
export declare function shouldProcess(deepLink: string): Promise<boolean>;
|
|
9
9
|
export declare function fetchOriginLinkData(): Promise<TappLinkDataResponse>;
|
|
10
10
|
export declare function simulateTestEvent(): void;
|
|
11
|
+
export declare function simulateDeferredLink(payload?: {
|
|
12
|
+
tappUrl?: string;
|
|
13
|
+
attrTappUrl?: string;
|
|
14
|
+
influencer?: string;
|
|
15
|
+
data?: {
|
|
16
|
+
[key: string]: string;
|
|
17
|
+
};
|
|
18
|
+
isFirstSession?: boolean;
|
|
19
|
+
}): void;
|
|
20
|
+
export declare function simulateFailResolving(url: string, error: string): void;
|
|
11
21
|
export * from './Types';
|
|
12
22
|
export * from './events';
|
|
13
23
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,oBAAoB,EAC1B,MAAM,SAAS,CAAC;AAOjB,wBAAgB,KAAK,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,oBAAoB,EAC1B,MAAM,SAAS,CAAC;AAOjB,wBAAgB,KAAK,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAY9C;AAED,wBAAgB,GAAG,CACjB,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,MAAM,EAChB,QAAQ,CAAC,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,GAC/B,OAAO,CAAC,MAAM,CAAC,CAKjB;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAgBrE;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAK7E;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAKhE;AAED,wBAAgB,mBAAmB,IAAI,OAAO,CAAC,oBAAoB,CAAC,CAKnE;AAED,wBAAgB,iBAAiB,IAAI,IAAI,CAKxC;AAID,wBAAgB,oBAAoB,CAAC,OAAO,CAAC,EAAE;IAC7C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;IACjC,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B,GAAG,IAAI,CAMP;AAID,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAMtE;AAED,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC"}
|
package/package.json
CHANGED
|
@@ -41,6 +41,14 @@ export interface Spec extends TurboModule {
|
|
|
41
41
|
}>;
|
|
42
42
|
|
|
43
43
|
simulateTestEvent(): void;
|
|
44
|
+
|
|
45
|
+
// DEBUG-only: iOS simulation methods for testing event delivery
|
|
46
|
+
// Using UnsafeObject to match NSDictionary* in Obj-C TurboModule
|
|
47
|
+
simulateDeferredLink(payload: UnsafeObject): void;
|
|
48
|
+
simulateFailResolving(url: string, errorMessage: string): void;
|
|
49
|
+
|
|
50
|
+
addListener(eventName: string): void;
|
|
51
|
+
removeListeners(count: number): void;
|
|
44
52
|
}
|
|
45
53
|
|
|
46
54
|
export default TurboModuleRegistry.getEnforcing<Spec>('ComTappSoSdk');
|
package/src/events.ts
CHANGED
|
@@ -1,8 +1,32 @@
|
|
|
1
|
-
import { NativeEventEmitter, NativeModules } from 'react-native';
|
|
1
|
+
import { NativeEventEmitter, NativeModules, Platform } from 'react-native';
|
|
2
2
|
import type { TappLinkDataResponse } from './Types';
|
|
3
3
|
|
|
4
|
-
const {
|
|
5
|
-
|
|
4
|
+
const { TappEventEmitter, ComTappSoSdk } = NativeModules;
|
|
5
|
+
import ComTappSoSdkTurbo from './NativeComTappSoSdk';
|
|
6
|
+
|
|
7
|
+
let eventEmitterModule: any;
|
|
8
|
+
|
|
9
|
+
if (Platform.OS === 'ios') {
|
|
10
|
+
eventEmitterModule = TappEventEmitter;
|
|
11
|
+
} else if (Platform.OS === 'android') {
|
|
12
|
+
// Policy: Prefer NativeModules.ComTappSoSdk because it is consistently wired
|
|
13
|
+
if (ComTappSoSdk && typeof ComTappSoSdk.addListener === 'function') {
|
|
14
|
+
eventEmitterModule = ComTappSoSdk;
|
|
15
|
+
} else if (
|
|
16
|
+
ComTappSoSdkTurbo &&
|
|
17
|
+
typeof ComTappSoSdkTurbo.addListener === 'function'
|
|
18
|
+
) {
|
|
19
|
+
eventEmitterModule = ComTappSoSdkTurbo;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (!eventEmitterModule) {
|
|
24
|
+
console.warn(
|
|
25
|
+
`[TappSDK] Event emitter module is undefined for platform: ${Platform.OS}. Events will not be received.`
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const eventEmitter = new NativeEventEmitter(eventEmitterModule);
|
|
6
30
|
|
|
7
31
|
export function addDeferredLinkListener(
|
|
8
32
|
listener: (response: TappLinkDataResponse) => void
|
package/src/index.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import ComTappSoSdk from './NativeComTappSoSdk';
|
|
2
|
-
import { Platform } from 'react-native';
|
|
2
|
+
import { Platform, NativeModules } from 'react-native';
|
|
3
3
|
import {
|
|
4
4
|
EventAction,
|
|
5
5
|
type InitConfig,
|
|
@@ -16,6 +16,13 @@ export function start(config: InitConfig): void {
|
|
|
16
16
|
if (Platform.OS === 'web') {
|
|
17
17
|
unsupportedPlatformMessage('start');
|
|
18
18
|
}
|
|
19
|
+
// Force-init the event emitter module to prevent race conditions
|
|
20
|
+
if (Platform.OS === 'ios') {
|
|
21
|
+
const { TappEventEmitter } = NativeModules;
|
|
22
|
+
if (TappEventEmitter) {
|
|
23
|
+
/* no-op access to trigger init */
|
|
24
|
+
}
|
|
25
|
+
}
|
|
19
26
|
ComTappSoSdk.start(config.authToken, config.env, config.tappToken);
|
|
20
27
|
}
|
|
21
28
|
|
|
@@ -77,5 +84,31 @@ export function simulateTestEvent(): void {
|
|
|
77
84
|
return ComTappSoSdk.simulateTestEvent();
|
|
78
85
|
}
|
|
79
86
|
|
|
87
|
+
// DEBUG-only: Simulate a deferred link event for iOS testing
|
|
88
|
+
// Only works in DEBUG builds on iOS
|
|
89
|
+
export function simulateDeferredLink(payload?: {
|
|
90
|
+
tappUrl?: string;
|
|
91
|
+
attrTappUrl?: string;
|
|
92
|
+
influencer?: string;
|
|
93
|
+
data?: { [key: string]: string };
|
|
94
|
+
isFirstSession?: boolean;
|
|
95
|
+
}): void {
|
|
96
|
+
if (Platform.OS !== 'ios') {
|
|
97
|
+
console.log('[simulateDeferredLink] Only supported on iOS');
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
ComTappSoSdk.simulateDeferredLink(payload || {});
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// DEBUG-only: Simulate a fail resolving URL event for iOS testing
|
|
104
|
+
// Only works in DEBUG builds on iOS
|
|
105
|
+
export function simulateFailResolving(url: string, error: string): void {
|
|
106
|
+
if (Platform.OS !== 'ios') {
|
|
107
|
+
console.log('[simulateFailResolving] Only supported on iOS');
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
ComTappSoSdk.simulateFailResolving(url, error);
|
|
111
|
+
}
|
|
112
|
+
|
|
80
113
|
export * from './Types';
|
|
81
114
|
export * from './events';
|