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.
@@ -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.36"
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.36",
21
+ "version": "3.9.38",
22
22
  "dependencies": {
23
23
  "plist": "^3.0.1",
24
24
  "xml2js": "^0.4.19",