reactnative-plugin-appice 1.7.47 → 1.7.49
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/android/build.gradle +1 -1
- package/android/src/main/AndroidManifest.xml +0 -9
- package/android/src/main/java/com/appice/react/AppICEUtils.java +81 -94
- package/android/src/main/java/com/appice/react/CampaignCampsReceiver.java +0 -2
- package/campaign.js +34 -38
- package/example/package.json +1 -1
- package/ios/AppIceReactPlugin.m +1 -1
- package/package.json +1 -1
- package/reactnative-plugin-appice.podspec +1 -1
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.46"
|
|
101
101
|
|
|
102
102
|
//glide
|
|
103
103
|
implementation "com.github.bumptech.glide:glide:4.11.0"
|
|
@@ -97,15 +97,6 @@
|
|
|
97
97
|
android:permission="android.permission.BIND_JOB_SERVICE">
|
|
98
98
|
</service>
|
|
99
99
|
|
|
100
|
-
<receiver
|
|
101
|
-
android:protectionLevel="signature"
|
|
102
|
-
android:name="semusi.context.ui.Carousel.CarouselEventReceiver"
|
|
103
|
-
android:exported="false">
|
|
104
|
-
<intent-filter>
|
|
105
|
-
<action android:name="io.appice.CAROUSELNOTIFICATIONFIRED" />
|
|
106
|
-
</intent-filter>
|
|
107
|
-
</receiver>
|
|
108
|
-
|
|
109
100
|
<receiver
|
|
110
101
|
android:name="semusi.ruleengine.pushmanager.AppICEMessageHandler"
|
|
111
102
|
android:exported="true"
|
|
@@ -3,6 +3,8 @@ package com.appice.react;
|
|
|
3
3
|
import static com.appice.react.AppIceReactPluginModule.isDeviceReadyFlag;
|
|
4
4
|
import static com.appice.react.AppIceReactPluginModule.pendingEventQueue;
|
|
5
5
|
|
|
6
|
+
import static semusi.ruleengine.pushmanager.NotificationClickHandler.K_PAYLOAD;
|
|
7
|
+
|
|
6
8
|
import android.content.Context;
|
|
7
9
|
import android.content.Intent;
|
|
8
10
|
import android.os.Bundle;
|
|
@@ -56,6 +58,8 @@ public class AppICEUtils {
|
|
|
56
58
|
}
|
|
57
59
|
|
|
58
60
|
|
|
61
|
+
// removed old logic that became overcomplicated with AI. later on when I reworked think
|
|
62
|
+
//of using different approach which flushevent when flag got updated
|
|
59
63
|
protected static void flushEventQueue(ReactApplicationContext ctx) {
|
|
60
64
|
if (!isDeviceReadyFlag || pendingEventQueue.isEmpty()) {
|
|
61
65
|
printLog("ActionPushDebug flushEventQueue", "Nothing to flush. flag=" + isDeviceReadyFlag + " queueSize=" + pendingEventQueue.size());
|
|
@@ -513,118 +517,101 @@ public class AppICEUtils {
|
|
|
513
517
|
}
|
|
514
518
|
}
|
|
515
519
|
|
|
520
|
+
// this function will handle both normal push and action button push.
|
|
521
|
+
// through listner user will identify.
|
|
516
522
|
public static void handleClickOnPush(Intent intent, Context context) {
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
Bundle bundle = intent.getExtras();
|
|
521
|
-
if (bundle != null) {
|
|
522
|
-
|
|
523
|
-
NotificationClickHandler pushClickData = NotificationClickHandler.fromBundle(bundle);
|
|
524
|
-
String payload = pushClickData.getPayload();
|
|
525
|
-
|
|
526
|
-
int pos = bundle.getInt("pos", -1);
|
|
527
|
-
int notificationId = bundle.getInt("n", 0);
|
|
528
|
-
|
|
529
|
-
if (pos == -1) {
|
|
530
|
-
CampaignCampsReceiver campsReceiver = new CampaignCampsReceiver();
|
|
531
|
-
campsReceiver.sendCallback(bundle, context);
|
|
532
|
-
intent.removeExtra("pos");
|
|
533
|
-
} else {
|
|
534
|
-
handleActionClick(payload, notificationId, intent, pushClickData, pos, context);
|
|
535
|
-
}
|
|
536
|
-
}else
|
|
537
|
-
printLog("ActionPushDebug", " | bundle is null ");
|
|
538
|
-
}
|
|
539
|
-
} else
|
|
540
|
-
printLog("ActionPushDebug", " | intent is null ");
|
|
541
|
-
} catch (Throwable e) {
|
|
542
|
-
printLog("ActionPushDebug"," | exception in null ");
|
|
523
|
+
if (intent == null) {
|
|
524
|
+
printLog("ActionPushDebug", "Intent is null");
|
|
525
|
+
return;
|
|
543
526
|
}
|
|
544
|
-
}
|
|
545
527
|
|
|
546
|
-
|
|
547
|
-
if (
|
|
528
|
+
Bundle bundle = intent.getExtras();
|
|
529
|
+
if (bundle == null) {
|
|
530
|
+
printLog("ActionPushDebug", "Bundle is null");
|
|
548
531
|
return;
|
|
549
532
|
}
|
|
533
|
+
|
|
534
|
+
NotificationClickHandler pushClickData = null;
|
|
535
|
+
|
|
550
536
|
try {
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
if (selectedAction != null) {
|
|
557
|
-
payloadJson.put("selectedAction", selectedAction.toJson());
|
|
558
|
-
} else {
|
|
559
|
-
ContextSdk.pushNotificationClicked(payloadJson.toString(), context);
|
|
537
|
+
pushClickData = NotificationClickHandler.fromBundle(bundle);
|
|
538
|
+
String payload = pushClickData.getPayload();
|
|
539
|
+
|
|
540
|
+
if (!Utility.isValidObject(payload)) {
|
|
541
|
+
return;
|
|
560
542
|
}
|
|
561
|
-
handleCampaignAction(campaign,context);
|
|
562
|
-
pushClickData.deleteKeyFromIntent(intent, NotificationClickHandler.K_PAYLOAD);
|
|
563
|
-
} catch (Exception e) {
|
|
564
|
-
printLog("ActionPushDebug","Action button: action click failed - " + e.getMessage());
|
|
565
|
-
}
|
|
566
|
-
}
|
|
567
543
|
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
return;
|
|
572
|
-
}
|
|
544
|
+
JSONObject payloadJson = new JSONObject(payload);
|
|
545
|
+
int pos = bundle.getInt("pos", -1);
|
|
546
|
+
int notificationId = bundle.getInt("n", -1);
|
|
573
547
|
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
548
|
+
// Notification body click
|
|
549
|
+
if (pos == -1) {
|
|
550
|
+
if (ContextSdk.isPayloadHaveExternalUrl(payload)) {
|
|
551
|
+
ContextSdk.pushNotificationClicked(payload, context);
|
|
552
|
+
ContextSdk.handleExternalUrl(payload, context);
|
|
553
|
+
return;
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
CampaignCampsReceiver campsReceiver = new CampaignCampsReceiver();
|
|
557
|
+
campsReceiver.sendCallback(bundle, context);
|
|
578
558
|
return;
|
|
579
559
|
}
|
|
580
|
-
String actionType = selectedAction.getActionType() != null ? selectedAction.getActionType().toLowerCase(Locale.ROOT) : null;
|
|
581
|
-
String actionContent = selectedAction.getActionContent();
|
|
582
|
-
String actionTitle = selectedAction.getActionTitle();
|
|
583
|
-
String actionURL = selectedAction.getActionUrl();
|
|
584
560
|
|
|
585
|
-
|
|
561
|
+
// Notification action button click
|
|
562
|
+
if (notificationId >= 0) {
|
|
563
|
+
payloadJson.put("notificationId", notificationId);
|
|
564
|
+
}
|
|
565
|
+
payloadJson.put("selectedIndex", pos);
|
|
566
|
+
|
|
567
|
+
Campaign campaign = ContextSdk.handlePush(payloadJson.toString(), context);
|
|
586
568
|
|
|
587
|
-
if (
|
|
588
|
-
printLog("ActionPushDebug","Action button: action type is null");
|
|
569
|
+
if (campaign == null) {
|
|
589
570
|
return;
|
|
590
571
|
}
|
|
591
572
|
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
printLog("ActionPushDebug onActionButtonClicked", "action button clicked | campaign: " + campaignStr);
|
|
613
|
-
printLog("ActionPushDebug onActionButtonClicked", "isDeviceReadyFlag: " + isDeviceReadyFlag);
|
|
614
|
-
printLog("ActionPushDebug onActionButtonClicked", "queue size before send: " + pendingEventQueue.size());
|
|
615
|
-
AppIceReactPluginModule.sendEvent(EnumConstants.APPICE_PUSH_NOTIFICATION_ACTION_BUTTON_CLICKED.getValue(), params);
|
|
616
|
-
printLog("ActionPushDebug onActionButtonClicked", "queue size after send: " + pendingEventQueue.size());
|
|
617
|
-
} else {
|
|
618
|
-
printLog("ActionPushDebug onActionButtonClicked", "campaignJson is null or empty — event NOT sent");
|
|
619
|
-
}
|
|
620
|
-
break;
|
|
621
|
-
default:
|
|
622
|
-
printLog("ActionPushDebug","Action button: unknown action type - " + actionType);
|
|
623
|
-
break;
|
|
573
|
+
Action action = campaign.getSelectedAction();
|
|
574
|
+
if (action == null) {
|
|
575
|
+
return;
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
String type = action.getActionType();
|
|
579
|
+
|
|
580
|
+
if (Utility.isValidObject(type) && (type.equalsIgnoreCase("lp") || type.equalsIgnoreCase("dl"))) {
|
|
581
|
+
Map<String, Object> map = new HashMap<>();
|
|
582
|
+
map.put("campid", campaign.getCampId());
|
|
583
|
+
map.put("abt", action.getActionTitle());
|
|
584
|
+
map.put("mid", campaign.getMessageId());
|
|
585
|
+
ContextSdk.tagEventObj("Campaign_Clicked", map, context);
|
|
586
|
+
|
|
587
|
+
if (type.equalsIgnoreCase("lp")) {
|
|
588
|
+
Utility.openExternalLinkUrl(action.getActionUrl(), context);
|
|
589
|
+
} else {
|
|
590
|
+
Utility.openDeepLinkUrl(action.getActionUrl(), context);
|
|
591
|
+
}
|
|
592
|
+
return;
|
|
624
593
|
}
|
|
625
594
|
|
|
595
|
+
WritableMap params = Arguments.createMap();
|
|
596
|
+
String campaignStr = campaign.toJson().toString();
|
|
597
|
+
|
|
598
|
+
params.putString(EnumConstants.APPICE_PUSH_NOTIFICATION_ACTION_BUTTON_CLICKED.getValue(), campaignStr);
|
|
599
|
+
|
|
600
|
+
printLog("ActionPushDebug onActionButtonClicked", "action button clicked | campaign: " + campaignStr);
|
|
601
|
+
printLog("ActionPushDebug onActionButtonClicked", "isDeviceReadyFlag: " + isDeviceReadyFlag);
|
|
602
|
+
printLog("ActionPushDebug onActionButtonClicked", "queue size before send: " + pendingEventQueue.size());
|
|
603
|
+
|
|
604
|
+
AppIceReactPluginModule.sendEvent(EnumConstants.APPICE_PUSH_NOTIFICATION_ACTION_BUTTON_CLICKED.getValue(), params);
|
|
605
|
+
|
|
606
|
+
printLog("ActionPushDebug onActionButtonClicked", "queue size after send: " + pendingEventQueue.size());
|
|
607
|
+
|
|
626
608
|
} catch (Exception e) {
|
|
627
|
-
printLog("ActionPushDebug","
|
|
609
|
+
printLog("ActionPushDebug","Notification click handling failed: " + e.getMessage());
|
|
610
|
+
} finally {
|
|
611
|
+
// Executes even when an earlier branch returns.
|
|
612
|
+
if (pushClickData != null) {
|
|
613
|
+
pushClickData.deleteKeyFromIntent(intent, K_PAYLOAD);
|
|
614
|
+
}
|
|
628
615
|
}
|
|
629
616
|
}
|
|
630
|
-
}
|
|
617
|
+
}
|
|
@@ -46,9 +46,7 @@ public class CampaignCampsReceiver extends BroadcastReceiver {
|
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
48
|
printLog("CampaignEvent |","sendCallback |isHTMLInApp "+isHTMLInApp+"| campaignStr "+campaignStr);
|
|
49
|
-
|
|
50
49
|
if (isHTMLInApp){
|
|
51
|
-
|
|
52
50
|
if (Utility.isValidObject(campaignStr)) {
|
|
53
51
|
WritableMap params = Arguments.createMap();
|
|
54
52
|
params.putString(EnumConstants.APPICE_HTML_INAPP_NOTIFICATION_CLICKED.getValue(), campaignStr);
|
package/campaign.js
CHANGED
|
@@ -1,39 +1,11 @@
|
|
|
1
|
-
const { Linking, Platform } = require('react-native');
|
|
2
1
|
|
|
3
|
-
|
|
4
|
-
if (campaign && campaign._data) {
|
|
5
|
-
campaign = campaign._data;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
const url = campaign.actionUrl || campaign.acu || campaign.eurl;
|
|
9
|
-
const actionType = campaign.actionType || campaign.act || campaign.et;
|
|
10
|
-
|
|
11
|
-
if (!url || typeof url !== 'string') {
|
|
12
|
-
console.log('Error: URL is not provided.');
|
|
13
|
-
return;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const httpUrls = url.startsWith('http://') || url.startsWith('https://');
|
|
17
|
-
|
|
18
|
-
if (httpUrls) {
|
|
19
|
-
try {
|
|
20
|
-
if (Platform.OS === 'ios') {
|
|
21
|
-
campaign = normalizeCampaignPayloadForPlatform(campaign);
|
|
22
|
-
return campaign;
|
|
23
|
-
// iOS handle redirection on native side for landing page.
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
await Linking.openURL(url);
|
|
27
|
-
console.log(`Successfully opened URL: ${url}`);
|
|
28
|
-
} catch (error) {
|
|
29
|
-
console.log('Error while opening URL:', error?.message || error);
|
|
30
|
-
}
|
|
31
|
-
}
|
|
2
|
+
const { Platform } = require('react-native');
|
|
32
3
|
|
|
33
|
-
|
|
34
|
-
//
|
|
4
|
+
async function handleClickOnPush(campaign) {
|
|
5
|
+
// not removing this fucntion, as UBI is using it for IOS and IOS was returning campaign class object without checking anything
|
|
6
|
+
campaign = normalizeCampaignPayloadForPlatform(campaign);
|
|
35
7
|
return campaign;
|
|
36
|
-
|
|
8
|
+
|
|
37
9
|
}
|
|
38
10
|
|
|
39
11
|
|
|
@@ -73,7 +45,7 @@ class Campaign {
|
|
|
73
45
|
// if parse fails, keep eventData as-is (object expected)
|
|
74
46
|
data = eventData || {};
|
|
75
47
|
}
|
|
76
|
-
|
|
48
|
+
|
|
77
49
|
// Keep app-side listener thin by normalizing payload shape in campaign layer.
|
|
78
50
|
data = normalizeCampaignPayloadForPlatform(data);
|
|
79
51
|
const isLegacy = data && (data.camp_id || data.eurl || data.et || data.abt || data.act || data.acc);
|
|
@@ -81,6 +53,7 @@ class Campaign {
|
|
|
81
53
|
if (isLegacy) {
|
|
82
54
|
// Map legacy fields into _data in a normalized way
|
|
83
55
|
this._data.campId = data.campId || data.camp_id || '';
|
|
56
|
+
this._data.mid = data.mid || '';
|
|
84
57
|
this._data.actionType = data.actionType || data.et || data.act || '';
|
|
85
58
|
this._data.actionUrl = data.actionUrl || data.eurl || data.acu || '';
|
|
86
59
|
this._data.actionContent = data.actionContent || data.acc || '';
|
|
@@ -94,8 +67,9 @@ class Campaign {
|
|
|
94
67
|
this._data.customData = data.customData || data.cdata || data.custom || {};
|
|
95
68
|
|
|
96
69
|
// Actions mapping (legacy may have abt/act/acc/acu)
|
|
97
|
-
|
|
98
|
-
|
|
70
|
+
const actions = data.actions || data.actionButtons;
|
|
71
|
+
this._data.actions = Array.isArray(actions)
|
|
72
|
+
? actions.map((action) => ({
|
|
99
73
|
actionTitle: action.actionTitle || action.abt || '',
|
|
100
74
|
actionType: action.actionType || action.act || '',
|
|
101
75
|
actionContent: action.actionContent || action.acc || '',
|
|
@@ -117,6 +91,7 @@ class Campaign {
|
|
|
117
91
|
// ===========================
|
|
118
92
|
toCampaign(jsonData) {
|
|
119
93
|
this._data.campId = jsonData.campId || jsonData.camp_id || '';
|
|
94
|
+
this._data.mid = jsonData.mid || '';
|
|
120
95
|
this._data.nh = jsonData.title || jsonData.nh || '';
|
|
121
96
|
this._data.nd = jsonData.description || jsonData.nd || '';
|
|
122
97
|
this._data.end = jsonData.expandedDescription || jsonData.end || '';
|
|
@@ -131,8 +106,9 @@ class Campaign {
|
|
|
131
106
|
this._data.expiry = jsonData.expiry || 0;
|
|
132
107
|
this._data.customData = jsonData.customData || jsonData.custom || {};
|
|
133
108
|
// Actions array mapping
|
|
134
|
-
|
|
135
|
-
|
|
109
|
+
const actions = jsonData.actions || jsonData.actionButtons;
|
|
110
|
+
this._data.actions = Array.isArray(actions)
|
|
111
|
+
? actions.map(function (action) {
|
|
136
112
|
return {
|
|
137
113
|
actionTitle: action.actionTitle || action.abt || '',
|
|
138
114
|
actionType: action.actionType || action.act || '',
|
|
@@ -215,6 +191,9 @@ class Campaign {
|
|
|
215
191
|
getCampaignId() {
|
|
216
192
|
return this._data.campId || this._data.camp_id || '';
|
|
217
193
|
}
|
|
194
|
+
getMid() {
|
|
195
|
+
return this._data.mid || '';
|
|
196
|
+
}
|
|
218
197
|
getActionUrl() {
|
|
219
198
|
return this._data.actionUrl || this._data.acu || this._data.eurl || '';
|
|
220
199
|
}
|
|
@@ -243,6 +222,23 @@ class Campaign {
|
|
|
243
222
|
return this._data.selectedActionUrl;
|
|
244
223
|
}
|
|
245
224
|
|
|
225
|
+
// ===========================
|
|
226
|
+
// Campaign Click Tracking
|
|
227
|
+
// ===========================
|
|
228
|
+
async pushActionNotificationClicked(AppICE) {
|
|
229
|
+
const dataObj = {
|
|
230
|
+
campid: this.getCampaignId(),
|
|
231
|
+
abt: this.getSelectedActionTitle(),
|
|
232
|
+
mid: this.getMid()
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
try {
|
|
236
|
+
await AppICE.tagEvent('Campaign_Clicked', dataObj);
|
|
237
|
+
} catch (error) {
|
|
238
|
+
console.error('Campaign_Clicked tracking failed:', error);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
246
242
|
// Convert to JSON
|
|
247
243
|
toJSON() {
|
|
248
244
|
return this._data;
|
package/example/package.json
CHANGED
package/ios/AppIceReactPlugin.m
CHANGED
|
@@ -457,7 +457,7 @@ RCT_EXPORT_METHOD(synchronizeInbox:(int)timeout callback:(RCTResponseSenderBlock
|
|
|
457
457
|
@"messageExpiryTime": @(inboxMessage.messageExpiryTime),
|
|
458
458
|
@"campType": inboxMessage.campType,
|
|
459
459
|
@"expandedImage": inboxMessage.expandedImage, //messageExpandedImage replaced to expandedImage as discussed
|
|
460
|
-
@"
|
|
460
|
+
@"actions": actionButtons
|
|
461
461
|
};
|
|
462
462
|
} else {
|
|
463
463
|
return @{};
|
package/package.json
CHANGED