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.
@@ -0,0 +1,60 @@
1
+ // ===============================
2
+ // TransactionalCampaign
3
+ // ===============================
4
+ const Campaign = require('./campaign');
5
+
6
+ class TransactionalCampaign extends Campaign {
7
+ constructor() {
8
+ super();
9
+ this._data.id = null;
10
+ this._data.p = null;
11
+ this._data.name = null;
12
+ this._data.custom = null;
13
+ this._data.delay = 0;
14
+ this._data.users = [];
15
+ this._data.emails = [];
16
+ this._data.msisdns = [];
17
+ this._data.tokens = [];
18
+ this._data.segment = "";
19
+ this._data.payload = [];
20
+ }
21
+ set setCampId(v) {
22
+ this._data.id = v;
23
+ }
24
+ set setPlatform(v) {
25
+ this._data.p = v;
26
+ }
27
+ set setName(v) {
28
+ this._data.name = v;
29
+ }
30
+ set setCustom(v) {
31
+ this._data.custom = v;
32
+ }
33
+ set setDelay(v) {
34
+ this._data.delay = v;
35
+ }
36
+ set setUsers(v) {
37
+ this._data.users = v;
38
+ }
39
+ set setEmails(v) {
40
+ this._data.emails = v;
41
+ }
42
+ set setMsisdns(v) {
43
+ this._data.msisdns = v;
44
+ }
45
+ set setTokens(v) {
46
+ this._data.tokens = v;
47
+ }
48
+ set setSegment(v) {
49
+ this._data.segment = v;
50
+ }
51
+ addPayload(payloadObj) {
52
+ this._data.payload.push(payloadObj.toJSON());
53
+ }
54
+ toRequestPayload() {
55
+ return JSON.stringify(this._data);
56
+ }
57
+ }
58
+
59
+ export default TransactionalCampaign;
60
+ module.exports = TransactionalCampaign;
@@ -97,7 +97,7 @@ dependencies {
97
97
  annotationProcessor "androidx.lifecycle:lifecycle-compiler:2.3.1"
98
98
 
99
99
  //appice
100
- implementation "appice.io.android:sdk:2.6.38"
100
+ implementation "appice.io.android:sdk:2.6.39"
101
101
 
102
102
  //glide
103
103
  implementation "com.github.bumptech.glide:glide:4.11.0"
@@ -1,5 +1,8 @@
1
1
  package com.appice.react;
2
2
 
3
+ import static com.appice.react.AppIceReactPluginModule.isDeviceReadyFlag;
4
+ import static com.appice.react.AppIceReactPluginModule.pendingEventQueue;
5
+
3
6
  import android.content.Context;
4
7
  import android.content.Intent;
5
8
  import android.os.Bundle;
@@ -8,7 +11,7 @@ import androidx.annotation.NonNull;
8
11
  import androidx.annotation.Nullable;
9
12
 
10
13
  import com.facebook.react.bridge.Arguments;
11
- import com.facebook.react.bridge.ReactContext;
14
+ import com.facebook.react.bridge.ReactApplicationContext;
12
15
  import com.facebook.react.bridge.ReadableArray;
13
16
  import com.facebook.react.bridge.ReadableMap;
14
17
  import com.facebook.react.bridge.ReadableMapKeySetIterator;
@@ -17,30 +20,28 @@ import com.facebook.react.bridge.WritableArray;
17
20
  import com.facebook.react.bridge.WritableMap;
18
21
  import com.facebook.react.modules.core.DeviceEventManagerModule;
19
22
 
20
- import java.util.ArrayDeque;
21
23
  import java.util.ArrayList;
22
- import java.util.Deque;
24
+ import java.util.Arrays;
23
25
  import java.util.HashMap;
24
26
  import java.util.Iterator;
25
27
  import java.util.List;
26
28
  import java.util.Map;
27
- import java.util.concurrent.atomic.AtomicBoolean;
28
29
 
29
30
  import org.json.JSONArray;
30
31
  import org.json.JSONObject;
31
32
 
33
+ import semusi.activitysdk.ContextSdk;
34
+ import semusi.context.counthandler.CampaignActionListener;
32
35
  import semusi.context.ui.appInbox.AppICEInboxMessage;
33
- import semusi.context.utility.PushClickData;
36
+
34
37
  import semusi.context.utility.Utility;
35
38
  import semusi.model.campaign.Campaign;
36
- import semusi.model.campaign.TransactionalCampaign;
37
39
  import semusi.model.user.User;
40
+ import semusi.ruleengine.pushmanager.NotificationClickHandler;
38
41
 
39
42
 
40
43
  public class AppICEUtils {
41
44
  private static final String TAG = "AppICEUtils";
42
- static final Deque<Event> EVENT_QUEUE = new ArrayDeque<>();
43
- static final AtomicBoolean IS_FLUSHING = new AtomicBoolean(false);
44
45
 
45
46
  static class Event {
46
47
  final String name;
@@ -52,86 +53,29 @@ public class AppICEUtils {
52
53
  }
53
54
  }
54
55
 
55
- static void sendEventHelper(String eventName, @Nullable WritableMap params, ReactContext context) {
56
- if (context == null || !context.hasActiveCatalystInstance()) {
57
- synchronized (EVENT_QUEUE) {
58
- WritableMap queued = null;
59
- if (params != null) {
60
- try {
61
- queued = cloneReadableMap(params);
62
- } catch (Exception ex) {
63
- printLog(TAG, "sendEvent: failed to clone params for queue " + eventName + " - " + ex.getMessage());
64
- queued = null;
65
- }
66
- }
67
- EVENT_QUEUE.add(new Event(eventName, queued));
68
- }
69
- return;
70
- }
71
-
72
- WritableMap emitCopy = null;
73
- if (params != null) {
74
- try {
75
- emitCopy = cloneReadableMap(params);
76
- } catch (Exception ex) {
77
- emitCopy = null;
78
- }
79
- }
80
-
81
- try {
82
- context.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
83
- .emit(eventName, emitCopy);
84
- printLog(TAG, "Successfully emitted event: " + eventName);
85
- } catch (Exception e) {
86
- printLog(TAG, "emit failed for " + eventName + " - " + e.getMessage());
87
- synchronized (EVENT_QUEUE) {
88
- WritableMap queued = null;
89
- if (params != null) {
90
- try {
91
- queued = cloneReadableMap(params);
92
- } catch (Exception ex) {
93
- queued = null;
94
- }
95
- }
96
- EVENT_QUEUE.add(new Event(eventName, queued));
97
- }
98
- }
99
- }
100
56
 
101
- static void flushEventQueue(ReactContext reactContext) {
102
- if (reactContext == null || !reactContext.hasActiveCatalystInstance()) {
57
+ // removed old logic that became overcomplicated with AI. later on when I reworked think
58
+ //of using different approach which flushevent when flag got updated
59
+ protected static void flushEventQueue(ReactApplicationContext ctx) {
60
+ if (!isDeviceReadyFlag || pendingEventQueue.isEmpty()) {
61
+ printLog("ActionPushDebug flushEventQueue", "Nothing to flush. flag=" + isDeviceReadyFlag + " queueSize=" + pendingEventQueue.size());
103
62
  return;
104
63
  }
105
64
 
106
- if (!IS_FLUSHING.compareAndSet(false, true)) {
107
- return;
108
- }
65
+ printLog("ActionPushDebug flushEventQueue", "Flushing " + pendingEventQueue.size() + " events");
109
66
 
110
- try {
111
- synchronized (EVENT_QUEUE) {
112
- int initialSize = EVENT_QUEUE.size();
113
- while (!EVENT_QUEUE.isEmpty()) {
114
- Event event = EVENT_QUEUE.poll();
115
- try {
116
- WritableMap toEmit = null;
117
- if (event.params != null) {
118
- try {
119
- toEmit = cloneReadableMap(event.params);
120
- } catch (Exception ex) {
121
- toEmit = event.params;
122
- }
123
- }
124
- reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
125
- .emit(event.name, toEmit);
126
- printLog(TAG, "Successfully flushed event: " + event.name + ". Remaining in queue: " + EVENT_QUEUE.size());
127
- } catch (Exception e) {
128
- EVENT_QUEUE.addFirst(event);
129
- break;
130
- }
131
- }
67
+ List<Map<String, Object>> toFlush = new ArrayList<>(pendingEventQueue);
68
+ pendingEventQueue.clear();
69
+
70
+ for (Map<String, Object> event : toFlush) {
71
+ try {
72
+ String eventName = (String) event.get("eventName");
73
+ WritableMap params = (WritableMap) event.get("param");
74
+ ctx.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit(eventName, params);
75
+ printLog("ActionPushDebug flushEventQueue", "Flushed: " + eventName);
76
+ } catch (Exception e) {
77
+ printLog("ActionPushDebug flushEventQueue", "Flush failed: " + e.getMessage());
132
78
  }
133
- } finally {
134
- IS_FLUSHING.set(false);
135
79
  }
136
80
  }
137
81
 
@@ -295,7 +239,6 @@ public class AppICEUtils {
295
239
  }
296
240
 
297
241
 
298
-
299
242
  public static WritableMap toWritableMap(Map<String, Object> map) {
300
243
  WritableMap writableMap = Arguments.createMap();
301
244
  Iterator iterator = map.entrySet().iterator();
@@ -452,7 +395,7 @@ public class AppICEUtils {
452
395
  }
453
396
  }
454
397
  return jsonObject;
455
- }catch (Throwable t){
398
+ } catch (Throwable t) {
456
399
  return null;
457
400
  }
458
401
  }
@@ -487,7 +430,7 @@ public class AppICEUtils {
487
430
  }
488
431
  }
489
432
  return jsonArray;
490
- }catch (Throwable t){
433
+ } catch (Throwable t) {
491
434
  return null;
492
435
  }
493
436
  }
@@ -496,9 +439,10 @@ public class AppICEUtils {
496
439
  System.out.println(TAG + ", " + message);
497
440
  }
498
441
 
499
- public static boolean handleAppICEPayload(@NonNull Intent intent, Context context){
442
+
443
+ public static boolean handleAppICEPayload(@NonNull Intent intent, Context context) {
500
444
  try {
501
- if (intent.getExtras() != null){
445
+ if (intent.getExtras() != null) {
502
446
  Bundle bundle = intent.getExtras();
503
447
  boolean isAppICEPush = bundle.getBoolean("ai_push", false);
504
448
  if (isAppICEPush) {
@@ -507,9 +451,95 @@ public class AppICEUtils {
507
451
  intent.removeExtra("ai_push");
508
452
  }
509
453
  }
510
- }catch (Throwable t){
511
- printLog("PUSH", " exception in click "+t);
454
+ } catch (Throwable t) {
455
+ printLog("PUSH", " exception in click " + t);
512
456
  }
513
457
  return false;
514
458
  }
459
+
460
+ /**
461
+ * Handles app link actions triggered from a notification click.
462
+ * <p>
463
+ * Flow:
464
+ * 1. Extracts NotificationClickHandler from the incoming Intent.
465
+ * 2. Retrieves the payload associated with the notification.
466
+ * 3. Validates the payload before processing.
467
+ * 4. If valid:
468
+ * - Triggers deep link handling via ContextSdk.handleOpenLinkUrl().
469
+ * - Logs the click event via ContextSdk.pushNotificationClicked().
470
+ * - Clears the intent to prevent duplicate processing.
471
+ * <p>
472
+ * Edge Cases Handled:
473
+ * - Null intent
474
+ * - Missing or invalid NotificationClickHandler
475
+ * - Empty or invalid payload
476
+ * - Any unexpected runtime exception
477
+ *
478
+ * @param intent Incoming intent containing notification click data
479
+ * @param context Application context used for handling actions
480
+ */
481
+ public static void handleAppLink(Intent intent, Context context) {
482
+ try {
483
+ if (intent != null) {
484
+ NotificationClickHandler clickHandler = NotificationClickHandler.fromIntent(intent);
485
+ if (clickHandler != null) {
486
+ String payload = clickHandler.getPayload();
487
+ printLog("handleAppLink","handleAppLink payload " + payload);
488
+ if (Utility.isValidObject(payload)) {
489
+ ContextSdk.handleOpenLinkUrl(payload, context);
490
+ ContextSdk.pushNotificationClicked(payload, context);
491
+ clickHandler.deleteIntent(intent);
492
+ } else
493
+ printLog("handleAppLink","payload is not valid");
494
+ }
495
+ } else
496
+ printLog("handleAppLink","intent is null ");
497
+ } catch (Throwable e) {
498
+ printLog("handleAppLink","exception in null ");
499
+ }
500
+ }
501
+
502
+ // this function will handle both normal push and action button push.
503
+ // through listner user will identify.
504
+ public static void handleClickOnPush(Intent intent, Context context) {
505
+ try {
506
+ if (intent != null) {
507
+ if (intent.getExtras() != null) {
508
+ Bundle bundle = intent.getExtras();
509
+ boolean isAppICEPush = bundle.getBoolean("ai_push", false);
510
+ if (isAppICEPush) {
511
+ CampaignCampsReceiver campsReceiver = new CampaignCampsReceiver();
512
+ campsReceiver.sendCallback(bundle, context);
513
+ intent.removeExtra("ai_push");
514
+ }else {
515
+ NotificationClickHandler.handleClickCallback(intent, context, new CampaignActionListener() {
516
+ @Override
517
+ public void onActionButtonClicked(Campaign campaign) {
518
+ WritableMap params = Arguments.createMap();
519
+ JSONObject campaignJson = campaign.toJson();
520
+
521
+ if (campaignJson != null && campaignJson.length() > 0) {
522
+ String campaignStr = campaignJson.toString();
523
+ params.putString(EnumConstants.APPICE_PUSH_NOTIFICATION_ACTION_BUTTON_CLICKED.getValue(), campaignStr);
524
+
525
+ printLog("ActionPushDebug onActionButtonClicked", "action button clicked | campaign: " + campaignStr);
526
+ printLog("ActionPushDebug onActionButtonClicked", "isDeviceReadyFlag: " + isDeviceReadyFlag);
527
+ printLog("ActionPushDebug onActionButtonClicked", "queue size before send: " + pendingEventQueue.size());
528
+
529
+ AppIceReactPluginModule.sendEvent(EnumConstants.APPICE_PUSH_NOTIFICATION_ACTION_BUTTON_CLICKED.getValue(), params);
530
+
531
+ printLog("ActionPushDebug onActionButtonClicked", "queue size after send: " + pendingEventQueue.size());
532
+ } else {
533
+ printLog("ActionPushDebug onActionButtonClicked", "campaignJson is null or empty — event NOT sent");
534
+ }
535
+ }
536
+ });
537
+ }
538
+ }
539
+ } else
540
+ printLog("ActionPushDebug", " | intent is null ");
541
+ } catch (Throwable e) {
542
+ printLog("ActionPushDebug"," | exception in null ");
543
+ }
544
+ }
515
545
  }
@@ -20,7 +20,9 @@ import com.facebook.react.bridge.ReactContextBaseJavaModule;
20
20
  import com.facebook.react.bridge.ReactMethod;
21
21
  import com.facebook.react.bridge.ReadableMap;
22
22
 
23
+
23
24
  import android.os.Handler;
25
+
24
26
  import semusi.activitysdk.Api;
25
27
  import semusi.activitysdk.ContextSdk;
26
28
  import semusi.activitysdk.IAppICEDeviceRegisterCallback;
@@ -34,6 +36,7 @@ import semusi.model.campaign.TransactionalCampaign;
34
36
  import semusi.model.user.User;
35
37
 
36
38
  import java.util.*;
39
+ import java.util.concurrent.ConcurrentHashMap;
37
40
 
38
41
 
39
42
  import androidx.annotation.NonNull;
@@ -43,6 +46,7 @@ import com.facebook.react.bridge.ReadableArray;
43
46
  import com.facebook.react.bridge.WritableArray;
44
47
  import com.facebook.react.bridge.WritableMap;
45
48
  import com.facebook.react.module.annotations.ReactModule;
49
+ import com.facebook.react.modules.core.DeviceEventManagerModule;
46
50
 
47
51
  import org.json.JSONObject;
48
52
 
@@ -50,6 +54,9 @@ import org.json.JSONObject;
50
54
  public class AppIceReactPluginModule extends ReactContextBaseJavaModule {
51
55
  private static ReactApplicationContext context = null;
52
56
  public static final String NAME = "AppIceReactPlugin";
57
+ protected static volatile boolean isDeviceReadyFlag;
58
+ protected static final List<Map<String, Object>> pendingEventQueue =
59
+ Collections.synchronizedList(new ArrayList<>());
53
60
 
54
61
  public AppIceReactPluginModule(ReactApplicationContext reactContext) {
55
62
  super(reactContext);
@@ -97,7 +104,8 @@ public class AppIceReactPluginModule extends ReactContextBaseJavaModule {
97
104
  , context);
98
105
 
99
106
  Api.startContext(context, config);
100
-
107
+ String token= ContextSdk.getFCMToken(context);
108
+ printLog("AppICE","| firebase token = "+token);
101
109
  } catch (Exception e) {
102
110
  printLog(NAME, "Exception in startContext : " + e);
103
111
  }
@@ -637,17 +645,30 @@ public class AppIceReactPluginModule extends ReactContextBaseJavaModule {
637
645
  Context context = getReactApplicationContext();
638
646
  callback.invoke(ContextSdk.getInternalId(context));
639
647
  }
640
- @ReactMethod
641
- public void isDeviceReady(Boolean flag){
642
- if (flag){
643
- ReactApplicationContext ctx = getReactApplicationContext();
644
- flushEventQueue(ctx);
648
+
649
+ public static void sendEvent(String eventName, @Nullable WritableMap params) {
650
+ if (isDeviceReadyFlag) {
651
+ try {
652
+ context.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit(eventName, params);
653
+ printLog("ActionPushDebug sendEvent", "Successfully emitted event: " + eventName);
654
+ } catch (Exception e) {
655
+ printLog("ActionPushDebug sendEvent", "emit failed for " + eventName + " - " + e.getMessage());
656
+ }
657
+ } else {
658
+ Map<String, Object> pending = new HashMap<>();
659
+ pending.put("eventName", eventName);
660
+ pending.put("param", params);
661
+ pendingEventQueue.add(pending);
662
+ printLog("ActionPushDebug sendEvent", "Queued event: " + eventName + " Queue size: " + pendingEventQueue.size());
645
663
  }
646
664
  }
647
665
 
648
- //=====================================
649
- public static void sendEvent(String eventName, @Nullable WritableMap params) {
650
- AppICEUtils.sendEventHelper(eventName, params, context);
666
+ @ReactMethod
667
+ public void isDeviceReady(Boolean flag) {
668
+ ReactApplicationContext ctx = getReactApplicationContext();
669
+ isDeviceReadyFlag = flag;
670
+ printLog("ActionPushDebug", "isDeviceReadyFlag " + isDeviceReadyFlag);
671
+ flushEventQueue(ctx);
651
672
  }
652
673
 
653
674
  private static AppICEInboxMessage getMediaPreProcessing(ReadableMap inboxMessage,Context context) {
@@ -863,6 +884,7 @@ public class AppIceReactPluginModule extends ReactContextBaseJavaModule {
863
884
  @ReactMethod
864
885
  public void scheduleTransactionalCampaign(String transactionalStringPayload){
865
886
  Context context = getReactApplicationContext();
887
+ printLog("AppIceReactPluginModule", "scheduleTransactionalCampaign, payload = "+transactionalStringPayload );
866
888
  TransactionalCampaign transactionalCampaign = TransactionalCampaign.toTransactionalCampaign(transactionalStringPayload);
867
889
  ContextSdk.scheduleCampaign(transactionalCampaign, context);
868
890
  }
@@ -883,6 +905,35 @@ public class AppIceReactPluginModule extends ReactContextBaseJavaModule {
883
905
  }
884
906
  }
885
907
 
908
+ //======================================================
909
+ // INAPP
910
+ //======================================================
911
+
912
+ @ReactMethod
913
+ public void resumeInApp(){
914
+ Context context = getReactApplicationContext();
915
+ ContextSdk.resumeInApp(context);
916
+ }
917
+
918
+ @ReactMethod
919
+ public void suspendInApp(){
920
+ Context context = getReactApplicationContext();
921
+ ContextSdk.suspendInApp(context);
922
+ }
923
+
924
+ @ReactMethod
925
+ public void discardInApp(){
926
+ Context context = getReactApplicationContext();
927
+ ContextSdk.discardInApp(context);
928
+ }
929
+
930
+ @ReactMethod
931
+ public void dismissInApp(){
932
+ ContextSdk.dismissInApp();
933
+ }
934
+
935
+ //================================================================
936
+
886
937
  @Nullable
887
938
  @Override
888
939
  public Map<String, Object> getConstants() {
@@ -899,6 +950,7 @@ public class AppIceReactPluginModule extends ReactContextBaseJavaModule {
899
950
  constants.put(EnumConstants.APPICE_USER_AGE.getConstants(), EnumConstants.APPICE_USER_AGE.getValue());
900
951
  constants.put(EnumConstants.APPICE_USER_GENDER.getConstants(), EnumConstants.APPICE_USER_GENDER.getValue());
901
952
  constants.put(EnumConstants.APPICE_PUSH_NOTIFICATION_CLICKED.getConstants(), EnumConstants.APPICE_PUSH_NOTIFICATION_CLICKED.getValue());
953
+ constants.put(EnumConstants.APPICE_PUSH_NOTIFICATION_ACTION_BUTTON_CLICKED.getConstants(), EnumConstants.APPICE_PUSH_NOTIFICATION_ACTION_BUTTON_CLICKED.getValue());
902
954
  constants.put(EnumConstants.APPICE_INAPP_NOTIFICATION_CLICKED.getConstants(), EnumConstants.APPICE_INAPP_NOTIFICATION_CLICKED.getValue());
903
955
  constants.put(EnumConstants.FIRST_SEEN.getConstants(), EnumConstants.FIRST_SEEN.getValue());
904
956
  constants.put(EnumConstants.LAST_SEEN.getConstants(), EnumConstants.LAST_SEEN.getValue());
@@ -921,6 +973,10 @@ public class AppIceReactPluginModule extends ReactContextBaseJavaModule {
921
973
  constants.put(EnumConstants.ACTION_URL.getConstants(), EnumConstants.ACTION_URL.getValue());
922
974
  constants.put(EnumConstants.ACTION_TYPE.getConstants(), EnumConstants.ACTION_TYPE.getValue());
923
975
  constants.put(EnumConstants.CUSTOMDATA.getConstants(), EnumConstants.CUSTOMDATA.getValue());
976
+ constants.put(EnumConstants.ACTION_TYPE_CUSTOM.getConstants(), EnumConstants.ACTION_TYPE_CUSTOM.getValue());
977
+ constants.put(EnumConstants.ACTION_TYPE_DEEPLINK.getConstants(), EnumConstants.ACTION_TYPE_DEEPLINK.getValue());
978
+ constants.put(EnumConstants.ACTION_TYPE_REPLY.getConstants(), EnumConstants.ACTION_TYPE_REPLY.getValue());
979
+ constants.put(EnumConstants.ACTION_TYPE_REMIND_ME_LATER.getConstants(), EnumConstants.ACTION_TYPE_REMIND_ME_LATER.getValue());
924
980
 
925
981
  return constants;
926
982
  }
@@ -31,6 +31,7 @@ public enum EnumConstants {
31
31
  //PUSH
32
32
  //============================
33
33
  APPICE_PUSH_NOTIFICATION_CLICKED("AppICEPushNotificationClicked"),
34
+ APPICE_PUSH_NOTIFICATION_ACTION_BUTTON_CLICKED("AppICEPushNotificationActionButtonClicked"),
34
35
 
35
36
  //===========================
36
37
  //IN-APP
@@ -88,7 +89,16 @@ public enum EnumConstants {
88
89
  CAMP_ID("CAMP_ID"),
89
90
  ACTION_URL("ACTION_URL"),
90
91
  ACTION_TYPE("ACTION_TYPE"),
91
- CUSTOMDATA("CUSTOMDATA");
92
+ CUSTOMDATA("CUSTOMDATA"),
93
+
94
+
95
+ //=======================
96
+ // ACTION TYPES
97
+ //=======================
98
+ ACTION_TYPE_CUSTOM("ACTION_TYPE_CUSTOM"),
99
+ ACTION_TYPE_DEEPLINK("ACTION_TYPE_DEEPLINK"),
100
+ ACTION_TYPE_REPLY("ACTION_TYPE_REPLY"),
101
+ ACTION_TYPE_REMIND_ME_LATER("ACTION_TYPE_REMIND_ME_LATER");
92
102
 
93
103
  private String constants;
94
104
 
@@ -148,6 +158,10 @@ public enum EnumConstants {
148
158
  return StringConstants.APPICE_PUSH_NOTIFICATION_CLICKED;
149
159
  }
150
160
 
161
+ case APPICE_PUSH_NOTIFICATION_ACTION_BUTTON_CLICKED:{
162
+ return StringConstants.APPICE_PUSH_NOTIFICATION_ACTION_BUTTON_CLICKED;
163
+ }
164
+
151
165
  case APPICE_INAPP_NOTIFICATION_CLICKED:{
152
166
  return StringConstants.APPICE_INAPP_NOTIFICATION_CLICKED;
153
167
  }
@@ -272,6 +286,22 @@ public enum EnumConstants {
272
286
  case CUSTOMDATA:{
273
287
  return CUSTOM_DATA;
274
288
  }
289
+
290
+ case ACTION_TYPE_CUSTOM:{
291
+ return CampaignConstants.CUSTOM;
292
+ }
293
+
294
+ case ACTION_TYPE_DEEPLINK:{
295
+ return CampaignConstants.DEEP_LINK;
296
+ }
297
+
298
+ case ACTION_TYPE_REPLY:{
299
+ return CampaignConstants.REPLY;
300
+ }
301
+ case ACTION_TYPE_REMIND_ME_LATER:{
302
+ return CampaignConstants.REMIND_LATER;
303
+ }
304
+
275
305
  default:
276
306
  return "";
277
307
  }
@@ -8,6 +8,7 @@ public interface StringConstants{
8
8
  String MEDIA_THUMBNAIL = "mediaThumbnail";
9
9
  String MEDIA_DATA = "mediaData";
10
10
  String APPICE_PUSH_NOTIFICATION_CLICKED = "AppICEPushNotificationClicked";
11
+ String APPICE_PUSH_NOTIFICATION_ACTION_BUTTON_CLICKED = "AppICEPushNotificationActionButtonClicked";
11
12
  String APPICE_INAPP_NOTIFICATION_CLICKED = "AppICEInAppClicked";
12
13
  String INBOX_MESSAGE = "message";
13
14
  String INBOX_TITLE = "title";
package/campaign.js CHANGED
@@ -1,6 +1,10 @@
1
1
  const { Linking, Platform } = require('react-native');
2
2
 
3
3
  async function handleClickOnPush(campaign) {
4
+ if (campaign && campaign._data) {
5
+ campaign = campaign._data;
6
+ }
7
+
4
8
  const url = campaign.actionUrl || campaign.acu || campaign.eurl;
5
9
  const actionType = campaign.actionType || campaign.act || campaign.et;
6
10
 
@@ -14,6 +18,7 @@ async function handleClickOnPush(campaign) {
14
18
  if (httpUrls) {
15
19
  try {
16
20
  if (Platform.OS === 'ios') {
21
+ campaign = normalizeCampaignPayloadForPlatform(campaign);
17
22
  return campaign;
18
23
  // iOS handle redirection on native side for landing page.
19
24
  }
@@ -31,6 +36,28 @@ async function handleClickOnPush(campaign) {
31
36
  }
32
37
  }
33
38
 
39
+
40
+ const PAYLOAD_KEYS = Object.freeze({
41
+ DATA: 'data',
42
+ MESSAGE: 'message',
43
+ });
44
+
45
+ // iOS push click payload often nests campaign fields under data.message.
46
+ // Android payload already comes in campaign shape.
47
+ function normalizeCampaignPayloadForPlatform(data) {
48
+ if (!data || typeof data !== 'object') return data;
49
+ if (Platform.OS !== 'ios') return data;
50
+
51
+ const dataNode = data[PAYLOAD_KEYS.DATA];
52
+ if (!dataNode || typeof dataNode !== 'object') return data;
53
+
54
+ const messageNode = dataNode[PAYLOAD_KEYS.MESSAGE];
55
+ if (messageNode && typeof messageNode === 'object') {
56
+ return messageNode;
57
+ }
58
+ return data;
59
+ }
60
+
34
61
  // ===============================
35
62
  // Campaign (merged backward-compatible)
36
63
  // ===============================
@@ -46,6 +73,9 @@ class Campaign {
46
73
  // if parse fails, keep eventData as-is (object expected)
47
74
  data = eventData || {};
48
75
  }
76
+
77
+ // Keep app-side listener thin by normalizing payload shape in campaign layer.
78
+ data = normalizeCampaignPayloadForPlatform(data);
49
79
  const isLegacy = data && (data.camp_id || data.eurl || data.et || data.abt || data.act || data.acc);
50
80
 
51
81
  if (isLegacy) {
@@ -200,6 +230,19 @@ class Campaign {
200
230
  return this._data.customData ? this._data.customData[key] || '' : '';
201
231
  }
202
232
 
233
+ //Action button
234
+ getSelectedActionTitle() {
235
+ return this._data.selectedActionTitle;
236
+ }
237
+
238
+ getSelectedActionType() {
239
+ return this._data.selectedActionType;
240
+ }
241
+
242
+ getSelectedActionUrl() {
243
+ return this._data.selectedActionUrl;
244
+ }
245
+
203
246
  // Convert to JSON
204
247
  toJSON() {
205
248
  return this._data;
@@ -17,7 +17,7 @@
17
17
  "install": "^0.13.0",
18
18
  "react": "18.0.0",
19
19
  "react-native": "0.69.4",
20
- "reactnative-plugin-appice": "1.7.42",
20
+ "reactnative-plugin-appice": "1.7.43",
21
21
  "react-native-mmkv": "2.12.2"
22
22
  },
23
23
  "devDependencies": {