reactnative-plugin-appice 1.7.43 → 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/TransactionalCampaign.js +60 -0
- package/android/build.gradle +1 -1
- package/android/src/main/java/com/appice/react/AppICEUtils.java +85 -98
- package/android/src/main/java/com/appice/react/AppIceReactPluginModule.java +62 -9
- package/android/src/main/java/com/appice/react/EnumConstants.java +31 -1
- package/android/src/main/java/com/appice/react/StringConstants.java +1 -0
- package/campaign.js +43 -0
- package/index.js +94 -65
- package/ios/AppICEReactEvent.m +11 -2
- package/ios/AppIceReactPlugin.h +7 -1
- package/ios/AppIceReactPlugin.m +198 -60
- package/ios/AppIceReactPlugin.xcworkspace/xcuserdata/artherajesh.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/package.json +2 -1
- package/reactnative-plugin-appice.podspec +1 -1
|
@@ -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;
|
package/android/build.gradle
CHANGED
|
@@ -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.
|
|
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.
|
|
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,18 +20,18 @@ 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.
|
|
24
|
+
import java.util.Arrays;
|
|
23
25
|
import java.util.HashMap;
|
|
24
26
|
import java.util.Iterator;
|
|
27
|
+
import java.util.List;
|
|
25
28
|
import java.util.Map;
|
|
26
|
-
import java.util.concurrent.atomic.AtomicBoolean;
|
|
27
29
|
|
|
28
30
|
import org.json.JSONArray;
|
|
29
31
|
import org.json.JSONObject;
|
|
30
32
|
|
|
31
33
|
import semusi.activitysdk.ContextSdk;
|
|
34
|
+
import semusi.context.counthandler.CampaignActionListener;
|
|
32
35
|
import semusi.context.ui.appInbox.AppICEInboxMessage;
|
|
33
36
|
|
|
34
37
|
import semusi.context.utility.Utility;
|
|
@@ -39,8 +42,6 @@ import semusi.ruleengine.pushmanager.NotificationClickHandler;
|
|
|
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
56
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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
|
-
|
|
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
|
-
|
|
107
|
-
return;
|
|
108
|
-
}
|
|
65
|
+
printLog("ActionPushDebug flushEventQueue", "Flushing " + pendingEventQueue.size() + " events");
|
|
109
66
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
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
|
-
|
|
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,24 +451,24 @@ 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
|
}
|
|
515
459
|
|
|
516
460
|
/**
|
|
517
461
|
* Handles app link actions triggered from a notification click.
|
|
518
|
-
*
|
|
462
|
+
* <p>
|
|
519
463
|
* Flow:
|
|
520
464
|
* 1. Extracts NotificationClickHandler from the incoming Intent.
|
|
521
465
|
* 2. Retrieves the payload associated with the notification.
|
|
522
466
|
* 3. Validates the payload before processing.
|
|
523
467
|
* 4. If valid:
|
|
524
|
-
*
|
|
525
|
-
*
|
|
526
|
-
*
|
|
527
|
-
*
|
|
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>
|
|
528
472
|
* Edge Cases Handled:
|
|
529
473
|
* - Null intent
|
|
530
474
|
* - Missing or invalid NotificationClickHandler
|
|
@@ -536,23 +480,66 @@ public class AppICEUtils {
|
|
|
536
480
|
*/
|
|
537
481
|
public static void handleAppLink(Intent intent, Context context) {
|
|
538
482
|
try {
|
|
539
|
-
if (intent != null){
|
|
483
|
+
if (intent != null) {
|
|
540
484
|
NotificationClickHandler clickHandler = NotificationClickHandler.fromIntent(intent);
|
|
541
485
|
if (clickHandler != null) {
|
|
542
486
|
String payload = clickHandler.getPayload();
|
|
543
|
-
|
|
487
|
+
printLog("handleAppLink","handleAppLink payload " + payload);
|
|
544
488
|
if (Utility.isValidObject(payload)) {
|
|
545
489
|
ContextSdk.handleOpenLinkUrl(payload, context);
|
|
546
490
|
ContextSdk.pushNotificationClicked(payload, context);
|
|
547
491
|
clickHandler.deleteIntent(intent);
|
|
548
492
|
} else
|
|
549
|
-
|
|
493
|
+
printLog("handleAppLink","payload is not valid");
|
|
550
494
|
}
|
|
551
|
-
}else
|
|
552
|
-
|
|
495
|
+
} else
|
|
496
|
+
printLog("handleAppLink","intent is null ");
|
|
553
497
|
} catch (Throwable e) {
|
|
554
|
-
|
|
498
|
+
printLog("handleAppLink","exception in null ");
|
|
555
499
|
}
|
|
556
500
|
}
|
|
557
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
|
+
}
|
|
558
545
|
}
|
|
@@ -36,6 +36,7 @@ import semusi.model.campaign.TransactionalCampaign;
|
|
|
36
36
|
import semusi.model.user.User;
|
|
37
37
|
|
|
38
38
|
import java.util.*;
|
|
39
|
+
import java.util.concurrent.ConcurrentHashMap;
|
|
39
40
|
|
|
40
41
|
|
|
41
42
|
import androidx.annotation.NonNull;
|
|
@@ -45,6 +46,7 @@ import com.facebook.react.bridge.ReadableArray;
|
|
|
45
46
|
import com.facebook.react.bridge.WritableArray;
|
|
46
47
|
import com.facebook.react.bridge.WritableMap;
|
|
47
48
|
import com.facebook.react.module.annotations.ReactModule;
|
|
49
|
+
import com.facebook.react.modules.core.DeviceEventManagerModule;
|
|
48
50
|
|
|
49
51
|
import org.json.JSONObject;
|
|
50
52
|
|
|
@@ -52,6 +54,9 @@ import org.json.JSONObject;
|
|
|
52
54
|
public class AppIceReactPluginModule extends ReactContextBaseJavaModule {
|
|
53
55
|
private static ReactApplicationContext context = null;
|
|
54
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<>());
|
|
55
60
|
|
|
56
61
|
public AppIceReactPluginModule(ReactApplicationContext reactContext) {
|
|
57
62
|
super(reactContext);
|
|
@@ -99,7 +104,8 @@ public class AppIceReactPluginModule extends ReactContextBaseJavaModule {
|
|
|
99
104
|
, context);
|
|
100
105
|
|
|
101
106
|
Api.startContext(context, config);
|
|
102
|
-
|
|
107
|
+
String token= ContextSdk.getFCMToken(context);
|
|
108
|
+
printLog("AppICE","| firebase token = "+token);
|
|
103
109
|
} catch (Exception e) {
|
|
104
110
|
printLog(NAME, "Exception in startContext : " + e);
|
|
105
111
|
}
|
|
@@ -639,17 +645,30 @@ public class AppIceReactPluginModule extends ReactContextBaseJavaModule {
|
|
|
639
645
|
Context context = getReactApplicationContext();
|
|
640
646
|
callback.invoke(ContextSdk.getInternalId(context));
|
|
641
647
|
}
|
|
642
|
-
|
|
643
|
-
public void
|
|
644
|
-
if (
|
|
645
|
-
|
|
646
|
-
|
|
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());
|
|
647
663
|
}
|
|
648
664
|
}
|
|
649
665
|
|
|
650
|
-
|
|
651
|
-
public
|
|
652
|
-
|
|
666
|
+
@ReactMethod
|
|
667
|
+
public void isDeviceReady(Boolean flag) {
|
|
668
|
+
ReactApplicationContext ctx = getReactApplicationContext();
|
|
669
|
+
isDeviceReadyFlag = flag;
|
|
670
|
+
printLog("ActionPushDebug", "isDeviceReadyFlag " + isDeviceReadyFlag);
|
|
671
|
+
flushEventQueue(ctx);
|
|
653
672
|
}
|
|
654
673
|
|
|
655
674
|
private static AppICEInboxMessage getMediaPreProcessing(ReadableMap inboxMessage,Context context) {
|
|
@@ -886,6 +905,35 @@ public class AppIceReactPluginModule extends ReactContextBaseJavaModule {
|
|
|
886
905
|
}
|
|
887
906
|
}
|
|
888
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
|
+
|
|
889
937
|
@Nullable
|
|
890
938
|
@Override
|
|
891
939
|
public Map<String, Object> getConstants() {
|
|
@@ -902,6 +950,7 @@ public class AppIceReactPluginModule extends ReactContextBaseJavaModule {
|
|
|
902
950
|
constants.put(EnumConstants.APPICE_USER_AGE.getConstants(), EnumConstants.APPICE_USER_AGE.getValue());
|
|
903
951
|
constants.put(EnumConstants.APPICE_USER_GENDER.getConstants(), EnumConstants.APPICE_USER_GENDER.getValue());
|
|
904
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());
|
|
905
954
|
constants.put(EnumConstants.APPICE_INAPP_NOTIFICATION_CLICKED.getConstants(), EnumConstants.APPICE_INAPP_NOTIFICATION_CLICKED.getValue());
|
|
906
955
|
constants.put(EnumConstants.FIRST_SEEN.getConstants(), EnumConstants.FIRST_SEEN.getValue());
|
|
907
956
|
constants.put(EnumConstants.LAST_SEEN.getConstants(), EnumConstants.LAST_SEEN.getValue());
|
|
@@ -924,6 +973,10 @@ public class AppIceReactPluginModule extends ReactContextBaseJavaModule {
|
|
|
924
973
|
constants.put(EnumConstants.ACTION_URL.getConstants(), EnumConstants.ACTION_URL.getValue());
|
|
925
974
|
constants.put(EnumConstants.ACTION_TYPE.getConstants(), EnumConstants.ACTION_TYPE.getValue());
|
|
926
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());
|
|
927
980
|
|
|
928
981
|
return constants;
|
|
929
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;
|
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
|
-
|
|
180
|
+
//AppIceReactPlugin.resumeInApp();
|
|
172
181
|
} else if (nextAppState === 'background') {
|
|
173
|
-
|
|
174
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
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
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
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
|
-
|
|
504
|
-
|
|
512
|
+
callWithCallback('isDeviceRegistered', null, callback);
|
|
513
|
+
},
|
|
505
514
|
|
|
506
515
|
setAppLanguage: function (language) {
|
|
507
|
-
|
|
508
|
-
|
|
516
|
+
|
|
517
|
+
AppIceReactPlugin.setAppLanguage(language);
|
|
509
518
|
|
|
510
519
|
},
|
|
511
520
|
|
|
512
521
|
getAppLanguage: function (callback) {
|
|
513
|
-
|
|
514
|
-
|
|
522
|
+
callWithCallback('getAppLanguage', null, callback);
|
|
523
|
+
},
|
|
515
524
|
|
|
516
525
|
setDeviceLanguage: function (language) {
|
|
517
526
|
|
|
518
|
-
|
|
519
|
-
|
|
527
|
+
AppIceReactPlugin.setDeviceLanguage(language);
|
|
528
|
+
|
|
520
529
|
},
|
|
521
530
|
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
531
|
+
getDeviceLanguage: function (callback) {
|
|
532
|
+
callWithCallback('getDeviceLanguage', null, callback);
|
|
533
|
+
},
|
|
525
534
|
|
|
526
|
-
|
|
527
|
-
|
|
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
|
-
|
|
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
|
-
|
|
544
|
-
|
|
545
|
-
|
|
559
|
+
},
|
|
560
|
+
|
|
561
|
+
/*===================
|
|
562
|
+
INAPP
|
|
563
|
+
=====================*/
|
|
546
564
|
|
|
547
|
-
|
|
548
|
-
|
|
565
|
+
resumeInApp: function () {
|
|
566
|
+
AppIceReactPlugin.resumeInApp();
|
|
567
|
+
},
|
|
549
568
|
|
|
550
|
-
|
|
569
|
+
suspendInApp: function () {
|
|
570
|
+
AppIceReactPlugin.suspendInApp();
|
|
571
|
+
},
|
|
551
572
|
|
|
552
|
-
|
|
553
|
-
|
|
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
|
-
|
|
589
|
-
|
|
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))
|
package/ios/AppICEReactEvent.m
CHANGED
|
@@ -36,7 +36,7 @@ RCT_EXPORT_MODULE();
|
|
|
36
36
|
|
|
37
37
|
- (NSArray<NSString *> *)supportedEvents
|
|
38
38
|
{
|
|
39
|
-
|
|
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
|
|
package/ios/AppIceReactPlugin.h
CHANGED
|
@@ -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:(
|
|
68
|
+
+ (void)pushNotificationClicked:(id)userInfo;
|
|
63
69
|
+ (void)pushNotificationReceived:(NSDictionary *)userInfo;
|
|
64
70
|
@end
|
|
65
71
|
|
package/ios/AppIceReactPlugin.m
CHANGED
|
@@ -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
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
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 :
|
|
51
|
-
INBOX_TITLE :
|
|
52
|
-
INBOX_MESSAGE_STATUS :
|
|
53
|
-
INBOX_CAMPAIGN_TYPE :
|
|
54
|
-
INBOX_MESSAGE_LANGUAGE :
|
|
55
|
-
INBOX_MESSAGE_ID :
|
|
56
|
-
INBOX_CAMPAIGN_ID :
|
|
57
|
-
INBOX_MESSAGE_CATEGORY :
|
|
58
|
-
INBOX_MESSAGE_ICON :
|
|
59
|
-
INBOX_CUSTOM_DATA :
|
|
60
|
-
INBOX_MESSAGE_EXPANDED_IMAGE
|
|
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
|
|
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 :
|
|
81
|
-
ACTION_URL :
|
|
82
|
-
ACTION_TYPE:
|
|
83
|
-
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:(
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
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:(
|
|
541
|
+
+ (void)storePendingDeeplink:(id)response {
|
|
546
542
|
@try {
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
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
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "reactnative-plugin-appice",
|
|
3
|
-
"version": "1.7.
|
|
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
|
],
|