@attentive-mobile/attentive-react-native-sdk 1.0.5 → 2.0.0-beta.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.
Files changed (37) hide show
  1. package/README.md +126 -0
  2. package/android/build.gradle +1 -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 +22 -6
  6. package/attentive-react-native-sdk.podspec +3 -3
  7. package/ios/AttentiveReactNativeSdk.h +1 -1
  8. package/ios/AttentiveReactNativeSdk.mm +317 -37
  9. package/ios/Bridging/ATTNNativeSDK.swift +506 -58
  10. package/ios/Bridging/AttentiveReactNativeSdk-Bridging-Header.h +3 -0
  11. package/ios/Bridging/AttentiveSDKManager.swift +83 -0
  12. package/ios/Podfile +3 -16
  13. package/lib/commonjs/NativeAttentiveReactNativeSdk.js +14 -0
  14. package/lib/commonjs/NativeAttentiveReactNativeSdk.js.map +1 -0
  15. package/lib/commonjs/eventTypes.js.map +1 -1
  16. package/lib/commonjs/index.js +362 -52
  17. package/lib/commonjs/index.js.map +1 -1
  18. package/lib/module/NativeAttentiveReactNativeSdk.js +7 -0
  19. package/lib/module/NativeAttentiveReactNativeSdk.js.map +1 -0
  20. package/lib/module/eventTypes.js.map +1 -1
  21. package/lib/module/index.js +345 -50
  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 -41
  28. package/lib/typescript/index.d.ts.map +1 -1
  29. package/package.json +21 -7
  30. package/src/NativeAttentiveReactNativeSdk.ts +152 -0
  31. package/src/eventTypes.tsx +57 -20
  32. package/src/index.tsx +472 -96
  33. package/android/src/main/java/com/attentivereactnativesdk/AttentiveReactNativeSdkModule.java +0 -310
  34. package/android/src/main/java/com/attentivereactnativesdk/AttentiveReactNativeSdkPackage.java +0 -28
  35. package/ios/AttentiveReactNativeSdk.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -7
  36. package/ios/AttentiveReactNativeSdk.xcodeproj/project.xcworkspace/xcuserdata/zheref.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  37. package/ios/AttentiveReactNativeSdk.xcodeproj/xcuserdata/zheref.xcuserdatad/xcschemes/xcschememanagement.plist +0 -14
@@ -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,75 +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"] enableDebugger:configuration[@"enableDebugger"]];
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;
25
37
  }
26
38
 
27
- RCT_EXPORT_METHOD(triggerCreative) {
28
- [self triggerCreative:nil];
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];
29
54
  }
30
55
 
31
- RCT_EXPORT_METHOD(triggerCreative:(NSString *)creativeId) {
32
- dispatch_async(dispatch_get_main_queue(), ^{
33
- UIWindow *window = [[UIApplication sharedApplication] keyWindow];
34
- UIView *topView = window.rootViewController.view;
35
- [self->_sdk trigger:topView creativeId:creativeId];
36
- });
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];
37
62
  }
38
63
 
39
- RCT_EXPORT_METHOD(destroyCreative) {
40
- dispatch_async(dispatch_get_main_queue(), ^{
41
- // [self->_sdk closeCreative]
42
- });
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];
43
70
  }
44
71
 
45
- RCT_EXPORT_METHOD(updateDomain:(NSString *)domain) {
46
- [_sdk updateDomain:domain];
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];
47
82
  }
48
83
 
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];
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];
52
90
  }
53
91
 
54
- RCT_EXPORT_METHOD(clearUser) {
55
- [_sdk clearUser];
92
+ // Push Notification Methods (New Architecture)
93
+ - (void)registerForPushNotifications {
94
+ [_sdk registerForPushNotifications];
56
95
  }
57
96
 
58
- RCT_EXPORT_METHOD(recordAddToCartEvent:(NSDictionary*)attrs) {
59
- [_sdk recordAddToCartEvent:attrs];
97
+ - (void)registerDeviceToken:(NSString *)token
98
+ authorizationStatus:(NSString *)authorizationStatus {
99
+ [_sdk registerDeviceToken:token authorizationStatus:authorizationStatus];
60
100
  }
61
101
 
62
- RCT_EXPORT_METHOD(recordProductViewEvent:(NSDictionary*)attrs) {
63
- [_sdk recordProductViewEvent:attrs];
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
+ }];
64
157
  }
65
158
 
66
- RCT_EXPORT_METHOD(recordPurchaseEvent:(NSDictionary*)attrs) {
67
- [_sdk recordPurchaseEvent:attrs];
159
+ - (void)handleRegularOpen:(NSString *)authorizationStatus {
160
+ UNAuthorizationStatus authStatus = [self authorizationStatusFromString:authorizationStatus];
161
+ [_sdk handleRegularOpen:authStatus];
68
162
  }
69
163
 
70
- RCT_EXPORT_METHOD(recordCustomEvent:(NSDictionary*)attrs) {
71
- [_sdk recordCustomEvent:attrs];
164
+ - (void)handlePushOpened:(NSDictionary *)userInfo
165
+ applicationState:(NSString *)applicationState
166
+ authorizationStatus:(NSString *)authorizationStatus {
167
+ [_sdk handlePushOpened:userInfo applicationState:applicationState authorizationStatus:authorizationStatus];
72
168
  }
73
169
 
74
- RCT_EXPORT_METHOD(invokeAttentiveDebugHelper) {
75
- [_sdk invokeAttentiveDebugHelper];
170
+ - (void)handleForegroundNotification:(NSDictionary *)userInfo {
171
+ [_sdk handleForegroundNotification:userInfo];
76
172
  }
77
173
 
78
- RCT_EXPORT_METHOD(exportDebugLogs:(RCTPromiseResolveBlock)resolve
79
- reject:(RCTPromiseRejectBlock)reject) {
80
- NSString *exportContent = [_sdk exportDebugLogs];
81
- resolve(exportContent);
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;
82
204
  }
83
205
 
84
- // Don't compile this code when we build for the old architecture.
85
- #ifdef RCT_NEW_ARCH_ENABLED
86
206
  - (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
87
207
  (const facebook::react::ObjCTurboModule::InitParams &)params
88
208
  {
89
209
  return std::make_shared<facebook::react::NativeAttentiveReactNativeSdkSpecJSI>(params);
90
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];
324
+ }
325
+
326
+ - (void)handleForegroundPush:(NSDictionary *)userInfo
327
+ authorizationStatus:(NSString *)authorizationStatus {
328
+ [_sdk handleForegroundPushFromRN:userInfo authorizationStatus:authorizationStatus];
329
+ }
330
+
331
+ - (void)handlePushOpen:(NSDictionary *)userInfo
332
+ authorizationStatus:(NSString *)authorizationStatus {
333
+ [_sdk handlePushOpenFromRN:userInfo authorizationStatus:authorizationStatus];
334
+ }
91
335
  #endif
92
336
 
337
+ - (void)triggerCreative:(NSString *)creativeId {
338
+ dispatch_async(dispatch_get_main_queue(), ^{
339
+ UIWindow *window = [[UIApplication sharedApplication] keyWindow];
340
+ UIView *topView = window.rootViewController.view;
341
+ if (creativeId == nil) {
342
+ [self->_sdk trigger:topView];
343
+ } else {
344
+ [self->_sdk trigger:topView creativeId:creativeId];
345
+ }
346
+ });
347
+ }
348
+
349
+ - (void)destroyCreative {
350
+ dispatch_async(dispatch_get_main_queue(), ^{
351
+ // [self->_sdk closeCreative]
352
+ });
353
+ }
354
+
355
+ - (void)updateDomain:(NSString *)domain {
356
+ [_sdk updateDomain:domain];
357
+ }
358
+
359
+ - (void)clearUser {
360
+ [_sdk clearUser];
361
+ }
362
+
363
+ - (void)invokeAttentiveDebugHelper {
364
+ [_sdk invokeAttentiveDebugHelper];
365
+ }
366
+
367
+ - (void)exportDebugLogs:(RCTPromiseResolveBlock)resolve
368
+ reject:(RCTPromiseRejectBlock)reject {
369
+ NSString *exportContent = [_sdk exportDebugLogs];
370
+ resolve(exportContent);
371
+ }
372
+
93
373
  @end
94
374