reactnative-plugin-appice 1.7.41 → 1.7.42

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.
@@ -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.37"
100
+ implementation "appice.io.android:sdk:2.6.38"
101
101
 
102
102
  //glide
103
103
  implementation "com.github.bumptech.glide:glide:4.11.0"
@@ -5,7 +5,7 @@
5
5
  <application>
6
6
  <service
7
7
  android:protectionLevel="signature"
8
- android:name="com.reactlibrary.NotificationEventService"
8
+ android:name="com.appice.react.NotificationEventService"
9
9
  android:exported="false">
10
10
  <intent-filter>
11
11
  <action android:name="com.appice.campaignEvent" />
@@ -14,7 +14,7 @@
14
14
 
15
15
  <receiver
16
16
  android:protectionLevel="signature"
17
- android:name="com.reactlibrary.CampaignCampsReceiver"
17
+ android:name="com.appice.react.CampaignCampsReceiver"
18
18
  android:exported="false">
19
19
  <intent-filter>
20
20
  <action android:name="com.appice.campaignEvent" />
@@ -35,7 +35,6 @@
35
35
  <action android:name="AppICE.Notification.FCM_Action" />
36
36
  <category android:name="android.intent.category.DEFAULT" />
37
37
  </intent-filter>
38
-
39
38
  </activity>
40
39
 
41
40
  <service
@@ -106,5 +105,14 @@
106
105
  <action android:name="io.appice.CAROUSELNOTIFICATIONFIRED" />
107
106
  </intent-filter>
108
107
  </receiver>
108
+
109
+ <receiver
110
+ android:name="semusi.ruleengine.pushmanager.AppICEMessageHandler"
111
+ android:exported="true"
112
+ android:permission="com.google.android.c2dm.permission.SEND" >
113
+ <intent-filter>
114
+ <action android:name="com.google.android.c2dm.intent.RECEIVE" />
115
+ </intent-filter>
116
+ </receiver>
109
117
  </application>
110
118
  </manifest>
@@ -421,50 +421,73 @@ public class AppICEUtils {
421
421
  }
422
422
 
423
423
  public static JSONObject toJSONObject(ReadableMap readableMap) {
424
- JSONObject jsonObject = new JSONObject();
425
-
426
424
  try {
425
+ JSONObject jsonObject = new JSONObject();
427
426
  ReadableMapKeySetIterator iterator = readableMap.keySetIterator();
428
-
429
427
  while (iterator.hasNextKey()) {
430
428
  String key = iterator.nextKey();
431
429
  ReadableType type = readableMap.getType(key);
432
-
433
430
  switch (type) {
434
431
  case Null:
435
- jsonObject.put(key, null);
432
+ jsonObject.put(key, JSONObject.NULL);
436
433
  break;
437
434
  case Boolean:
438
435
  jsonObject.put(key, readableMap.getBoolean(key));
439
436
  break;
440
- case Number:
441
- jsonObject.put(key, readableMap.getDouble(key));
437
+ case Number: {
438
+ double num = readableMap.getDouble(key);
439
+ if (num == (long) num) jsonObject.put(key, (long) num);
440
+ else jsonObject.put(key, num);
442
441
  break;
442
+ }
443
443
  case String:
444
444
  jsonObject.put(key, readableMap.getString(key));
445
445
  break;
446
446
  case Map:
447
447
  jsonObject.put(key, toJSONObject(readableMap.getMap(key)));
448
448
  break;
449
+ case Array:
450
+ jsonObject.put(key, toJSONArray(readableMap.getArray(key)));
451
+ break;
449
452
  }
450
453
  }
451
- }catch (Throwable t){
452
454
  return jsonObject;
455
+ }catch (Throwable t){
456
+ return null;
453
457
  }
454
-
455
- return jsonObject;
456
458
  }
457
459
 
458
- public static TransactionalCampaign toTransactionalCampaign(ReadableMap transactionalMap) {
459
- if (transactionalMap == null) return null;
460
- TransactionalCampaign transactionalCampaign = new TransactionalCampaign();
461
-
460
+ public static JSONArray toJSONArray(ReadableArray array) {
461
+ JSONArray jsonArray = new JSONArray();
462
462
  try {
463
- JSONObject root = toJSONObject(transactionalMap);
464
- transactionalCampaign.toTransactionalCampaign(root.toString());
465
- return transactionalCampaign;
466
- } catch (Throwable t) {
467
- Utility.handleSDKException("toTransactionalCampaign", t);
463
+ for (int i = 0; i < array.size(); i++) {
464
+ ReadableType type = array.getType(i);
465
+ switch (type) {
466
+ case Null:
467
+ jsonArray.put(JSONObject.NULL);
468
+ break;
469
+ case Boolean:
470
+ jsonArray.put(array.getBoolean(i));
471
+ break;
472
+ case Number: {
473
+ double num = array.getDouble(i);
474
+ if (num == (long) num) jsonArray.put((long) num);
475
+ else jsonArray.put(num);
476
+ break;
477
+ }
478
+ case String:
479
+ jsonArray.put(array.getString(i));
480
+ break;
481
+ case Map:
482
+ jsonArray.put(toJSONObject(array.getMap(i)));
483
+ break;
484
+ case Array:
485
+ jsonArray.put(toJSONArray(array.getArray(i)));
486
+ break;
487
+ }
488
+ }
489
+ return jsonArray;
490
+ }catch (Throwable t){
468
491
  return null;
469
492
  }
470
493
  }
@@ -23,6 +23,7 @@ import com.facebook.react.bridge.ReadableMap;
23
23
  import android.os.Handler;
24
24
  import semusi.activitysdk.Api;
25
25
  import semusi.activitysdk.ContextSdk;
26
+ import semusi.activitysdk.IAppICEDeviceRegisterCallback;
26
27
  import semusi.activitysdk.SdkConfig;
27
28
 
28
29
  import semusi.context.ui.appInbox.AppICEInboxMessage;
@@ -860,12 +861,28 @@ public class AppIceReactPluginModule extends ReactContextBaseJavaModule {
860
861
 
861
862
  //================================================
862
863
  @ReactMethod
863
- public void scheduleTransactionalCampaign(ReadableMap trasanctionalMap){
864
+ public void scheduleTransactionalCampaign(String transactionalStringPayload){
864
865
  Context context = getReactApplicationContext();
865
- TransactionalCampaign transactionalCampaign = AppICEUtils.toTransactionalCampaign(trasanctionalMap);
866
+ TransactionalCampaign transactionalCampaign = TransactionalCampaign.toTransactionalCampaign(transactionalStringPayload);
866
867
  ContextSdk.scheduleCampaign(transactionalCampaign, context);
867
868
  }
868
869
 
870
+ //=================================================
871
+ @ReactMethod
872
+ public void isDeviceRegistered(Callback callback) {
873
+ Context context = getReactApplicationContext();
874
+ try {
875
+ ContextSdk.isDeviceRegistered(context, new IAppICEDeviceRegisterCallback() {
876
+ @Override
877
+ public void isDeviceRegistered(boolean status) {
878
+ callback.invoke(status);
879
+ }
880
+ });
881
+ } catch (Throwable e) {
882
+ callback.invoke(e.getMessage());
883
+ }
884
+ }
885
+
869
886
  @Nullable
870
887
  @Override
871
888
  public Map<String, Object> getConstants() {
package/campaign.js CHANGED
@@ -1,9 +1,8 @@
1
+ const { Linking, Platform } = require('react-native');
1
2
 
2
- import { Linking, Platform } from 'react-native';
3
-
4
- const handleClickOnPush = async (campaign) => {
5
- const url = campaign.actionUrl;
6
- const actionType = campaign.actionType;
3
+ async function handleClickOnPush(campaign) {
4
+ const url = campaign.actionUrl || campaign.acu || campaign.eurl;
5
+ const actionType = campaign.actionType || campaign.act || campaign.et;
7
6
 
8
7
  if (!url || typeof url !== 'string') {
9
8
  console.log('Error: URL is not provided.');
@@ -30,10 +29,14 @@ const handleClickOnPush = async (campaign) => {
30
29
  // handle custom deeplink
31
30
  return campaign;
32
31
  }
33
- };
32
+ }
34
33
 
34
+ // ===============================
35
+ // Campaign (merged backward-compatible)
36
+ // ===============================
35
37
  class Campaign {
36
- constructor(eventData) {
38
+ constructor(eventData = {}) {
39
+ this._data = {};
37
40
  let data = eventData;
38
41
  try {
39
42
  if (typeof eventData === 'string') {
@@ -43,69 +46,169 @@ class Campaign {
43
46
  // if parse fails, keep eventData as-is (object expected)
44
47
  data = eventData || {};
45
48
  }
46
-
47
- const isIOS = Platform.OS === 'ios';
48
-
49
- if (isIOS) {
50
- this.campId = data.campId || '';
51
- } else {
52
- this.campId = data.camp_id || '';
49
+ const isLegacy = data && (data.camp_id || data.eurl || data.et || data.abt || data.act || data.acc);
50
+
51
+ if (isLegacy) {
52
+ // Map legacy fields into _data in a normalized way
53
+ this._data.campId = data.campId || data.camp_id || '';
54
+ this._data.actionType = data.actionType || data.et || data.act || '';
55
+ this._data.actionUrl = data.actionUrl || data.eurl || data.acu || '';
56
+ this._data.actionContent = data.actionContent || data.acc || '';
57
+ this._data.nh = data.title || data.nh || '';
58
+ this._data.nd = data.description || data.nd || '';
59
+ this._data.end = data.expandedDescription || data.end || this._data.nd || '';
60
+ this._data.ct = data.campType || data.t || '';
61
+ this._data.selectedIndex = data.selectedIndex || 0;
62
+ this._data.ln = data.language || data.lang || data.ln || '';
63
+ this._data.replyText = data.replyText || '';
64
+ this._data.customData = data.customData || data.cdata || data.custom || {};
65
+
66
+ // Actions mapping (legacy may have abt/act/acc/acu)
67
+ this._data.actions = Array.isArray(data.actions)
68
+ ? data.actions.map((action) => ({
69
+ actionTitle: action.actionTitle || action.abt || '',
70
+ actionType: action.actionType || action.act || '',
71
+ actionContent: action.actionContent || action.acc || '',
72
+ actionUrl: action.actionUrl || action.acu || ''
73
+ }))
74
+ : [];
75
+
76
+ const selected = data.selectedAction || {};
77
+ this._data.selectedActionTitle = selected.actionTitle || selected.abt || '';
78
+ this._data.selectedActionType = selected.actionType || selected.act || '';
79
+ this._data.selectedActionUrl = selected.actionUrl || selected.acu || '';
80
+ } else if (Object.keys(data || {}).length > 0) {
81
+ this.toCampaign(data);
53
82
  }
83
+ }
54
84
 
55
- this.actionType = data.et || '';
56
- this.actionUrl = data.eurl || '';
57
- this.actionContent = data.actionContent || '';
58
- this.title = data.nh || '';
59
- this.description = data.nd || '';
60
- this.campType = data.t || '';
61
- this.selectedIndex = data.selectedIndex || 0;
62
- this.language = data.language || data.lang || '';
63
- this.replyText = data.replyText || '';
64
- this.customData = data.customData || data.cdata || {};
65
-
66
- const selected = data.selectedAction || {};
67
- this.selectedAction = selected;
68
-
69
- this.actions = Array.isArray(data.actions)
70
- ? data.actions.map((action) => {
85
+ // ===========================
86
+ // Map JSON data to internal _data
87
+ // ===========================
88
+ toCampaign(jsonData) {
89
+ this._data.campId = jsonData.campId || jsonData.camp_id || '';
90
+ this._data.nh = jsonData.title || jsonData.nh || '';
91
+ this._data.nd = jsonData.description || jsonData.nd || '';
92
+ this._data.end = jsonData.expandedDescription || jsonData.end || '';
93
+ this._data.ct = jsonData.campType || jsonData.ct || '';
94
+ this._data.ctype = jsonData.ctype || '';
95
+ this._data.dtype = jsonData.dtype || '';
96
+ this._data.actionType = jsonData.actionType || jsonData.act || '';
97
+ this._data.actionUrl = jsonData.actionUrl || jsonData.acu || '';
98
+ this._data.selectedIndex = jsonData.selectedIndex || 0;
99
+ this._data.ln = jsonData.language || jsonData.ln || '';
100
+ this._data.replyText = jsonData.replyText || '';
101
+ this._data.expiry = jsonData.expiry || 0;
102
+ this._data.customData = jsonData.customData || jsonData.custom || {};
103
+ // Actions array mapping
104
+ this._data.actions = Array.isArray(jsonData.actions)
105
+ ? jsonData.actions.map(function (action) {
71
106
  return {
72
107
  actionTitle: action.actionTitle || action.abt || '',
73
108
  actionType: action.actionType || action.act || '',
74
- actionContent: action.actionContent || action.acc || '',
75
109
  actionUrl: action.actionUrl || action.acu || ''
76
110
  };
77
111
  })
78
112
  : [];
113
+ // Selected action mapping
114
+ const sel = jsonData.selectedAction || {};
115
+ this._data.selectedActionTitle = sel.actionTitle || sel.abt || '';
116
+ this._data.selectedActionType = sel.actionType || sel.act || '';
117
+ this._data.selectedActionUrl = sel.actionUrl || sel.acu || '';
118
+ }
79
119
 
80
- if (isIOS) {
81
- this.selectedActionTitle = selected.actionTitle || '';
82
- this.selectedActionType = selected.actionType || '';
83
- this.actionContent = selected.actionContent || '';
84
- this.selectedActionUrl = selected.actionUrl || '';
85
- } else {
86
- this.selectedActionTitle = selected.abt || '';
87
- this.selectedActionType = selected.act || '';
88
- this.actionContent = selected.acc || '';
89
- this.selectedActionUrl = selected.acu || '';
90
- }
120
+ // ===========================
121
+ // Setters (normalized keys)
122
+ // ===========================
123
+ set setTitle(v) {
124
+ this._data['nh'] = v;
125
+ }
126
+ set setDescription(v) {
127
+ this._data['nd'] = v;
128
+ }
129
+ set setExpandedDescription(v) {
130
+ this._data['end'] = v;
131
+ }
132
+ set setCampaignType(v) {
133
+ this._data['ct'] = v;
134
+ }
135
+ set setDeliveryType(v) {
136
+ this._data['dtype'] = v;
137
+ }
138
+ set setSelectedIndex(v) {
139
+ this._data['selectedIndex'] = v;
140
+ }
141
+ set setLanguage(v) {
142
+ this._data['ln'] = v;
143
+ }
144
+ set setExpiry(v) {
145
+ this._data['expiry'] = v;
146
+ }
147
+ set setActions(v) {
148
+ this._data['actions'] = v;
149
+ }
150
+ set setCustomData(v) {
151
+ this._data['customData'] = v;
91
152
  }
92
153
 
93
- // Getter methods for campaign properties
94
- getCampaignId() {
95
- return this.campId;
154
+ // ===========================
155
+ // Getters (normalized keys)
156
+ // ===========================
157
+ get getTitle() {
158
+ return this._data['nh'];
159
+ }
160
+ get getDescription() {
161
+ return this._data['nd'];
162
+ }
163
+ get getCampaignType() {
164
+ return this._data['ct'];
165
+ }
166
+ get getDeliveryType() {
167
+ return this._data['dtype'];
168
+ }
169
+ get getSelectedIndex() {
170
+ return this._data['selectedIndex'];
171
+ }
172
+ get getLanguage() {
173
+ return this._data['ln'];
174
+ }
175
+ get getExpiry() {
176
+ return this._data['expiry'];
177
+ }
178
+ get getActions() {
179
+ return this._data['actions'];
180
+ }
181
+ get getCustomData() {
182
+ return this._data['customData'];
96
183
  }
97
184
 
185
+ getCampaignId() {
186
+ return this._data.campId || this._data.camp_id || '';
187
+ }
98
188
  getActionUrl() {
99
- return this.actionUrl;
189
+ return this._data.actionUrl || this._data.acu || this._data.eurl || '';
100
190
  }
101
-
102
191
  getActionType() {
103
- return this.actionType;
192
+ return this._data.actionType || this._data.act || this._data.et || '';
104
193
  }
105
-
106
194
  getCustomData() {
107
- return this.customData;
195
+ return this._data.customData || this._data.cdata || {};
196
+ }
197
+
198
+ // Custom data getter
199
+ getCustomDataValue(key) {
200
+ return this._data.customData ? this._data.customData[key] || '' : '';
201
+ }
202
+
203
+ // Convert to JSON
204
+ toJSON() {
205
+ return this._data;
108
206
  }
109
207
  }
110
208
 
111
- export { Campaign, handleClickOnPush };
209
+ // Export compatibility: provide both direct export and named members
210
+ module.exports = Campaign;
211
+ module.exports.Campaign = Campaign;
212
+ module.exports.handleClickOnPush = handleClickOnPush;
213
+ export default Campaign;
214
+ export { handleClickOnPush };
package/example/App.js CHANGED
@@ -6,26 +6,61 @@
6
6
  * @flow strict-local
7
7
  */
8
8
 
9
- import React from 'react';
10
- import { Alert,
11
- Text,
12
- Button,
13
- View,
14
- AppState
15
- } from 'react-native';
16
- // Define a type for the props parameter
17
- type EventProps = {
18
- [key: string]: string; // all values are strings
19
- };
9
+ import React, {useState} from 'react';
10
+ import {
11
+ Alert,
12
+ Text,
13
+ Button,
14
+ View,
15
+ AppState,
16
+ TextInput,
17
+ StyleSheet,
18
+ Platform,
19
+ ScrollView,
20
+ } from 'react-native';
21
+
20
22
  import { getInboxMessages, getMessageCounts, setUser, updatedInboxMessage } from './ancilliary';
21
- import { handleUrl,receiveDeepLink } from './offerIdhandler';
23
+
22
24
  const AppICE = require('reactnative-plugin-appice');
23
- const { Campaign, handleClickOnPush } = require('reactnative-plugin-appice/campaign');
24
- const HelloWorldApp = () => {
25
25
 
26
+ let Campaign;
27
+ try {
28
+ const campaignModule = require('reactnative-plugin-appice/campaign');
29
+ Campaign = campaignModule.Campaign || campaignModule.default || campaignModule;
30
+ } catch (e) {
31
+ console.log('Campaign load error:', e);
32
+ }
33
+
34
+ let TransactionalCampaign;
35
+ try {
36
+ const transactionalModule = require('reactnative-plugin-appice/TransactionalCampaign');
37
+ TransactionalCampaign = transactionalModule.TransactionalCampaign || transactionalModule.default || transactionalModule;
38
+ } catch (e) {
39
+ console.log('TransactionalCampaign load error:', e);
40
+ }
41
+
42
+ let handleClickOnPush;
43
+ try {
44
+ const campaignModule = require('reactnative-plugin-appice/campaign');
45
+ handleClickOnPush = campaignModule.handleClickOnPush;
46
+ } catch (e) {
47
+ console.log('handleClickOnPush load error:', e);
48
+ }
49
+
50
+ console.log('TransactionalCampaign available:', !!TransactionalCampaign);
51
+ console.log('Campaign available:', !!Campaign);
52
+ const HelloWorldApp = () => {
53
+ const [campaignId, setCampaignId] = useState('1234');
54
+ const [campaignTitle, setCampaignTitle] = useState('Sample Title');
55
+ const [campaignDesc, setCampaignDesc] = useState('Sample description');
56
+ const [campaignLang, setCampaignLang] = useState('en');
57
+ const [campaignUser, setCampaignUser] = useState('');
58
+ const [appLang, setAppLang] = useState('en');
59
+ const [deviceLang, setDeviceLang] = useState('en');
60
+ const [customTopic, setCustomTopic] = useState('Login');
26
61
 
27
62
 
28
- const certs: never[] = [];
63
+ const certs = [];
29
64
  if (AppICE) {
30
65
  console.log('AppICE is available');
31
66
  AppICE.preInitialise();
@@ -58,14 +93,61 @@ const HelloWorldApp = () => {
58
93
 
59
94
 
60
95
  return (
61
- <View
62
- style={{
63
- flex: 1,
64
- justifyContent: 'center',
65
- alignItems: 'center',
66
- marginBottom: 10,
67
- }}>
68
- <Text>AppICE React Demo</Text>
96
+ <ScrollView contentContainerStyle={styles.container} keyboardShouldPersistTaps="handled">
97
+ <Text style={styles.title}>AppICE React Demo</Text>
98
+ <View style={styles.inputRow}>
99
+ <TextInput
100
+ style={styles.input}
101
+ placeholder="Campaign Id"
102
+ value={campaignId}
103
+ onChangeText={setCampaignId}
104
+ />
105
+ <TextInput
106
+ style={styles.input}
107
+ placeholder="Lang"
108
+ value={campaignLang}
109
+ onChangeText={setCampaignLang}
110
+ />
111
+ </View>
112
+ <TextInput
113
+ style={styles.inputFull}
114
+ placeholder="Title"
115
+ value={campaignTitle}
116
+ onChangeText={setCampaignTitle}
117
+ />
118
+ <TextInput
119
+ style={styles.inputFull}
120
+ placeholder="Description"
121
+ value={campaignDesc}
122
+ onChangeText={setCampaignDesc}
123
+ multiline
124
+ />
125
+ <TextInput
126
+ style={styles.inputFull}
127
+ placeholder="User (optional)"
128
+ value={campaignUser}
129
+ onChangeText={setCampaignUser}
130
+ />
131
+ <View style={styles.inputRow}>
132
+ <TextInput
133
+ style={styles.input}
134
+ placeholder="App Language"
135
+ value={appLang}
136
+ onChangeText={setAppLang}
137
+ />
138
+ <TextInput
139
+ style={styles.input}
140
+ placeholder="Device Language"
141
+ value={deviceLang}
142
+ onChangeText={setDeviceLang}
143
+ />
144
+ </View>
145
+ <TextInput
146
+ style={styles.inputFull}
147
+ placeholder="Custom Topic"
148
+ value={customTopic}
149
+ onChangeText={setCustomTopic}
150
+ />
69
151
  <Button onPress={sendEvent} title="Send Event" color="#841584" />
70
152
  <Button onPress={setSampleUserID} title="setUserID" color="#841584" />
71
153
  <Button onPress={getUserId} title="getUserId" color="#841584" />
@@ -77,12 +159,82 @@ const HelloWorldApp = () => {
77
159
  <Button onPress={getMessageCount} title="getMessageCount" color="#841584" />
78
160
  <Button onPress={updateInboxMessage} title="updateInbox" color="#841584" />
79
161
  <Button onPress={synchronizeInbox} title="synchronizeInbox" color="#841584" />
162
+ <Button onPress={() => {
163
+ if (!AppICE) { Alert.alert('AppICE not available'); return; }
164
+ AppICE.setAppLanguage(appLang);
165
+ Alert.alert('setAppLanguage', appLang);
166
+ }} title="setAppLanguage" color="#6a51ae" />
167
+ <Button onPress={() => {
168
+ if (!AppICE) { Alert.alert('AppICE not available'); return; }
169
+ AppICE.setDeviceLanguage(deviceLang);
170
+ Alert.alert('setDeviceLanguage', deviceLang);
171
+ }} title="setDeviceLanguage" color="#6a51ae" />
172
+ <Button onPress={() => {
173
+ if (!AppICE) { Alert.alert('AppICE not available'); return; }
174
+ AppICE.setCustomTopic(customTopic);
175
+ Alert.alert('setCustomTopic', customTopic);
176
+ }} title="setCustomTopic" color="#6a51ae" />
177
+ <Button onPress={() => {
178
+ if (!AppICE) { Alert.alert('AppICE not available'); return; }
179
+ if (AppICE.removeCustomTopic) {
180
+ AppICE.removeCustomTopic(customTopic);
181
+ Alert.alert('removeCustomTopic', customTopic);
182
+ } else {
183
+ Alert.alert('removeCustomTopic not supported');
184
+ }
185
+ }} title="removeCustomTopic" color="#6a51ae" />
186
+ <Button onPress={() => {
187
+ if (!AppICE) { Alert.alert('AppICE not available'); return; }
188
+ try {
189
+ AppICE.isDeviceRegistered((err, registered) => {
190
+ if (err) {
191
+ console.log('isDeviceRegistered error', err);
192
+ Alert.alert('isDeviceRegistered', 'Error: ' + String(err));
193
+ return;
194
+ }
195
+ console.log('[isDeviceRegistered] ', registered);
196
+ Alert.alert('isDeviceRegistered', String(registered));
197
+ if (registered) {
198
+ // ensure languages/topics set when registered
199
+ if (AppICE.setAppLanguage) AppICE.setAppLanguage(appLang);
200
+ if (AppICE.setDeviceLanguage) AppICE.setDeviceLanguage(deviceLang);
201
+ }
202
+ });
203
+ } catch (e) {
204
+ console.log('isDeviceRegistered call failed', e);
205
+ Alert.alert('isDeviceRegistered', 'Call failed');
206
+ }
207
+ }} title="isDeviceRegistered" color="#2b8a3e" />
80
208
  <Button onPress={getUserDetails} title="getUserDetails" color="#841584" />
81
209
  <Button onPress={getUserData} title="getUserData" color="#841584" />
82
210
  <Button onPress={getCampaignById} title="getCampaignById" color="#841584" />
83
211
  <Button onPress={getCampaigns} title="getCampaigns" color="#841584" />
84
212
 
85
- </View>
213
+ <View style={styles.spacer} />
214
+ <Button
215
+ title="Send Random Test Campaign"
216
+ onPress={() => {
217
+ const payload = generateTestCampaign();
218
+ console.log('Sending test campaign:', payload);
219
+ scheduleTransactionalCampaign(payload);
220
+ }}
221
+ color="#0b79d0"
222
+ />
223
+ <Button
224
+ title="Schedule Transactional Campaign"
225
+ onPress={() =>
226
+ scheduleTransactionalCampaign({
227
+ Id: campaignId,
228
+ Title: campaignTitle,
229
+ Desc: campaignDesc,
230
+ Lang: campaignLang,
231
+ User: campaignUser || undefined,
232
+ })
233
+ }
234
+ color="#2a9d8f"
235
+ />
236
+
237
+ </ScrollView>
86
238
  );
87
239
 
88
240
  }
@@ -304,7 +456,7 @@ const getUserData = () => {
304
456
  AppICE.tagEvent(event, segment, flush)
305
457
  }
306
458
 
307
- // getCampaigns
459
+ // getCampaigns
308
460
 
309
461
  const getCampaigns = () => {
310
462
 
@@ -314,12 +466,12 @@ const getCampaigns = () => {
314
466
  console.log('Campaigns:', campaigns);
315
467
 
316
468
  campaigns.forEach((campaign) => {
317
-
469
+
318
470
  console.log('getCampaigns of Campaign ID:', campaign.getCampaignId());
319
471
  console.log('Action URL is :', campaign.getActionUrl());
320
472
  console.log('Action Type is :', campaign.getActionType());
321
473
  console.log('Custom Data is :', campaign.getCustomData());
322
-
474
+
323
475
  });
324
476
  });
325
477
  };
@@ -337,5 +489,98 @@ const getCampaignById = () => {
337
489
  });
338
490
  };
339
491
 
492
+ const isIOSDevice = () => Platform.OS === 'ios';
493
+ const generateUniqueNum = () => Date.now();
494
+ const getExpiryTime = () => Math.floor(Date.now() / 1000) + 3600; // +1 hour (epoch seconds)
495
+
496
+ const generateTestCampaign = () => {
497
+ const id = `test-${Date.now()}`;
498
+ return {
499
+ Id: id,
500
+ Title: `Test Title ${Math.floor(Math.random() * 1000)}`,
501
+ Desc: `This is a test description for ${id}`,
502
+ Lang: Math.random() > 0.5 ? 'en' : 'ar-AE',
503
+ User: `testUser${Math.floor(Math.random() * 9999)}`,
504
+ };
505
+ };
506
+
507
+ const scheduleTransactionalCampaign = (campaignData) => {
508
+ try {
509
+ if (!TransactionalCampaign || !Campaign) {
510
+ console.log('TransactionalCampaign or Campaign classes not available');
511
+ return;
512
+ }
513
+
514
+ const transactionalCampaign = new TransactionalCampaign();
515
+ const campaign = new Campaign();
516
+
517
+ transactionalCampaign.setCampId = campaignData.Id;
518
+ transactionalCampaign.setPlatform = isIOSDevice() ? 'iOS' : 'Android';
519
+ transactionalCampaign.setName = '';
520
+ transactionalCampaign.setCustom = { requestId: generateUniqueNum().toString() };
521
+ transactionalCampaign.setDelay = 0;
522
+ transactionalCampaign.setUsers = campaignData.User ? [campaignData.User] : [];
523
+
524
+ campaign.setTitle = campaignData.Title;
525
+ campaign.setDescription = campaignData.Desc;
526
+ campaign.setExpandedDescription = campaignData.Desc;
527
+ campaign.setCampaignType = 'PUSH';
528
+ campaign.setDeliveryType = 'Push';
529
+ campaign.setLanguage = campaignData.Lang;
530
+ campaign.setExpiry = getExpiryTime();
531
+ campaign.setActions = [];
532
+
533
+ transactionalCampaign.addPayload(campaign);
534
+ const finalPayload = transactionalCampaign.toRequestPayload();
535
+ console.log('scheduleTransactionalCampaign payload:', finalPayload);
536
+
537
+ AppICE.scheduleTransactionalCampaign(finalPayload);
538
+ } catch (error) {
539
+ console.log('appiceutil::scheduleTransactionalCampaign exception: ' + error);
540
+ }
541
+ };
542
+
543
+
544
+ const styles = StyleSheet.create({
545
+ container: {
546
+ flexGrow: 1,
547
+ padding: 16,
548
+ alignItems: 'stretch',
549
+ justifyContent: 'flex-start',
550
+ paddingBottom: Platform.OS === 'android' ? 56 : 32,
551
+ backgroundColor: '#fff',
552
+ },
553
+ title: {
554
+ fontSize: 20,
555
+ fontWeight: '600',
556
+ marginBottom: 12,
557
+ textAlign: 'center',
558
+ },
559
+ inputRow: {
560
+ flexDirection: 'row',
561
+ justifyContent: 'space-between',
562
+ gap: 8,
563
+ marginBottom: 8,
564
+ },
565
+ input: {
566
+ flex: 1,
567
+ borderWidth: 1,
568
+ borderColor: '#ddd',
569
+ padding: 8,
570
+ marginRight: 8,
571
+ borderRadius: 4,
572
+ },
573
+ inputFull: {
574
+ borderWidth: 1,
575
+ borderColor: '#ddd',
576
+ padding: 8,
577
+ marginBottom: 8,
578
+ borderRadius: 4,
579
+ },
580
+ spacer: {
581
+ height: 12,
582
+ },
583
+ });
584
+
340
585
 
341
586
  export default HelloWorldApp;
@@ -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.40",
20
+ "reactnative-plugin-appice": "1.7.42",
21
21
  "react-native-mmkv": "2.12.2"
22
22
  },
23
23
  "devDependencies": {
package/index.js CHANGED
@@ -435,34 +435,6 @@ var AppICEReact = {
435
435
  AppIceReactPlugin.isDeviceReady(isActive);
436
436
  },
437
437
 
438
- //===============================================
439
- // language setting
440
- //===============================================
441
-
442
- setAppLanguage: function (language) {
443
- if (Platform.OS === 'android') {
444
- AppIceReactPlugin.setAppLanguage(language);
445
- }
446
- },
447
-
448
- subscribeAppLanguage: function (language) {
449
- if (Platform.OS === 'android') {
450
- AppIceReactPlugin.subscribeAppLanguage(language);
451
- }
452
- },
453
-
454
- setDeviceLanguage: function (language) {
455
- if (Platform.OS === 'android') {
456
- AppIceReactPlugin.setDeviceLanguage(language);
457
- }
458
- },
459
-
460
- subscribeDeviceLanguage: function (language) {
461
- if (Platform.OS === 'android') {
462
- AppIceReactPlugin.subscribeDeviceLanguage(language);
463
- }
464
- },
465
-
466
438
  /*===============
467
439
  synchronizeData
468
440
  ================*/
@@ -523,6 +495,60 @@ var AppICEReact = {
523
495
  });
524
496
  },
525
497
 
498
+ //===============================================
499
+ // Topic Push
500
+ //===============================================
501
+
502
+ isDeviceRegistered: function (callback) {
503
+ callWithCallback('isDeviceRegistered', null, callback);
504
+ },
505
+
506
+ setAppLanguage: function (language) {
507
+
508
+ AppIceReactPlugin.setAppLanguage(language);
509
+
510
+ },
511
+
512
+ getAppLanguage: function (callback) {
513
+ callWithCallback('getAppLanguage', null, callback);
514
+ },
515
+
516
+ setDeviceLanguage: function (language) {
517
+
518
+ AppIceReactPlugin.setDeviceLanguage(language);
519
+
520
+ },
521
+
522
+ getDeviceLanguage: function (callback) {
523
+ callWithCallback('getDeviceLanguage', null, callback);
524
+ },
525
+
526
+ subscribeAppLanguage: function (language) {
527
+ if (Platform.OS === 'android') {
528
+ AppIceReactPlugin.subscribeAppLanguage(language);
529
+ }
530
+ },
531
+
532
+ subscribeDeviceLanguage: function (language) {
533
+ if (Platform.OS === 'android') {
534
+ AppIceReactPlugin.subscribeDeviceLanguage(language);
535
+ }
536
+ },
537
+
538
+ // -------- Custom Topics --------
539
+ setCustomTopic: function (topic) {
540
+ AppIceReactPlugin.setCustomTopic(topic);
541
+ },
542
+
543
+ removeCustomTopic: function (topic) {
544
+ AppIceReactPlugin.removeCustomTopic(topic);
545
+ },
546
+
547
+ scheduleTransactionalCampaign: function (payloadJson) {
548
+ AppIceReactPlugin.scheduleTransactionalCampaign(payloadJson);
549
+
550
+ },
551
+
526
552
  //campaign enum
527
553
  CampaignType,
528
554
  };
@@ -6,6 +6,7 @@
6
6
  #import "AppICEInboxMessage.h"
7
7
  #import <UserNotifications/UserNotifications.h>
8
8
  #import "Campaign.h"
9
+ #import "TransactionalCampaign.h"
9
10
  @implementation AppIceReactPlugin
10
11
 
11
12
  static BOOL isAppInitialized = NO;
@@ -668,6 +669,61 @@ RCT_EXPORT_METHOD(getCampaignById:(NSString *)campID callback:(RCTResponseSender
668
669
  [self returnResult:formatedCampaign withCallback:callback andError:nil];
669
670
  }
670
671
 
672
+ #pragma mark - Topic Push (Language / Platform / Custom Topics)
673
+
674
+ RCT_EXPORT_METHOD(setAppLanguage:(NSString *)lang)
675
+ {
676
+ [[appICE sharedInstance] setAppLanguage:lang];
677
+ }
678
+
679
+ RCT_EXPORT_METHOD(getAppLanguage:(RCTResponseSenderBlock)callback)
680
+ {
681
+ NSString *value = [[appICE sharedInstance] getAppLanguage];
682
+ [self returnResult:value withCallback:callback andError:nil];
683
+ }
684
+
685
+ RCT_EXPORT_METHOD(setDeviceLanguage:(NSString *)lang)
686
+ {
687
+ [[appICE sharedInstance] setDeviceLanguage:lang];
688
+ }
689
+
690
+ RCT_EXPORT_METHOD(getDeviceLanguage:(RCTResponseSenderBlock)callback)
691
+ {
692
+ NSString *value = [[appICE sharedInstance] getDeviceLanguage];
693
+ [self returnResult:value withCallback:callback andError:nil];
694
+ }
695
+
696
+ RCT_EXPORT_METHOD(setCustomTopic:(NSString *)topic)
697
+ {
698
+ [[appICE sharedInstance] setCustomTopic:topic];
699
+ }
700
+
701
+ RCT_EXPORT_METHOD(removeCustomTopic:(NSString *)topic)
702
+ {
703
+ [[appICE sharedInstance] removeCustomTopic:topic];
704
+ }
705
+
706
+ RCT_EXPORT_METHOD(isDeviceRegistered:(RCTResponseSenderBlock)callback)
707
+ {
708
+ if (!callback) return;
709
+
710
+ [[appICE sharedInstance] isDeviceRegistered:^(BOOL isRegistered) {
711
+ callback(@[[NSNull null], @(isRegistered)]);
712
+ }];
713
+ }
714
+
715
+ RCT_EXPORT_METHOD(scheduleTransactionalCampaign:(NSString *)payloadJson)
716
+ {
717
+ @try {
718
+ if (payloadJson.length == 0) return;
719
+ TransactionalCampaign *tCampaign = [TransactionalCampaign toTransactionalCampaign:payloadJson];
720
+ if (tCampaign) {
721
+ [[appICE sharedInstance] scheduleCampaign:tCampaign];
722
+ }
723
+ } @catch (NSException *exception) {
724
+
725
+ }
726
+ }
671
727
 
672
728
  - (void)returnResult:(id)result withCallback:(RCTResponseSenderBlock)callback andError:(NSString *)error {
673
729
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "reactnative-plugin-appice",
3
- "version": "1.7.41",
3
+ "version": "1.7.42",
4
4
  "description": "appICE React Native SDK",
5
5
  "main": "index.js",
6
6
  "files": [
@@ -23,7 +23,7 @@ Pod::Spec.new do |s|
23
23
  s.requires_arc = true
24
24
 
25
25
  s.dependency "React"
26
- s.dependency "AppICE-IOS-SDK", "1.8.19"
26
+ s.dependency "AppICE-IOS-SDK", "1.8.20"
27
27
  # ...
28
28
  # s.dependency "..."
29
29
  end