@attentive-mobile/attentive-react-native-sdk 1.0.3-beta.1 → 2.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/README.md +150 -0
  2. package/android/build.gradle +4 -0
  3. package/android/src/main/kotlin/com/attentivereactnativesdk/AttentiveReactNativeSdkModule.kt +384 -0
  4. package/android/src/main/kotlin/com/attentivereactnativesdk/AttentiveReactNativeSdkPackage.kt +36 -0
  5. package/android/src/main/kotlin/com/attentivereactnativesdk/debug/AttentiveDebugHelper.kt +438 -0
  6. package/android/src/main/kotlin/com/attentivereactnativesdk/debug/DebugEvent.kt +76 -0
  7. package/attentive-react-native-sdk.podspec +4 -5
  8. package/ios/AttentiveReactNativeSdk.h +6 -6
  9. package/ios/AttentiveReactNativeSdk.mm +325 -35
  10. package/ios/AttentiveReactNativeSdk.xcodeproj/project.pbxproj +2 -2
  11. package/ios/Bridging/ATTNNativeSDK.swift +1118 -3
  12. package/ios/Bridging/AttentiveReactNativeSdk-Bridging-Header.h +3 -0
  13. package/ios/Bridging/AttentiveSDKManager.swift +83 -0
  14. package/ios/Podfile +4 -17
  15. package/lib/commonjs/NativeAttentiveReactNativeSdk.js +14 -0
  16. package/lib/commonjs/NativeAttentiveReactNativeSdk.js.map +1 -0
  17. package/lib/commonjs/index.js +363 -39
  18. package/lib/commonjs/index.js.map +1 -1
  19. package/lib/module/NativeAttentiveReactNativeSdk.js +7 -0
  20. package/lib/module/NativeAttentiveReactNativeSdk.js.map +1 -0
  21. package/lib/module/index.js +346 -38
  22. package/lib/module/index.js.map +1 -1
  23. package/lib/typescript/NativeAttentiveReactNativeSdk.d.ts +103 -0
  24. package/lib/typescript/NativeAttentiveReactNativeSdk.d.ts.map +1 -0
  25. package/lib/typescript/eventTypes.d.ts +44 -17
  26. package/lib/typescript/eventTypes.d.ts.map +1 -1
  27. package/lib/typescript/index.d.ts +276 -33
  28. package/lib/typescript/index.d.ts.map +1 -1
  29. package/package.json +22 -8
  30. package/src/NativeAttentiveReactNativeSdk.ts +152 -0
  31. package/src/eventTypes.tsx +57 -20
  32. package/src/index.tsx +472 -82
  33. package/android/src/main/java/com/attentivereactnativesdk/AttentiveReactNativeSdkModule.java +0 -247
  34. package/android/src/main/java/com/attentivereactnativesdk/AttentiveReactNativeSdkPackage.java +0 -28
@@ -6,6 +6,7 @@
6
6
  //
7
7
 
8
8
  #import "AttentiveReactNativeSdk.h"
9
+ #import <UserNotifications/UserNotifications.h>
9
10
 
10
11
  #if __has_include(<AttentiveReactNativeSdk-Swift.h>)
11
12
  #import "AttentiveReactNativeSdk-Swift.h"
@@ -20,65 +21,354 @@
20
21
 
21
22
  RCT_EXPORT_MODULE()
22
23
 
23
- RCT_EXPORT_METHOD(initialize:(NSDictionary*)configuration) {
24
- _sdk = [[ATTNNativeSDK alloc] initWithDomain:configuration[@"attentiveDomain"] mode:configuration[@"mode"] skipFatigueOnCreatives:configuration[@"skipFatigueOnCreatives"]];
24
+ #ifdef RCT_NEW_ARCH_ENABLED
25
+ // New Architecture implementation with flattened parameters
26
+ - (void)initialize:(NSString *)attentiveDomain
27
+ mode:(NSString *)mode
28
+ skipFatigueOnCreatives:(BOOL)skipFatigueOnCreatives
29
+ enableDebugger:(BOOL)enableDebugger {
30
+ _sdk = [[ATTNNativeSDK alloc] initWithDomain:attentiveDomain
31
+ mode:mode
32
+ skipFatigueOnCreatives:skipFatigueOnCreatives
33
+ enableDebugger:enableDebugger];
34
+
35
+ // Make SDK instance accessible from native code (e.g., AppDelegate)
36
+ [AttentiveSDKManager shared].sdk = _sdk;
37
+ }
38
+
39
+ - (void)identify:(NSString *)phone
40
+ email:(NSString *)email
41
+ klaviyoId:(NSString *)klaviyoId
42
+ shopifyId:(NSString *)shopifyId
43
+ clientUserId:(NSString *)clientUserId
44
+ customIdentifiers:(NSDictionary *)customIdentifiers {
45
+ NSMutableDictionary *identifiers = [NSMutableDictionary new];
46
+ if (phone && ![phone isEqual:[NSNull null]]) identifiers[@"phone"] = phone;
47
+ if (email && ![email isEqual:[NSNull null]]) identifiers[@"email"] = email;
48
+ if (klaviyoId && ![klaviyoId isEqual:[NSNull null]]) identifiers[@"klaviyoId"] = klaviyoId;
49
+ if (shopifyId && ![shopifyId isEqual:[NSNull null]]) identifiers[@"shopifyId"] = shopifyId;
50
+ if (clientUserId && ![clientUserId isEqual:[NSNull null]]) identifiers[@"clientUserId"] = clientUserId;
51
+ if (customIdentifiers && ![customIdentifiers isEqual:[NSNull null]]) identifiers[@"customIdentifiers"] = customIdentifiers;
52
+
53
+ [_sdk identify:identifiers];
54
+ }
55
+
56
+ - (void)recordAddToCartEvent:(NSArray *)items
57
+ deeplink:(NSString *)deeplink {
58
+ NSMutableDictionary *attrs = [NSMutableDictionary new];
59
+ attrs[@"items"] = items;
60
+ if (deeplink && ![deeplink isEqual:[NSNull null]]) attrs[@"deeplink"] = deeplink;
61
+ [_sdk recordAddToCartEvent:attrs];
62
+ }
63
+
64
+ - (void)recordProductViewEvent:(NSArray *)items
65
+ deeplink:(NSString *)deeplink {
66
+ NSMutableDictionary *attrs = [NSMutableDictionary new];
67
+ attrs[@"items"] = items;
68
+ if (deeplink && ![deeplink isEqual:[NSNull null]]) attrs[@"deeplink"] = deeplink;
69
+ [_sdk recordProductViewEvent:attrs];
70
+ }
71
+
72
+ - (void)recordPurchaseEvent:(NSArray *)items
73
+ orderId:(NSString *)orderId
74
+ cartId:(NSString *)cartId
75
+ cartCoupon:(NSString *)cartCoupon {
76
+ NSMutableDictionary *attrs = [NSMutableDictionary new];
77
+ attrs[@"items"] = items;
78
+ attrs[@"orderId"] = orderId;
79
+ if (cartId && ![cartId isEqual:[NSNull null]]) attrs[@"cartId"] = cartId;
80
+ if (cartCoupon && ![cartCoupon isEqual:[NSNull null]]) attrs[@"cartCoupon"] = cartCoupon;
81
+ [_sdk recordPurchaseEvent:attrs];
82
+ }
83
+
84
+ - (void)recordCustomEvent:(NSString *)type
85
+ properties:(NSDictionary *)properties {
86
+ NSMutableDictionary *attrs = [NSMutableDictionary new];
87
+ attrs[@"type"] = type;
88
+ attrs[@"properties"] = properties;
89
+ [_sdk recordCustomEvent:attrs];
90
+ }
91
+
92
+ // Push Notification Methods (New Architecture)
93
+ - (void)registerForPushNotifications {
94
+ [_sdk registerForPushNotifications];
95
+ }
96
+
97
+ - (void)registerDeviceToken:(NSString *)token
98
+ authorizationStatus:(NSString *)authorizationStatus {
99
+ [_sdk registerDeviceToken:token authorizationStatus:authorizationStatus];
100
+ }
101
+
102
+ - (void)registerDeviceTokenWithCallback:(NSString *)token
103
+ authorizationStatus:(NSString *)authorizationStatus
104
+ callback:(RCTResponseSenderBlock)callback {
105
+ // Convert hex string token to Data
106
+ NSMutableData *tokenData = [[NSMutableData alloc] init];
107
+ unsigned char byte;
108
+ for (NSUInteger i = 0; i < token.length; i += 2) {
109
+ NSString *hex = [token substringWithRange:NSMakeRange(i, 2)];
110
+ if ([[NSScanner scannerWithString:hex] scanHexInt:(unsigned int *)&byte]) {
111
+ [tokenData appendBytes:&byte length:1];
112
+ }
113
+ }
114
+
115
+ // Convert string authorization status to UNAuthorizationStatus enum
116
+ UNAuthorizationStatus authStatus = [self authorizationStatusFromString:authorizationStatus];
117
+
118
+ // Call the Swift method with callback (note: selector is registerDeviceTokenWithCallback:authorizationStatus:callback:)
119
+ [_sdk registerDeviceTokenWithCallback:tokenData
120
+ authorizationStatus:authStatus
121
+ callback:^(NSData * _Nullable data, NSURL * _Nullable url, NSURLResponse * _Nullable response, NSError * _Nullable error) {
122
+ // Convert response to JavaScript-compatible objects
123
+ NSDictionary *dataDict = nil;
124
+ if (data) {
125
+ NSString *dataString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
126
+ if (dataString) {
127
+ dataDict = @{@"string": dataString, @"length": @(data.length)};
128
+ }
129
+ }
130
+
131
+ NSString *urlString = url ? [url absoluteString] : nil;
132
+
133
+ NSDictionary *responseDict = nil;
134
+ if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
135
+ NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
136
+ responseDict = @{
137
+ @"statusCode": @(httpResponse.statusCode),
138
+ @"headers": httpResponse.allHeaderFields ?: @{}
139
+ };
140
+ }
141
+
142
+ NSDictionary *errorDict = nil;
143
+ if (error) {
144
+ errorDict = @{
145
+ @"code": @(error.code),
146
+ @"domain": error.domain,
147
+ @"description": error.localizedDescription
148
+ };
149
+ }
150
+
151
+ // Invoke the callback with the results
152
+ callback(@[dataDict ?: [NSNull null],
153
+ urlString ?: [NSNull null],
154
+ responseDict ?: [NSNull null],
155
+ errorDict ?: [NSNull null]]);
156
+ }];
157
+ }
158
+
159
+ - (void)handleRegularOpen:(NSString *)authorizationStatus {
160
+ UNAuthorizationStatus authStatus = [self authorizationStatusFromString:authorizationStatus];
161
+ [_sdk handleRegularOpen:authStatus];
162
+ }
163
+
164
+ - (void)handlePushOpened:(NSDictionary *)userInfo
165
+ applicationState:(NSString *)applicationState
166
+ authorizationStatus:(NSString *)authorizationStatus {
167
+ [_sdk handlePushOpened:userInfo applicationState:applicationState authorizationStatus:authorizationStatus];
168
+ }
169
+
170
+ - (void)handleForegroundNotification:(NSDictionary *)userInfo {
171
+ [_sdk handleForegroundNotification:userInfo];
172
+ }
173
+
174
+ - (void)handleForegroundPush:(NSDictionary *)userInfo
175
+ authorizationStatus:(NSString *)authorizationStatus {
176
+ [_sdk handleForegroundPushFromRN:userInfo authorizationStatus:authorizationStatus];
177
+ }
178
+
179
+ - (void)handlePushOpen:(NSDictionary *)userInfo
180
+ authorizationStatus:(NSString *)authorizationStatus {
181
+ [_sdk handlePushOpenFromRN:userInfo authorizationStatus:authorizationStatus];
182
+ }
183
+
184
+ // Helper method to convert string to UNAuthorizationStatus
185
+ - (UNAuthorizationStatus)authorizationStatusFromString:(NSString *)statusString {
186
+ if ([statusString isEqualToString:@"authorized"]) {
187
+ return UNAuthorizationStatusAuthorized;
188
+ } else if ([statusString isEqualToString:@"denied"]) {
189
+ return UNAuthorizationStatusDenied;
190
+ } else if ([statusString isEqualToString:@"notDetermined"]) {
191
+ return UNAuthorizationStatusNotDetermined;
192
+ } else if ([statusString isEqualToString:@"provisional"]) {
193
+ if (@available(iOS 12.0, *)) {
194
+ return UNAuthorizationStatusProvisional;
195
+ }
196
+ return UNAuthorizationStatusNotDetermined;
197
+ } else if ([statusString isEqualToString:@"ephemeral"]) {
198
+ if (@available(iOS 14.0, *)) {
199
+ return UNAuthorizationStatusEphemeral;
200
+ }
201
+ return UNAuthorizationStatusNotDetermined;
202
+ }
203
+ return UNAuthorizationStatusNotDetermined;
204
+ }
205
+
206
+ - (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
207
+ (const facebook::react::ObjCTurboModule::InitParams &)params
208
+ {
209
+ return std::make_shared<facebook::react::NativeAttentiveReactNativeSdkSpecJSI>(params);
210
+ }
211
+
212
+ #else
213
+ // Old Architecture implementation with dictionary parameters
214
+ - (void)initialize:(NSDictionary*)configuration {
215
+ _sdk = [[ATTNNativeSDK alloc] initWithDomain:configuration[@"attentiveDomain"]
216
+ mode:configuration[@"mode"]
217
+ skipFatigueOnCreatives:configuration[@"skipFatigueOnCreatives"]
218
+ enableDebugger:configuration[@"enableDebugger"]];
219
+
220
+ // Make SDK instance accessible from native code (e.g., AppDelegate)
221
+ [AttentiveSDKManager shared].sdk = _sdk;
222
+ }
223
+
224
+ - (void)identify:(NSDictionary*)identifiers {
225
+ [_sdk identify:identifiers];
226
+ }
227
+
228
+ - (void)recordAddToCartEvent:(NSDictionary*)attrs {
229
+ [_sdk recordAddToCartEvent:attrs];
230
+ }
231
+
232
+ - (void)recordProductViewEvent:(NSDictionary*)attrs {
233
+ [_sdk recordProductViewEvent:attrs];
234
+ }
235
+
236
+ - (void)recordPurchaseEvent:(NSDictionary*)attrs {
237
+ [_sdk recordPurchaseEvent:attrs];
238
+ }
239
+
240
+ - (void)recordCustomEvent:(NSDictionary*)attrs {
241
+ [_sdk recordCustomEvent:attrs];
242
+ }
243
+
244
+ // Push Notification Methods (Old Architecture)
245
+ - (void)registerForPushNotifications {
246
+ [_sdk registerForPushNotifications];
247
+ }
248
+
249
+ - (void)registerDeviceToken:(NSString *)token
250
+ authorizationStatus:(NSString *)authorizationStatus {
251
+ [_sdk registerDeviceToken:token authorizationStatus:authorizationStatus];
252
+ }
253
+
254
+ - (void)registerDeviceTokenWithCallback:(NSString *)token
255
+ authorizationStatus:(NSString *)authorizationStatus
256
+ callback:(RCTResponseSenderBlock)callback {
257
+ // Convert hex string token to Data
258
+ NSMutableData *tokenData = [[NSMutableData alloc] init];
259
+ unsigned char byte;
260
+ for (NSUInteger i = 0; i < token.length; i += 2) {
261
+ NSString *hex = [token substringWithRange:NSMakeRange(i, 2)];
262
+ if ([[NSScanner scannerWithString:hex] scanHexInt:(unsigned int *)&byte]) {
263
+ [tokenData appendBytes:&byte length:1];
264
+ }
265
+ }
266
+
267
+ // Convert string authorization status to UNAuthorizationStatus enum
268
+ UNAuthorizationStatus authStatus = [self authorizationStatusFromString:authorizationStatus];
269
+
270
+ // Call the Swift method with callback (note: selector is registerDeviceTokenWithCallback:authorizationStatus:callback:)
271
+ [_sdk registerDeviceTokenWithCallback:tokenData
272
+ authorizationStatus:authStatus
273
+ callback:^(NSData * _Nullable data, NSURL * _Nullable url, NSURLResponse * _Nullable response, NSError * _Nullable error) {
274
+ // Convert response to JavaScript-compatible objects
275
+ NSDictionary *dataDict = nil;
276
+ if (data) {
277
+ NSString *dataString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
278
+ if (dataString) {
279
+ dataDict = @{@"string": dataString, @"length": @(data.length)};
280
+ }
281
+ }
282
+
283
+ NSString *urlString = url ? [url absoluteString] : nil;
284
+
285
+ NSDictionary *responseDict = nil;
286
+ if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
287
+ NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
288
+ responseDict = @{
289
+ @"statusCode": @(httpResponse.statusCode),
290
+ @"headers": httpResponse.allHeaderFields ?: @{}
291
+ };
292
+ }
293
+
294
+ NSDictionary *errorDict = nil;
295
+ if (error) {
296
+ errorDict = @{
297
+ @"code": @(error.code),
298
+ @"domain": error.domain,
299
+ @"description": error.localizedDescription
300
+ };
301
+ }
302
+
303
+ // Invoke the callback with the results
304
+ callback(@[dataDict ?: [NSNull null],
305
+ urlString ?: [NSNull null],
306
+ responseDict ?: [NSNull null],
307
+ errorDict ?: [NSNull null]]);
308
+ }];
309
+ }
310
+
311
+ - (void)handleRegularOpen:(NSString *)authorizationStatus {
312
+ UNAuthorizationStatus authStatus = [self authorizationStatusFromString:authorizationStatus];
313
+ [_sdk handleRegularOpen:authStatus];
314
+ }
315
+
316
+ - (void)handlePushOpened:(NSDictionary *)userInfo
317
+ applicationState:(NSString *)applicationState
318
+ authorizationStatus:(NSString *)authorizationStatus {
319
+ [_sdk handlePushOpened:userInfo applicationState:applicationState authorizationStatus:authorizationStatus];
320
+ }
321
+
322
+ - (void)handleForegroundNotification:(NSDictionary *)userInfo {
323
+ [_sdk handleForegroundNotification:userInfo];
25
324
  }
26
325
 
27
- RCT_EXPORT_METHOD(triggerCreative) {
28
- [self triggerCreative:nil];
326
+ - (void)handleForegroundPush:(NSDictionary *)userInfo
327
+ authorizationStatus:(NSString *)authorizationStatus {
328
+ [_sdk handleForegroundPushFromRN:userInfo authorizationStatus:authorizationStatus];
29
329
  }
30
330
 
31
- RCT_EXPORT_METHOD(triggerCreative:(NSString *)creativeId) {
331
+ - (void)handlePushOpen:(NSDictionary *)userInfo
332
+ authorizationStatus:(NSString *)authorizationStatus {
333
+ [_sdk handlePushOpenFromRN:userInfo authorizationStatus:authorizationStatus];
334
+ }
335
+ #endif
336
+
337
+ - (void)triggerCreative:(NSString *)creativeId {
32
338
  dispatch_async(dispatch_get_main_queue(), ^{
33
339
  UIWindow *window = [[UIApplication sharedApplication] keyWindow];
34
340
  UIView *topView = window.rootViewController.view;
35
- [self->_sdk trigger:topView creativeId:creativeId];
341
+ if (creativeId == nil) {
342
+ [self->_sdk trigger:topView];
343
+ } else {
344
+ [self->_sdk trigger:topView creativeId:creativeId];
345
+ }
36
346
  });
37
347
  }
38
348
 
39
- RCT_EXPORT_METHOD(destroyCreative) {
349
+ - (void)destroyCreative {
40
350
  dispatch_async(dispatch_get_main_queue(), ^{
41
351
  // [self->_sdk closeCreative]
42
352
  });
43
353
  }
44
354
 
45
- RCT_EXPORT_METHOD(updateDomain:(NSString *)domain) {
355
+ - (void)updateDomain:(NSString *)domain {
46
356
  [_sdk updateDomain:domain];
47
357
  }
48
358
 
49
- RCT_EXPORT_METHOD(identify:(NSDictionary*)identifiers) {
50
- // The dictionary already has the correct keys from the React code, so no translating necessary
51
- [_sdk identify:identifiers];
52
- }
53
-
54
- RCT_EXPORT_METHOD(clearUser) {
359
+ - (void)clearUser {
55
360
  [_sdk clearUser];
56
361
  }
57
362
 
58
- RCT_EXPORT_METHOD(recordAddToCartEvent:(NSDictionary*)attrs) {
59
- [_sdk recordAddToCartEvent:attrs];
363
+ - (void)invokeAttentiveDebugHelper {
364
+ [_sdk invokeAttentiveDebugHelper];
60
365
  }
61
366
 
62
- RCT_EXPORT_METHOD(recordProductViewEvent:(NSDictionary*)attrs) {
63
- [_sdk recordProductViewEvent:attrs];
367
+ - (void)exportDebugLogs:(RCTPromiseResolveBlock)resolve
368
+ reject:(RCTPromiseRejectBlock)reject {
369
+ NSString *exportContent = [_sdk exportDebugLogs];
370
+ resolve(exportContent);
64
371
  }
65
372
 
66
- RCT_EXPORT_METHOD(recordPurchaseEvent:(NSDictionary*)attrs) {
67
- [_sdk recordPurchaseEvent:attrs];
68
- }
69
-
70
- RCT_EXPORT_METHOD(recordCustomEvent:(NSDictionary*)attrs) {
71
- [_sdk recordCustomEvent:attrs];
72
- }
73
-
74
- // Don't compile this code when we build for the old architecture.
75
- //#ifdef RCT_NEW_ARCH_ENABLED
76
- //- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
77
- // (const facebook::react::ObjCTurboModule::InitParams &)params
78
- //{
79
- // return std::make_shared<facebook::react::NativeAttentiveReactNativeSdkSpecJSI>(params);
80
- //}
81
- //#endif
82
-
83
373
  @end
84
374
 
@@ -193,7 +193,7 @@
193
193
  GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
194
194
  GCC_WARN_UNUSED_FUNCTION = YES;
195
195
  GCC_WARN_UNUSED_VARIABLE = YES;
196
- IPHONEOS_DEPLOYMENT_TARGET = 8.0;
196
+ IPHONEOS_DEPLOYMENT_TARGET = 14.0;
197
197
  MTL_ENABLE_DEBUG_INFO = YES;
198
198
  ONLY_ACTIVE_ARCH = YES;
199
199
  OTHER_LDFLAGS = (
@@ -247,7 +247,7 @@
247
247
  GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
248
248
  GCC_WARN_UNUSED_FUNCTION = YES;
249
249
  GCC_WARN_UNUSED_VARIABLE = YES;
250
- IPHONEOS_DEPLOYMENT_TARGET = 8.0;
250
+ IPHONEOS_DEPLOYMENT_TARGET = 14.0;
251
251
  MTL_ENABLE_DEBUG_INFO = NO;
252
252
  OTHER_LDFLAGS = (
253
253
  "$(inherited)",