react-native-acoustic-mobile-push-inbox-beta 3.9.36 → 3.9.38
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/src/main/assets/mce/plugins/rn-plugin-inbox.json +20 -0
- package/android/src/main/java/co/acoustic/mobile/push/plugin/inbox/RNAcousticMobilePushInboxModule.java +361 -552
- package/android/src/main/java/co/acoustic/mobile/push/plugin/inbox/RNPushNotificationInboxCustomAction.java +329 -0
- package/package.json +2 -2
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright © 2019, 2025 Acoustic, L.P. All rights reserved.
|
|
3
|
+
*
|
|
4
|
+
* NOTICE: This file contains material that is confidential and proprietary to
|
|
5
|
+
* Acoustic, L.P. and/or other developers. No license is granted under any intellectual or
|
|
6
|
+
* industrial property rights of Acoustic, L.P. except as may be provided in an agreement with
|
|
7
|
+
* Acoustic, L.P. Any unauthorized copying or distribution of content from this file is
|
|
8
|
+
* prohibited.
|
|
9
|
+
*/
|
|
10
|
+
package co.acoustic.mobile.push.plugin.inbox;
|
|
11
|
+
|
|
12
|
+
import android.app.Activity;
|
|
13
|
+
import android.content.Context;
|
|
14
|
+
import android.content.Intent;
|
|
15
|
+
import android.os.Build;
|
|
16
|
+
import android.os.Bundle;
|
|
17
|
+
import android.view.ViewGroup;
|
|
18
|
+
import android.view.ViewParent;
|
|
19
|
+
import android.view.Window;
|
|
20
|
+
import android.widget.FrameLayout;
|
|
21
|
+
import android.widget.RelativeLayout;
|
|
22
|
+
|
|
23
|
+
import com.facebook.react.ReactApplication;
|
|
24
|
+
import com.facebook.react.ReactInstanceManager;
|
|
25
|
+
import com.facebook.react.ReactNativeHost;
|
|
26
|
+
import com.facebook.react.ReactRootView;
|
|
27
|
+
import com.facebook.react.bridge.ReactApplicationContext;
|
|
28
|
+
import com.facebook.react.bridge.ReactMethod;
|
|
29
|
+
|
|
30
|
+
import co.acoustic.mobile.push.sdk.api.OperationCallback;
|
|
31
|
+
import co.acoustic.mobile.push.sdk.api.OperationResult;
|
|
32
|
+
import co.acoustic.mobile.push.sdk.api.message.MessageProcessor;
|
|
33
|
+
import co.acoustic.mobile.push.sdk.api.message.MessageSync;
|
|
34
|
+
import co.acoustic.mobile.push.sdk.api.notification.MceNotificationAction;
|
|
35
|
+
import co.acoustic.mobile.push.sdk.api.notification.NotificationDetails;
|
|
36
|
+
|
|
37
|
+
import java.lang.ref.WeakReference;
|
|
38
|
+
import java.util.ArrayList;
|
|
39
|
+
import java.util.Iterator;
|
|
40
|
+
import java.util.Map;
|
|
41
|
+
import java.util.Objects;
|
|
42
|
+
|
|
43
|
+
import org.json.JSONArray;
|
|
44
|
+
import org.json.JSONException;
|
|
45
|
+
import org.json.JSONObject;
|
|
46
|
+
|
|
47
|
+
import co.acoustic.mobile.push.sdk.notification.ActionImpl;
|
|
48
|
+
import co.acoustic.mobile.push.sdk.plugin.inbox.InboxEvents;
|
|
49
|
+
import co.acoustic.mobile.push.sdk.plugin.inbox.InboxMessageProcessor;
|
|
50
|
+
import co.acoustic.mobile.push.sdk.plugin.inbox.InboxMessageReference;
|
|
51
|
+
import co.acoustic.mobile.push.sdk.plugin.inbox.RichContent;
|
|
52
|
+
import co.acoustic.mobile.push.sdk.util.Logger;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* A custom action handler for RNPushNotificationInbox, responsible for processing inbox messages and navigating to the inbox screen when a push notification is clicked.
|
|
56
|
+
*/
|
|
57
|
+
public class RNPushNotificationInboxCustomAction implements MceNotificationAction {
|
|
58
|
+
final String TAG = "RNPushNotificationInboxCustomAction";
|
|
59
|
+
|
|
60
|
+
private static WeakReference<ReactApplicationContext> weakReactContext;
|
|
61
|
+
private static String inboxActionModule;
|
|
62
|
+
private RelativeLayout relativeLayout = null;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Default constructor required by MceNotificationAction interface
|
|
66
|
+
*/
|
|
67
|
+
public RNPushNotificationInboxCustomAction() {
|
|
68
|
+
Logger.d(TAG, "RNPushNotificationInboxCustomAction initialized");
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Constructor with context and module name
|
|
73
|
+
* @param reactContext The React application context
|
|
74
|
+
* @param inboxActionModule The inbox action module name
|
|
75
|
+
*/
|
|
76
|
+
public RNPushNotificationInboxCustomAction(ReactApplicationContext reactContext, String inboxActionModule) {
|
|
77
|
+
if (reactContext != null) {
|
|
78
|
+
weakReactContext = new WeakReference<>(reactContext);
|
|
79
|
+
}
|
|
80
|
+
RNPushNotificationInboxCustomAction.inboxActionModule = inboxActionModule;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Safely get the React context from WeakReference
|
|
85
|
+
* @return The ReactApplicationContext or null if not available
|
|
86
|
+
*/
|
|
87
|
+
private ReactApplicationContext getReactContext() {
|
|
88
|
+
return weakReactContext != null ? weakReactContext.get() : null;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Clean up resources to prevent memory leaks
|
|
93
|
+
*/
|
|
94
|
+
public static void clearContext() {
|
|
95
|
+
if (weakReactContext != null) {
|
|
96
|
+
weakReactContext.clear();
|
|
97
|
+
weakReactContext = null;
|
|
98
|
+
}
|
|
99
|
+
inboxActionModule = null;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Inbox SDK callback to handle custom actions triggered from the inbox
|
|
104
|
+
* @param context The application context
|
|
105
|
+
* @param type The type of action triggered
|
|
106
|
+
* @param name The name of the action triggered
|
|
107
|
+
* @param attribution The attribution data for the action
|
|
108
|
+
* @param mailingId The ID of the mailing that triggered the action
|
|
109
|
+
* @param payload The payload data associated with the action
|
|
110
|
+
* @param fromNotification boolean indicating whether the action was triggered from a notification
|
|
111
|
+
*/
|
|
112
|
+
@Override
|
|
113
|
+
public void handleAction(final Context context, final String type, final String name, final String attribution, final String mailingId, final Map<String, String> payload, final boolean fromNotification) {
|
|
114
|
+
Logger.i(TAG, "currentActivity is ");
|
|
115
|
+
|
|
116
|
+
Activity currentActivity = Objects.requireNonNull(getReactContext()).getCurrentActivity();
|
|
117
|
+
if (currentActivity == null) {
|
|
118
|
+
Logger.i(TAG, "Can't find activity, starting");
|
|
119
|
+
|
|
120
|
+
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
|
|
121
|
+
Intent it = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
|
|
122
|
+
context.sendBroadcast(it);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
Intent intent = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName());
|
|
126
|
+
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
127
|
+
context.startActivity(intent);
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
final Activity activity = currentActivity;
|
|
132
|
+
final InboxMessageReference messageReference = new InboxMessageReference(payload.get("value"), payload.get(InboxMessageReference.INBOX_MESSAGE_ID_KEY));
|
|
133
|
+
if (messageReference.hasReference()) {
|
|
134
|
+
final RichContent inboxMessage = messageReference.getMessageFromDb(getReactContext());
|
|
135
|
+
if (inboxMessage == null) {
|
|
136
|
+
Logger.d(TAG, "Inbox message not found");
|
|
137
|
+
InboxMessageProcessor.addMessageToLoad(messageReference);
|
|
138
|
+
MessageSync.syncMessages(getReactContext(), new OperationCallback<MessageSync.SyncReport>() {
|
|
139
|
+
@Override
|
|
140
|
+
public void onSuccess(MessageSync.SyncReport syncReport, OperationResult result) {
|
|
141
|
+
Logger.i(TAG, "Downloaded messages");
|
|
142
|
+
InboxMessageProcessor.Report report = null;
|
|
143
|
+
for (MessageProcessor.ProcessReport processReport : syncReport.getReports()) {
|
|
144
|
+
if (processReport instanceof InboxMessageProcessor.Report) {
|
|
145
|
+
report = (InboxMessageProcessor.Report) processReport;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
for (int i = 0; i < report.getNewMessages().size(); i++) {
|
|
149
|
+
RichContent message = report.getNewMessages().get(i);
|
|
150
|
+
if (message.getMessageId().equals(messageReference.getInboxMessageId())) {
|
|
151
|
+
Logger.i(TAG, "Downloaded message");
|
|
152
|
+
final RichContent msg = message;
|
|
153
|
+
activity.runOnUiThread(new Runnable() {
|
|
154
|
+
@Override
|
|
155
|
+
public void run() {
|
|
156
|
+
internalHideInbox();
|
|
157
|
+
|
|
158
|
+
showInboxMessage(msg, activity);
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
if (fromNotification) {
|
|
162
|
+
InboxEvents.sendInboxNotificationOpenedEvent(context, new ActionImpl(type, name, payload), attribution, mailingId);
|
|
163
|
+
}
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
Logger.e(TAG, "Could not find downloaded message");
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
@Override
|
|
171
|
+
public void onFailure(MessageSync.SyncReport syncReport, OperationResult result) {
|
|
172
|
+
Logger.e(TAG, "Could not download message");
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
} else {
|
|
176
|
+
activity.runOnUiThread(new Runnable() {
|
|
177
|
+
@Override
|
|
178
|
+
public void run() {
|
|
179
|
+
internalHideInbox();
|
|
180
|
+
showInboxMessage(inboxMessage, activity);
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
if (fromNotification) {
|
|
184
|
+
InboxEvents.sendInboxNotificationOpenedEvent(context, new ActionImpl(type, name, payload), attribution, mailingId);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
@Override
|
|
191
|
+
public void init(Context context, JSONObject jsonObject) {
|
|
192
|
+
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
@Override
|
|
196
|
+
public void update(Context context, JSONObject jsonObject) {
|
|
197
|
+
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
@Override
|
|
201
|
+
public boolean shouldDisplayNotification(Context context, NotificationDetails notificationDetails, Bundle bundle) {
|
|
202
|
+
return true;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
@Override
|
|
206
|
+
public boolean shouldSendDefaultEvent(Context context) {
|
|
207
|
+
return false;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
@ReactMethod
|
|
211
|
+
public void hideInbox() {
|
|
212
|
+
final Activity activity = Objects.requireNonNull(getReactContext()).getCurrentActivity();
|
|
213
|
+
if (activity == null) {
|
|
214
|
+
Logger.e(TAG, "Can't find activity");
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
activity.runOnUiThread(new Runnable() {
|
|
219
|
+
@Override
|
|
220
|
+
public void run() {
|
|
221
|
+
internalHideInbox();
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
// Needs to be run on the main thread.
|
|
228
|
+
private void internalHideInbox() {
|
|
229
|
+
if (this.relativeLayout != null) {
|
|
230
|
+
ViewParent parent = this.relativeLayout.getParent();
|
|
231
|
+
if (parent instanceof ViewGroup) {
|
|
232
|
+
ViewGroup group = (ViewGroup) parent;
|
|
233
|
+
group.removeView(this.relativeLayout);
|
|
234
|
+
} else {
|
|
235
|
+
Logger.e(TAG, "InApp Parent is not a ViewGroup!");
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
this.relativeLayout = null;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// Needs to be run on the main thread.
|
|
242
|
+
private void showInboxMessage(RichContent inboxMessage, Activity activity) {
|
|
243
|
+
if (inboxActionModule == null) {
|
|
244
|
+
Logger.e(TAG, "inbox action module is not registered");
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
this.relativeLayout = new RelativeLayout(getReactContext());
|
|
249
|
+
relativeLayout.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.FILL_PARENT, RelativeLayout.LayoutParams.FILL_PARENT));
|
|
250
|
+
RelativeLayout.LayoutParams viewLayout = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.FILL_PARENT, RelativeLayout.LayoutParams.FILL_PARENT);
|
|
251
|
+
|
|
252
|
+
viewLayout.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
|
|
253
|
+
|
|
254
|
+
ReactApplication application = (ReactApplication) activity.getApplication();
|
|
255
|
+
ReactNativeHost reactNativeHost = application.getReactNativeHost();
|
|
256
|
+
ReactInstanceManager reactInstanceManager = reactNativeHost.getReactInstanceManager();
|
|
257
|
+
|
|
258
|
+
Bundle messageBundle = new Bundle();
|
|
259
|
+
messageBundle.putLong("sendDate", inboxMessage.getSendDate().getTime());
|
|
260
|
+
messageBundle.putLong("expirationDate", inboxMessage.getExpirationDate().getTime());
|
|
261
|
+
messageBundle.putBoolean("isDeleted", inboxMessage.getIsDeleted());
|
|
262
|
+
messageBundle.putBoolean("isRead", inboxMessage.getIsRead());
|
|
263
|
+
messageBundle.putBoolean("isExpired", inboxMessage.getIsExpired());
|
|
264
|
+
messageBundle.putString("templateName", inboxMessage.getTemplate());
|
|
265
|
+
messageBundle.putString("attribution", inboxMessage.getAttribution());
|
|
266
|
+
messageBundle.putString("mailingId", inboxMessage.getMessageId());
|
|
267
|
+
messageBundle.putString("inboxMessageId", inboxMessage.getMessageId());
|
|
268
|
+
messageBundle.putString("richContentId", inboxMessage.getContentId());
|
|
269
|
+
|
|
270
|
+
try {
|
|
271
|
+
JSONObject content = inboxMessage.getContent();
|
|
272
|
+
if (content != null) {
|
|
273
|
+
messageBundle.putBundle("content", convertJsonObjectToBundle(content));
|
|
274
|
+
}
|
|
275
|
+
} catch (Exception ex) {
|
|
276
|
+
Logger.d(TAG, "Couldn't convert inbox json content", ex);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
Bundle initialProperties = new Bundle();
|
|
280
|
+
initialProperties.putBundle("message", messageBundle);
|
|
281
|
+
|
|
282
|
+
ReactRootView reactRootView = new ReactRootView(getReactContext());
|
|
283
|
+
reactRootView.setLayoutParams(viewLayout);
|
|
284
|
+
reactRootView.startReactApplication(reactInstanceManager, inboxActionModule, initialProperties);
|
|
285
|
+
relativeLayout.addView(reactRootView);
|
|
286
|
+
|
|
287
|
+
Window window = activity.getWindow();
|
|
288
|
+
FrameLayout.LayoutParams relativeLayoutParams = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.FILL_PARENT, FrameLayout.LayoutParams.FILL_PARENT);
|
|
289
|
+
window.addContentView(relativeLayout, relativeLayoutParams);
|
|
290
|
+
|
|
291
|
+
RNAcousticMobilePushInboxModule.relativeLayout = relativeLayout;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
public Bundle convertJsonObjectToBundle(JSONObject jsonObject) throws JSONException {
|
|
295
|
+
Bundle bundle = new Bundle();
|
|
296
|
+
Iterator<String> jsonIterator = jsonObject.keys();
|
|
297
|
+
while (jsonIterator.hasNext()) {
|
|
298
|
+
String key = jsonIterator.next();
|
|
299
|
+
Object value = jsonObject.get(key);
|
|
300
|
+
|
|
301
|
+
if (value instanceof Boolean) {
|
|
302
|
+
Boolean booleanValue = (Boolean) value;
|
|
303
|
+
bundle.putShort(key, (short) (booleanValue.booleanValue() ? 1 : 0));
|
|
304
|
+
} else if (value instanceof Integer) {
|
|
305
|
+
Integer integerValue = (Integer) value;
|
|
306
|
+
bundle.putFloat(key, integerValue.floatValue());
|
|
307
|
+
} else if (value instanceof Long) {
|
|
308
|
+
Long longValue = (Long) value;
|
|
309
|
+
bundle.putFloat(key, longValue.floatValue());
|
|
310
|
+
} else if (value instanceof Double) {
|
|
311
|
+
Double doubleValue = (Double) value;
|
|
312
|
+
bundle.putFloat(key, doubleValue.floatValue());
|
|
313
|
+
} else if (value instanceof String) {
|
|
314
|
+
bundle.putString(key, (String) value);
|
|
315
|
+
} else if (value instanceof JSONObject) {
|
|
316
|
+
bundle.putBundle(key, convertJsonObjectToBundle((JSONObject) value));
|
|
317
|
+
} else if (value instanceof JSONArray) {
|
|
318
|
+
ArrayList<String> array = new ArrayList<String>();
|
|
319
|
+
JSONArray jsonArray = (JSONArray) value;
|
|
320
|
+
for (int i = 0; i < jsonArray.length(); i++) {
|
|
321
|
+
Object arrayValue = jsonArray.get(i);
|
|
322
|
+
array.add(arrayValue.toString());
|
|
323
|
+
}
|
|
324
|
+
bundle.putStringArrayList(key, array);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
return bundle;
|
|
328
|
+
}
|
|
329
|
+
}
|
package/package.json
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
],
|
|
10
10
|
"author": "Acoustic, L.P.",
|
|
11
11
|
"peerDependencies": {
|
|
12
|
-
"react-native-acoustic-mobile-push-beta": "3.9.
|
|
12
|
+
"react-native-acoustic-mobile-push-beta": "3.9.38"
|
|
13
13
|
},
|
|
14
14
|
"description": "BETA: Acoustic Mobile Push Inbox Content Plugin",
|
|
15
15
|
"main": "index.js",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"directory": "plugins/react-native-acoustic-mobile-push-inbox",
|
|
19
19
|
"url": "https://github.com/go-acoustic/Acoustic-Mobile-Push-React-Native"
|
|
20
20
|
},
|
|
21
|
-
"version": "3.9.
|
|
21
|
+
"version": "3.9.38",
|
|
22
22
|
"dependencies": {
|
|
23
23
|
"plist": "^3.0.1",
|
|
24
24
|
"xml2js": "^0.4.19",
|