reactnative-plugin-appice 1.7.42 → 1.7.44

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/index.js CHANGED
@@ -25,11 +25,12 @@ export const ACTION_URL = AppIceReactPlugin.ACTION_URL;
25
25
  export const ACTION_TYPE = AppIceReactPlugin.ACTION_TYPE;
26
26
  export const CUSTOMDATA = AppIceReactPlugin.CUSTOMDATA;
27
27
 
28
+
28
29
  const CampaignType = {
29
30
  NATIVE: 'NATIVE',
30
31
  INAPP: 'INAPP',
31
32
  PUSH: 'PUSH',
32
- };
33
+ };
33
34
 
34
35
 
35
36
  var AppICEReact = {
@@ -40,6 +41,7 @@ var AppICEReact = {
40
41
  // PUSH
41
42
  //========================
42
43
  AppICEPushNotificationClicked: AppIceReactPlugin.AppICEPushNotificationClicked,
44
+ AppICEPushNotificationActionButtonClicked: AppIceReactPlugin.AppICEPushNotificationActionButtonClicked,
43
45
 
44
46
  //==========================
45
47
  // IN-APP
@@ -101,7 +103,14 @@ var AppICEReact = {
101
103
  AVERAGE_TRANSACTION_AMOUNT: AppIceReactPlugin.AVERAGE_TRANSACTION_AMOUNT,
102
104
  FREQUENCY_OF_TRANSACTION: AppIceReactPlugin.FREQUENCY_OF_TRANSACTION,
103
105
  TYPE_OF_TRANSACTION: AppIceReactPlugin.TYPE_OF_TRANSACTION,
104
-
106
+
107
+ //====================
108
+ // ACTION BUTTON TYPES
109
+ //====================
110
+ ACTION_TYPE_CUSTOM: AppIceReactPlugin.ACTION_TYPE_CUSTOM,
111
+ ACTION_TYPE_DEEPLINK: AppIceReactPlugin.ACTION_TYPE_DEEPLINK,
112
+ ACTION_TYPE_REPLY: AppIceReactPlugin.ACTION_TYPE_REPLY,
113
+ ACTION_TYPE_REMIND_ME_LATER: AppIceReactPlugin.ACTION_TYPE_REMIND_ME_LATER,
105
114
 
106
115
  //======================
107
116
  // LISTENER
@@ -168,10 +177,10 @@ var AppICEReact = {
168
177
  AppState.addEventListener('change', (nextAppState) => {
169
178
  if (nextAppState === 'active') {
170
179
  AppIceReactPlugin.isDeviceReady(true);
171
- // AppIceReactPlugin.registerLifeCycle();
180
+ //AppIceReactPlugin.resumeInApp();
172
181
  } else if (nextAppState === 'background') {
173
- AppIceReactPlugin.isDeviceReady(false);
174
- // AppIceReactPlugin.registerLifeCycle();
182
+ AppIceReactPlugin.isDeviceReady(false);
183
+ //AppIceReactPlugin.discardInApp();
175
184
  }
176
185
  });
177
186
  },
@@ -199,7 +208,7 @@ var AppICEReact = {
199
208
  if (flush == undefined || flush == null) {
200
209
  await AppIceReactPlugin.tagEvent(eventName, props);
201
210
  } else {
202
- const lastEventData = await getEventData(LAST_EVENT_KEY)
211
+ const lastEventData = await getEventData(LAST_EVENT_KEY)
203
212
 
204
213
 
205
214
  if (lastEventData != undefined && lastEventData !== eventName) {
@@ -450,9 +459,9 @@ var AppICEReact = {
450
459
  callWithCallback('getUserForIds', [userIds], callback);
451
460
  },
452
461
 
453
- /*===================
454
- GetCampaign
455
- =====================*/
462
+ /*===================
463
+ GetCampaign
464
+ =====================*/
456
465
 
457
466
  /**
458
467
  * getCampaigns
@@ -462,69 +471,69 @@ var AppICEReact = {
462
471
 
463
472
  getCampaigns: function (campType, callback) {
464
473
  AppIceReactPlugin.getCampaigns(campType, (campaignArray) => {
465
- const campaigns = campaignArray.map(
466
- (campaignData) =>
467
- new Campaign(
468
- campaignData[CAMP_ID],
469
- campaignData[ACTION_URL],
470
- campaignData[ACTION_TYPE],
471
- campaignData[CUSTOMDATA]
472
- )
473
- );
474
- callback(campaigns);
474
+ const campaigns = campaignArray.map(
475
+ (campaignData) =>
476
+ new Campaign(
477
+ campaignData[CAMP_ID],
478
+ campaignData[ACTION_URL],
479
+ campaignData[ACTION_TYPE],
480
+ campaignData[CUSTOMDATA]
481
+ )
482
+ );
483
+ callback(campaigns);
475
484
  });
476
- },
477
-
478
-
485
+ },
486
+
487
+
479
488
 
480
489
  /**
481
490
  * getCampaignById
482
491
  * @param campId - string
483
492
  * @callback -Return a single Campaign object
484
493
  */
485
-
486
- getCampaignById: function (campId, callback) {
487
- AppIceReactPlugin.getCampaignById(campId, (campaignData) => {
488
- const getCampaign = new Campaign(
489
- campaignData[CAMP_ID],
490
- campaignData[ACTION_URL],
491
- campaignData[ACTION_TYPE],
492
- campaignData[CUSTOMDATA]
493
- );
494
- callback(getCampaign);
495
- });
496
- },
497
-
498
- //===============================================
499
- // Topic Push
494
+
495
+ getCampaignById: function (campId, callback) {
496
+ AppIceReactPlugin.getCampaignById(campId, (campaignData) => {
497
+ const getCampaign = new Campaign(
498
+ campaignData[CAMP_ID],
499
+ campaignData[ACTION_URL],
500
+ campaignData[ACTION_TYPE],
501
+ campaignData[CUSTOMDATA]
502
+ );
503
+ callback(getCampaign);
504
+ });
505
+ },
506
+
507
+ //===============================================
508
+ // Topic Push
500
509
  //===============================================
501
510
 
502
511
  isDeviceRegistered: function (callback) {
503
- callWithCallback('isDeviceRegistered', null, callback);
504
- },
512
+ callWithCallback('isDeviceRegistered', null, callback);
513
+ },
505
514
 
506
515
  setAppLanguage: function (language) {
507
-
508
- AppIceReactPlugin.setAppLanguage(language);
516
+
517
+ AppIceReactPlugin.setAppLanguage(language);
509
518
 
510
519
  },
511
520
 
512
521
  getAppLanguage: function (callback) {
513
- callWithCallback('getAppLanguage', null, callback);
514
- },
522
+ callWithCallback('getAppLanguage', null, callback);
523
+ },
515
524
 
516
525
  setDeviceLanguage: function (language) {
517
526
 
518
- AppIceReactPlugin.setDeviceLanguage(language);
519
-
527
+ AppIceReactPlugin.setDeviceLanguage(language);
528
+
520
529
  },
521
530
 
522
- getDeviceLanguage: function (callback) {
523
- callWithCallback('getDeviceLanguage', null, callback);
524
- },
531
+ getDeviceLanguage: function (callback) {
532
+ callWithCallback('getDeviceLanguage', null, callback);
533
+ },
525
534
 
526
- subscribeAppLanguage: function (language) {
527
- if (Platform.OS === 'android') {
535
+ subscribeAppLanguage: function (language) {
536
+ if (Platform.OS === 'android') {
528
537
  AppIceReactPlugin.subscribeAppLanguage(language);
529
538
  }
530
539
  },
@@ -535,24 +544,44 @@ var AppICEReact = {
535
544
  }
536
545
  },
537
546
 
538
- // -------- Custom Topics --------
539
- setCustomTopic: function (topic) {
540
- AppIceReactPlugin.setCustomTopic(topic);
541
- },
547
+ // -------- Custom Topics --------
548
+ setCustomTopic: function (topic) {
549
+ AppIceReactPlugin.setCustomTopic(topic);
550
+ },
551
+
552
+ removeCustomTopic: function (topic) {
553
+ AppIceReactPlugin.removeCustomTopic(topic);
554
+ },
555
+
556
+ scheduleTransactionalCampaign: function (payloadJson) {
557
+ AppIceReactPlugin.scheduleTransactionalCampaign(payloadJson);
542
558
 
543
- removeCustomTopic: function (topic) {
544
- AppIceReactPlugin.removeCustomTopic(topic);
545
- },
559
+ },
560
+
561
+ /*===================
562
+ INAPP
563
+ =====================*/
546
564
 
547
- scheduleTransactionalCampaign: function (payloadJson) {
548
- AppIceReactPlugin.scheduleTransactionalCampaign(payloadJson);
565
+ resumeInApp: function () {
566
+ AppIceReactPlugin.resumeInApp();
567
+ },
549
568
 
550
- },
569
+ suspendInApp: function () {
570
+ AppIceReactPlugin.suspendInApp();
571
+ },
551
572
 
552
- //campaign enum
553
- CampaignType,
573
+ discardInApp: function () {
574
+ AppIceReactPlugin.discardInApp();
575
+ },
576
+
577
+ dismissInApp: function (campType, callback) {
578
+ AppIceReactPlugin.dismissInApp();
579
+ },
580
+
581
+ //campaign enum
582
+ CampaignType,
554
583
  };
555
-
584
+
556
585
 
557
586
 
558
587
  //================================
@@ -585,8 +614,8 @@ const handleStoredEvents = async (eventName, props) => {
585
614
  events.push({ eventName, props });
586
615
 
587
616
  // Save the updated events list
588
- // appStorage.set(EVENT_KEY + eventName, JSON.stringify(events));
589
- // appStorage.set(LAST_EVENT_KEY, eventName);
617
+ // appStorage.set(EVENT_KEY + eventName, JSON.stringify(events));
618
+ // appStorage.set(LAST_EVENT_KEY, eventName);
590
619
 
591
620
  // async Storage
592
621
  await AsyncStorage.setItem(EVENT_KEY + eventName, JSON.stringify(events))
@@ -36,7 +36,7 @@ RCT_EXPORT_MODULE();
36
36
 
37
37
  - (NSArray<NSString *> *)supportedEvents
38
38
  {
39
- return @[kAppICEPushNotificationClicked, kAppICEInAppClicked];
39
+ return @[kAppICEPushNotificationClicked, kAppICEInAppClicked, kAppICEPushNotificationActionButtonClicked];
40
40
  }
41
41
 
42
42
 
@@ -51,7 +51,11 @@ RCT_EXPORT_MODULE();
51
51
  name:kAppICEInAppClicked
52
52
  object:nil];
53
53
 
54
-
54
+ // Observer for the handlePush event
55
+ [[NSNotificationCenter defaultCenter] addObserver:self
56
+ selector:@selector(didReceiveHandlePush:)
57
+ name:kAppICEPushNotificationActionButtonClicked
58
+ object:nil];
55
59
 
56
60
  }
57
61
 
@@ -82,5 +86,10 @@ RCT_EXPORT_MODULE();
82
86
  [self sendEventWithName:kAppICEInAppClicked body:eventDict];
83
87
  }
84
88
 
89
+ - (void)didReceiveHandlePush:(NSNotification *)event {
90
+ // Forward the handlePush event (which contains campaign data) to JS
91
+ [self sendEventWithName:kAppICEPushNotificationActionButtonClicked body:event.userInfo];
92
+ }
93
+
85
94
  @end
86
95
 
@@ -2,6 +2,7 @@
2
2
  #import <UserNotifications/UserNotifications.h>
3
3
  static NSString *const kAppICEPushNotificationClicked = @"AppICEPushNotificationClicked";
4
4
  static NSString *const kAppICEInAppClicked = @"AppICEInAppClicked";
5
+ static NSString *const kAppICEPushNotificationActionButtonClicked = @"AppICEPushNotificationActionButtonClicked";
5
6
 
6
7
  static NSString *const kn = @"APPICE_USER_NAME";
7
8
  static NSString *const kem = @"APPICE_USER_EMAIL";
@@ -35,6 +36,11 @@ static NSString *const ACTION_URL = @"ACTION_URL";
35
36
  static NSString *const ACTION_TYPE = @"ACTION_TYPE";
36
37
  static NSString *const CUSTOMDATA = @"CUSTOMDATA";
37
38
 
39
+ static NSString *const ACTION_TYPE_CUSTOM = @"ACTION_TYPE_CUSTOM";
40
+ static NSString *const ACTION_TYPE_DEEPLINK = @"ACTION_TYPE_DEEPLINK";
41
+ static NSString *const ACTION_TYPE_REPLY = @"ACTION_TYPE_REPLY";
42
+ static NSString *const ACTION_TYPE_REMIND_ME_LATER = @"ACTION_TYPE_REMIND_ME_LATER";
43
+
38
44
  // Custom data
39
45
  static NSString *const DEMOGRAPHIC_INFO = @"DEMOGRAPHIC_INFO";
40
46
  static NSString *TOP_N_PRODUCTS_VIEWED;
@@ -59,7 +65,7 @@ static NSString *TYPE_OF_TRANSACTION;
59
65
 
60
66
  @interface AppIceReactPlugin : NSObject <RCTBridgeModule,UNUserNotificationCenterDelegate>
61
67
  +(void)didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken;
62
- + (void)pushNotificationClicked:(NSDictionary *)userInfo;
68
+ + (void)pushNotificationClicked:(id)userInfo;
63
69
  + (void)pushNotificationReceived:(NSDictionary *)userInfo;
64
70
  @end
65
71
 
@@ -7,10 +7,13 @@
7
7
  #import <UserNotifications/UserNotifications.h>
8
8
  #import "Campaign.h"
9
9
  #import "TransactionalCampaign.h"
10
+ #import "AppICEConstantsPrivate.h"
10
11
  @implementation AppIceReactPlugin
11
12
 
12
13
  static BOOL isAppInitialized = NO;
13
14
  static NSDictionary *pendingDeeplink = nil;
15
+ static UNNotificationResponse *pendingDeeplinkResponse = nil;
16
+ static NSString *pendingSelectedAction = nil;
14
17
 
15
18
  RCT_EXPORT_MODULE()
16
19
  + (BOOL)requiresMainQueueSetup {
@@ -36,30 +39,31 @@ RCT_EXPORT_MODULE()
36
39
  return @{
37
40
  kAppICEPushNotificationClicked : kAppICEPushNotificationClicked,
38
41
  kAppICEInAppClicked : kAppICEInAppClicked,
39
- kn : @"n",
40
- kem : @"e",
41
- kph : @"p",
42
- ka : @"a",
43
- kg : @"g",
44
- ked : @"edt",
45
- ket : @"emt",
46
- km : @"m",
47
- kis_emp : @"em",
48
- kdob: @"d",
42
+ kAppICEPushNotificationActionButtonClicked : kAppICEPushNotificationActionButtonClicked,
43
+ kn : NAME,
44
+ kem : EMAIL,
45
+ kph : PHONE,
46
+ ka : AGE,
47
+ kg : GENDER,
48
+ ked : EDUCATIONTYPE,
49
+ ket : EMPLOYMENTTYPE,
50
+ km : ISMARRIED,
51
+ kis_emp : ISEMPLOYED,
52
+ kdob: D,
49
53
 
50
- INBOX_MESSAGE : @"message",
51
- INBOX_TITLE : @"title",
52
- INBOX_MESSAGE_STATUS : @"messageStatus",
53
- INBOX_CAMPAIGN_TYPE : @"campType",
54
- INBOX_MESSAGE_LANGUAGE : @"messageLanguage",
55
- INBOX_MESSAGE_ID : @"id",
56
- INBOX_CAMPAIGN_ID : @"campId",
57
- INBOX_MESSAGE_CATEGORY : @"category",
58
- INBOX_MESSAGE_ICON : @"icon",
59
- INBOX_CUSTOM_DATA : @"cdata",
60
- INBOX_MESSAGE_EXPANDED_IMAGE :@"eni",
54
+ INBOX_MESSAGE : MESSAGE,
55
+ INBOX_TITLE : TITLE,
56
+ INBOX_MESSAGE_STATUS : MESSAGESTATUS,
57
+ INBOX_CAMPAIGN_TYPE : CAMPTYPE,
58
+ INBOX_MESSAGE_LANGUAGE : MESSAGELANGUAGE,
59
+ INBOX_MESSAGE_ID : CAMPAIGN_ID,
60
+ INBOX_CAMPAIGN_ID : CAMPAIGNID,
61
+ INBOX_MESSAGE_CATEGORY : CATEGORY,
62
+ INBOX_MESSAGE_ICON : ICON,
63
+ INBOX_CUSTOM_DATA : CDATA,
64
+ INBOX_MESSAGE_EXPANDED_IMAGE :ENI,
61
65
 
62
- DEMOGRAPHIC_INFO :@"customProperties",
66
+ DEMOGRAPHIC_INFO :DEMOGRAPHIC_INFO,
63
67
  @"TOP_N_PRODUCTS_VIEWED" : TOP_N_PRODUCTS_VIEWED,
64
68
  @"N_COMPLAINTS_RAISED" : N_COMPLAINTS_RAISED,
65
69
  @"PREF_LOGIN_DEVICE" : PREF_LOGIN_DEVICE,
@@ -77,10 +81,15 @@ RCT_EXPORT_MODULE()
77
81
  @"AVERAGE_TRANSACTION_AMOUNT" : AVERAGE_TRANSACTION_AMOUNT,
78
82
  @"FREQUENCY_OF_TRANSACTION": FREQUENCY_OF_TRANSACTION,
79
83
  @"TYPE_OF_TRANSACTION" : TYPE_OF_TRANSACTION,
80
- CAMP_ID : @"campId",
81
- ACTION_URL : @"actionUrl",
82
- ACTION_TYPE: @"actionType",
83
- CUSTOMDATA : @"customData"
84
+ CAMP_ID : CAMPAIGNID,
85
+ ACTION_URL : ACTIONURL,
86
+ ACTION_TYPE: ACTIONTYPE,
87
+ CUSTOMDATA : CUSTOMDATA,
88
+
89
+ ACTION_TYPE_CUSTOM: CUS,
90
+ ACTION_TYPE_DEEPLINK: DL,
91
+ ACTION_TYPE_REPLY: RLY,
92
+ ACTION_TYPE_REMIND_ME_LATER: RML
84
93
  };
85
94
  }
86
95
  - (dispatch_queue_t)methodQueue {
@@ -248,26 +257,13 @@ RCT_EXPORT_METHOD(setUser:(NSDictionary*)userProfile)
248
257
  * when Called in killed state isAppInitialized will be false and deeplink is stored and will be handled after the App is initialized.
249
258
  ===========================*/
250
259
 
251
- + (void)pushNotificationClicked:(NSDictionary *)userInfo {
252
- @try {
253
-
254
- if (!isAppInitialized) {
255
- RCTLog(@"Deeplink Push : not isAppInitialized" );
256
- // App is not initialized, store the deeplink for later processing
257
- [self storePendingDeeplink:userInfo];
258
- } else {
259
- // App is initialized, handle deeplinks in the click handler
260
- RCTLog(@"Deeplink Push : pushNotificationClicked deeplink handled" );
261
- [self storePendingDeeplink:userInfo];
262
- [self processPendingDeeplink];
260
+ + (void)pushNotificationClicked:(id)response {
261
+ @try {
262
+ [self storePendingDeeplink:response];
263
+ [self processPendingDeeplink]; // processPendingDeeplink itself enforces init rules
264
+ } @catch (NSException *exception) {
265
+ RCTLog(@"Deeplink Push : pushNotificationClicked exception %@", exception);
263
266
  }
264
-
265
- NSDictionary *event = @{ kAppICEPushNotificationClicked : userInfo};
266
- [[NSNotificationCenter defaultCenter] postNotificationName:kAppICEPushNotificationClicked object:nil userInfo:event];
267
- } @catch (NSException *exception) {
268
- RCTLog(@"Deeplink Push : pushNotificationClicked exception %@",exception);
269
- }
270
-
271
267
  }
272
268
 
273
269
  RCT_EXPORT_METHOD(inAppClicked:(NSDictionary*)userInfo)
@@ -542,34 +538,129 @@ RCT_EXPORT_METHOD(getMediaThumbnail:(NSDictionary *)inboxMessageDict mediaData:(
542
538
  * @param userInfo - NSDictionary
543
539
  * Store the pending deeplink info in the static variable for later processing
544
540
  -----------------------------------------------------------------------------*/
545
- + (void)storePendingDeeplink:(NSDictionary *)userInfo {
541
+ + (void)storePendingDeeplink:(id)response {
546
542
  @try {
547
- // Store the pending deeplink info in the static variable for later processing
548
- pendingDeeplink = userInfo;
549
- RCTLog(@"Deeplink Push : storePendingDeeplink called" );
543
+ // Store the pending deeplink info in the static variable for later processing
544
+ // Old flow: NSDictionary userInfo
545
+ if ([response isKindOfClass:[NSDictionary class]]) {
546
+ // Old flow
547
+ pendingDeeplink = (NSDictionary *)response;
548
+ pendingDeeplinkResponse = nil;
549
+ pendingSelectedAction = nil;
550
+ RCTLog(@"Deeplink Push : storePendingDeeplink old flow pendingDeeplink: %@", pendingDeeplink);
551
+ return;
552
+ }
553
+ if ([response isKindOfClass:[UNNotificationResponse class]]) {
554
+ // New flow
555
+ pendingDeeplinkResponse = (UNNotificationResponse *)response;
556
+ pendingDeeplink = pendingDeeplinkResponse.notification.request.content.userInfo;
557
+ pendingSelectedAction = [self resolvedActFromResponse:pendingDeeplinkResponse];
558
+ RCTLog(@"Deeplink Push : storePendingDeeplink selectedAct: %@ actionIdentifier: %@",
559
+ pendingSelectedAction, pendingDeeplinkResponse.actionIdentifier);
560
+ return;
561
+ }
562
+ pendingDeeplink = nil;
563
+ pendingDeeplinkResponse = nil;
564
+ pendingSelectedAction = nil;
550
565
  } @catch (NSException *exception) {
551
566
  RCTLog(@"Deeplink Push : storePendingDeeplink exception %@",exception);
552
567
  }
553
568
  }
554
569
 
570
+ + (NSString *)resolvedActFromResponse:(UNNotificationResponse *)response {
571
+ // Maps iOS actionIdentifier -> payload action "act" value for routing.
572
+ if (![response isKindOfClass:[UNNotificationResponse class]]) return @"";
573
+
574
+ NSString *identifier = response.actionIdentifier ?: @"";
575
+ if ([identifier isEqualToString:UNNotificationDefaultActionIdentifier]) {
576
+ return DEFAULT;
577
+ }
578
+ NSDictionary *userInfo = response.notification.request.content.userInfo;
579
+ NSDictionary *message = userInfo[DATA][MESSAGE];
580
+ NSArray *actions = [message[ACTIONS] isKindOfClass:[NSArray class]] ? message[ACTIONS] : @[];
581
+ for (id a in actions) {
582
+ if (![a isKindOfClass:[NSDictionary class]]) continue;
583
+ NSDictionary *action = (NSDictionary *)a;
584
+ NSString *abt = [action[ABT] isKindOfClass:[NSString class]] ? action[ABT] : @"";
585
+ NSString *act = [action[ACT] isKindOfClass:[NSString class]] ? action[ACT] : @"";
586
+ if ([abt caseInsensitiveCompare:identifier] == NSOrderedSame) {
587
+ return act.lowercaseString;
588
+ }
589
+ }
590
+ // fallback: if identifier itself equals act
591
+ NSString *idLower = identifier.lowercaseString;
592
+ for (id a in actions) {
593
+ if (![a isKindOfClass:[NSDictionary class]]) continue;
594
+ NSString *act = [a[ACT] isKindOfClass:[NSString class]] ? [a[ACT] lowercaseString] : @"";
595
+ if ([act isEqualToString:idLower]) return act;
596
+ }
597
+ return @""; // unknown action
598
+ }
599
+
555
600
  /*----------------------------------------------------------------------------
556
601
  processPendingDeeplink
557
602
  * Process the pending deeplink if it exists and the app is initialized
603
+ * Flow A: Legacy wrapper input (NSDictionary userInfo).
604
+ Behavior is unchanged: process only after React/SDK initialization.
605
+ * Flow B: New wrapper input (UNNotificationResponse).
606
+ Routing is based on resolved payload action type.
607
+ 1. Normal push click (default action) -> preserve old behavior.
608
+ 2. RML/RLY/DIS action buttons -> allow kill/background processing path.
609
+ 3. Other action buttons -> process only after initialization.
558
610
  * Clear the pending deeplink after processing
559
611
  -----------------------------------------------------------------------------*/
560
612
  + (void)processPendingDeeplink {
561
613
  @try {
562
-
563
- RCTLog(@"Deeplink Push : processPendingDeeplink called isAppInitialized: %d , pendingDeeplink: %@",isAppInitialized,pendingDeeplink);
564
- if (isAppInitialized && pendingDeeplink) {
565
- RCTLog(@"Deeplink Push : handled in stored data");
566
- [[appICE sharedInstance] handleClickOnPush:pendingDeeplink OpenDeepLink:YES];
567
- pendingDeeplink = nil;
568
- }
614
+ BOOL didProcess = NO;
615
+ //Flow A
616
+ if (pendingDeeplink && !pendingDeeplinkResponse) {
617
+ if (isAppInitialized) {
618
+ [[appICE sharedInstance] handleClickOnPush:pendingDeeplink OpenDeepLink:YES];
619
+ NSDictionary *event = @{ kAppICEPushNotificationClicked : pendingDeeplink };
620
+ [[NSNotificationCenter defaultCenter] postNotificationName:kAppICEPushNotificationClicked
621
+ object:nil
622
+ userInfo:event];
623
+ didProcess = YES;
624
+ }
625
+ }
626
+ // Flow B:
627
+ if (!didProcess && pendingDeeplinkResponse) {
628
+ NSString *act = (pendingSelectedAction ?: @"").lowercaseString;
629
+ // B1) Normal push click (default action) -> preserve old behavior.
630
+ if ([act isEqualToString:DEFAULT]) {
631
+ if (isAppInitialized && pendingDeeplink) {
632
+ [[appICE sharedInstance] handleClickOnPush:pendingDeeplink OpenDeepLink:YES];
633
+ NSDictionary *event = @{ kAppICEPushNotificationClicked : pendingDeeplink };
634
+ [[NSNotificationCenter defaultCenter] postNotificationName:kAppICEPushNotificationClicked
635
+ object:nil
636
+ userInfo:event];
637
+ didProcess = YES;
638
+ }
639
+ }
640
+ // B2) RML/RLY/DIS action buttons -> allow kill/background processing path.
641
+ else if ([act isEqualToString:RML] ||
642
+ [act isEqualToString:RLY] ||
643
+ [act isEqualToString:DIS]) {
644
+ [self handlePush:pendingDeeplinkResponse openDeepLink:YES];
645
+ didProcess = YES;
646
+ }
647
+ // B3) Other action buttons -> process only after initialization.
648
+ else {
649
+ if (isAppInitialized) {
650
+ [self handlePush:pendingDeeplinkResponse openDeepLink:YES];
651
+ didProcess = YES;
652
+ }
653
+ }
654
+ }
655
+ if (didProcess) {
656
+ pendingDeeplink = nil;
657
+ pendingDeeplinkResponse = nil;
658
+ pendingSelectedAction = nil;
659
+ RCTLog(@"Deeplink Push : pending cleared");
660
+ }
569
661
  } @catch (NSException *exception) {
570
662
  RCTLog(@"Deeplink Push : processPendingDeeplink exception %@",exception);
571
663
  } @finally {
572
- pendingDeeplink = nil;
573
664
  RCTLog(@"Deeplink Push : finally processPendingDeeplink pendingDeeplink set as nil");
574
665
  }
575
666
 
@@ -628,7 +719,7 @@ RCT_EXPORT_METHOD(getUserForIds:(NSArray*)userIds callback:(RCTResponseSenderBlo
628
719
  NSDictionary *formattedMessage = [getUserData toDictionary];
629
720
  [formattedGetUser addObject:formattedMessage];
630
721
  }
631
- NSLog(@"[getUserDetails]: Formatted getUser Messages: %@", formattedGetUser);
722
+ RCTLog(@"[getUserDetails]: Formatted getUser Messages: %@", formattedGetUser);
632
723
  [self returnResult:formattedGetUser withCallback:callback andError:nil];
633
724
 
634
725
  }
@@ -647,7 +738,7 @@ RCT_EXPORT_METHOD(getCampaigns:(NSString *)type callback:(RCTResponseSenderBlock
647
738
 
648
739
  for (Campaign *campaign in campaigns) {
649
740
  NSDictionary *formatedCampaign = campaign.toDictionary;
650
- NSLog(@"Campaign: Formatted getCampaigns: %@", formatedCampaign);
741
+ RCTLog(@"Campaign: Formatted getCampaigns: %@", formatedCampaign);
651
742
  [formattedCampaigns addObject:formatedCampaign];
652
743
  }
653
744
  [self returnResult:formattedCampaigns withCallback:callback andError:nil];
@@ -721,7 +812,54 @@ RCT_EXPORT_METHOD(scheduleTransactionalCampaign:(NSString *)payloadJson)
721
812
  [[appICE sharedInstance] scheduleCampaign:tCampaign];
722
813
  }
723
814
  } @catch (NSException *exception) {
724
-
815
+
816
+ }
817
+ }
818
+
819
+ #pragma mark - In-app display state
820
+
821
+ // React Native API to resume in-app rendering after it was paused/suspended.
822
+ RCT_EXPORT_METHOD(resumeInApp)
823
+ {
824
+ [[appICE sharedInstance] resumeInApp];
825
+ }
826
+
827
+ // React Native API to temporarily suspend in-app rendering.
828
+ RCT_EXPORT_METHOD(suspendInApp)
829
+ {
830
+ [[appICE sharedInstance] suspendInApp];
831
+ }
832
+
833
+ // React Native API to discard queued or active in-app state.
834
+ RCT_EXPORT_METHOD(discardInApp)
835
+ {
836
+ [[appICE sharedInstance] discardInApp];
837
+ }
838
+
839
+ // React Native API to dismiss the currently visible in-app.
840
+ RCT_EXPORT_METHOD(dismissInApp)
841
+ {
842
+ [[appICE sharedInstance] dismissInApp];
843
+ }
844
+
845
+ // Handles push click responses from app delegate paths, including kill-state/cold-start handoff.
846
+ // Emits `kAppICEPushNotificationActionButtonClicked` with campaign payload for JS listeners.
847
+ +(void)handlePush:(id)response openDeepLink:(BOOL)openDeepLink {
848
+ @try {
849
+ RCTLog(@"handlePushFromAppDelegate: Entered are");
850
+ [[appICE sharedInstance] pushNotificationClicked:response openDeepLink:openDeepLink];
851
+ Campaign *campaign = [[appICE sharedInstance] handleClickCallback:response];
852
+
853
+ NSDictionary *campaignDict = campaign ? [campaign toDictionary] : @{};
854
+ RCTLog(@"handlePushFromAppDelegate: Campaign data: %@", campaignDict);
855
+
856
+ // Post an event with the campaign data so JS can process it.
857
+ NSDictionary *event = @{ kAppICEPushNotificationActionButtonClicked : campaignDict };
858
+ [[NSNotificationCenter defaultCenter] postNotificationName:kAppICEPushNotificationActionButtonClicked
859
+ object:nil
860
+ userInfo:event];
861
+ } @catch (NSException *exception) {
862
+ RCTLog(@"handlePushFromAppDelegate exception: %@", exception);
725
863
  }
726
864
  }
727
865
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "reactnative-plugin-appice",
3
- "version": "1.7.42",
3
+ "version": "1.7.44",
4
4
  "description": "appICE React Native SDK",
5
5
  "main": "index.js",
6
6
  "files": [
@@ -9,6 +9,7 @@
9
9
  "android",
10
10
  "index.js",
11
11
  "campaign.js",
12
+ "TransactionalCampaign.js",
12
13
  "ios",
13
14
  "reactnative-plugin-appice.podspec"
14
15
  ],