Skip to content

Commit 03a0df3

Browse files
authored
Merge pull request #340 from Iterable/inbox
[MOB-4356] react native inbox
2 parents bede61b + 7f28f7b commit 03a0df3

29 files changed

+3633
-1676
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -48,5 +48,6 @@ Config.d.ts
4848
Config.sample.d.ts
4949

5050
package-lock.json
51+
.vscode/launch.json
5152

5253
coverage/

android/src/main/java/com/iterable/reactnative/RNIterableAPIModule.java

+67-5
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import com.facebook.react.bridge.WritableMap;
2222
import com.facebook.react.modules.core.DeviceEventManagerModule;
2323
import com.facebook.react.modules.core.RCTNativeAppEventEmitter;
24+
import com.iterable.iterableapi.InboxSessionManager;
2425
import com.iterable.iterableapi.IterableAction;
2526
import com.iterable.iterableapi.IterableActionContext;
2627
import com.iterable.iterableapi.IterableApi;
@@ -32,21 +33,22 @@
3233
import com.iterable.iterableapi.IterableInAppCloseAction;
3334
import com.iterable.iterableapi.IterableInAppHandler;
3435
import com.iterable.iterableapi.IterableInAppLocation;
36+
import com.iterable.iterableapi.IterableInAppManager;
3537
import com.iterable.iterableapi.IterableInAppMessage;
38+
import com.iterable.iterableapi.IterableInboxSession;
3639
import com.iterable.iterableapi.IterableLogger;
3740
import com.iterable.iterableapi.IterableUrlHandler;
3841
import com.iterable.iterableapi.RNIterableInternal;
3942

40-
4143
import org.json.JSONArray;
4244
import org.json.JSONException;
4345
import org.json.JSONObject;
4446

47+
import java.util.List;
4548
import java.util.concurrent.CountDownLatch;
4649
import java.util.concurrent.TimeUnit;
4750

48-
public class RNIterableAPIModule extends ReactContextBaseJavaModule implements IterableUrlHandler, IterableCustomActionHandler, IterableInAppHandler, IterableAuthHandler {
49-
51+
public class RNIterableAPIModule extends ReactContextBaseJavaModule implements IterableUrlHandler, IterableCustomActionHandler, IterableInAppHandler, IterableAuthHandler, IterableInAppManager.Listener {
5052
private final ReactApplicationContext reactContext;
5153
private static String TAG = "RNIterableAPIModule";
5254

@@ -58,6 +60,8 @@ public class RNIterableAPIModule extends ReactContextBaseJavaModule implements I
5860
private CountDownLatch authHandlerCallbackLatch;
5961
private String passedAuthToken = null;
6062

63+
private final InboxSessionManager sessionManager = new InboxSessionManager();
64+
6165
public RNIterableAPIModule(ReactApplicationContext reactContext) {
6266
super(reactContext);
6367
this.reactContext = reactContext;
@@ -94,6 +98,9 @@ public void initializeWithApiKey(String apiKey, ReadableMap configReadableMap, S
9498

9599
IterableApi.initialize(reactContext, apiKey, configBuilder.build());
96100
IterableApi.getInstance().setDeviceAttribute("reactNativeSDKVersion", version);
101+
102+
IterableApi.getInstance().getInAppManager().addListener(this);
103+
97104
// TODO: Figure out what the error cases are and handle them appropriately
98105
// This is just here to match the TS types and let the JS thread know when we are done initializing
99106
promise.resolve(true);
@@ -285,8 +292,8 @@ public void handleAppLink(String uri, Promise promise) {
285292
// ---------------------------------------------------------------------------------------
286293
// endregion
287294

288-
// region Track APIs
289295
// ---------------------------------------------------------------------------------------
296+
// region Track APIs
290297
@ReactMethod
291298
public void trackInAppOpen(String messageId, @Nullable Integer location) {
292299
IterableInAppMessage message = RNIterableInternal.getMessageById(messageId);
@@ -345,6 +352,7 @@ public void trackInAppClose(String messageId, Integer location, Integer source,
345352

346353
IterableApi.getInstance().trackInAppClose(inAppMessage, clickedUrl, closeAction, inAppCloseLocation);
347354
}
355+
348356
// ---------------------------------------------------------------------------------------
349357
// endregion
350358

@@ -371,6 +379,18 @@ public void getInAppMessages(Promise promise) {
371379
}
372380
}
373381

382+
@ReactMethod
383+
public void getInboxMessages(Promise promise) {
384+
IterableLogger.d(TAG, "getInboxMessages");
385+
try {
386+
JSONArray inboxMessageJsonArray = Serialization.serializeInAppMessages(IterableApi.getInstance().getInAppManager().getInboxMessages());
387+
promise.resolve(Serialization.convertJsonToArray(inboxMessageJsonArray));
388+
} catch (JSONException e) {
389+
IterableLogger.e(TAG, e.getLocalizedMessage());
390+
promise.reject("", "Failed to fetch messages with error " + e.getLocalizedMessage());
391+
}
392+
}
393+
374394
@ReactMethod
375395
public void setInAppShowResponse(Integer number) {
376396
IterableLogger.printInfo();
@@ -414,6 +434,34 @@ public Intent getMainActivityIntent(Context context) {
414434
// ---------------------------------------------------------------------------------------
415435
// endregion
416436

437+
// ---------------------------------------------------------------------------------------
438+
// region Inbox In-App Session Tracking APIs
439+
440+
@ReactMethod
441+
public void startSession(ReadableArray visibleRows) {
442+
List<IterableInboxSession.Impression> serializedRows = Serialization.impressionsFromReadableArray(visibleRows);
443+
444+
sessionManager.startSession(serializedRows);
445+
}
446+
447+
@ReactMethod
448+
public void endSession() {
449+
sessionManager.endSession();
450+
}
451+
452+
@ReactMethod
453+
public void updateVisibleRows(ReadableArray visibleRows) {
454+
List<IterableInboxSession.Impression> serializedRows = Serialization.impressionsFromReadableArray(visibleRows);
455+
456+
sessionManager.updateVisibleRows(serializedRows);
457+
}
458+
459+
// ---------------------------------------------------------------------------------------
460+
// endregion
461+
462+
// ---------------------------------------------------------------------------------------
463+
// region Private Serialization Functions
464+
417465
private static Integer[] readableArrayToIntegerArray(ReadableArray array) {
418466
if (array == null) {
419467
return null;
@@ -440,6 +488,9 @@ private static JSONObject optSerializedDataFields(ReadableMap dataFields) {
440488
return dataFieldsJson;
441489
}
442490

491+
// ---------------------------------------------------------------------------------------
492+
// endregion
493+
443494
// ---------------------------------------------------------------------------------------
444495
// region IterableSDK callbacks
445496

@@ -528,6 +579,9 @@ public void removeListeners(Integer count) {
528579
// ---------------------------------------------------------------------------------------
529580
// endregion
530581

582+
// ---------------------------------------------------------------------------------------
583+
// region Misc Bridge Functions
584+
531585
@ReactMethod
532586
public void passAlongAuthToken(String authToken) {
533587
passedAuthToken = authToken;
@@ -541,11 +595,19 @@ public void sendEvent(@NonNull String eventName, @Nullable Object eventData) {
541595
reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit(eventName, eventData);
542596
}
543597

598+
@Override
599+
public void onInboxUpdated() {
600+
sendEvent(EventName.receivedIterableInboxChanged.name(), null);
601+
}
602+
603+
// ---------------------------------------------------------------------------------------
604+
// endregion
544605
}
545606

546607
enum EventName {
547608
handleUrlCalled,
548609
handleCustomActionCalled,
549610
handleInAppCalled,
550-
handleAuthCalled
611+
handleAuthCalled,
612+
receivedIterableInboxChanged
551613
}

android/src/main/java/com/iterable/reactnative/Serialization.java

+28
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import com.iterable.iterableapi.IterableInAppHandler;
2121
import com.iterable.iterableapi.IterableInAppLocation;
2222
import com.iterable.iterableapi.IterableInAppMessage;
23+
import com.iterable.iterableapi.IterableInboxSession;
2324
import com.iterable.iterableapi.IterableLogger;
2425
import com.iterable.iterableapi.RNIterableInternal;
2526

@@ -223,6 +224,33 @@ static JSONObject actionContextToJson(IterableActionContext iterableActionContex
223224
return actionContextJson;
224225
}
225226

227+
static IterableInboxSession.Impression inboxImpressionFromMap(JSONObject impressionMap) throws JSONException {
228+
return new IterableInboxSession.Impression(impressionMap.getString("messageId"),
229+
impressionMap.getBoolean("silentInbox"),
230+
impressionMap.optInt("displayCount", 0),
231+
(float) impressionMap.optDouble("duration", 0)
232+
);
233+
}
234+
235+
static List<IterableInboxSession.Impression> impressionsFromReadableArray(ReadableArray array) {
236+
ArrayList<IterableInboxSession.Impression> list = new ArrayList<>();
237+
238+
try {
239+
JSONArray impressionJsonArray = convertArrayToJson(array);
240+
241+
for (int i = 0; i < impressionJsonArray.length(); i++) {
242+
JSONObject impressionObj = impressionJsonArray.getJSONObject(i);
243+
list.add(inboxImpressionFromMap(impressionObj));
244+
}
245+
} catch (JSONException e) {
246+
IterableLogger.e(TAG, "Failed converting to JSONObject");
247+
}
248+
249+
return list;
250+
}
251+
252+
253+
226254
// ---------------------------------------------------------------------------------------
227255
// region React Native JSON conversion methods
228256
// obtained from https://gist.github.com/viperwarp/2beb6bbefcc268dee7ad

ios/RNIterableAPI/RNIterableAPI.m

+12-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77

88
@interface RCT_EXTERN_REMAP_MODULE(RNIterableAPI, ReactIterableAPI, NSObject)
99

10-
// MARK: - SDK Functions
10+
// MARK: - Native SDK Functions
11+
1112
RCT_EXTERN_METHOD(initializeWithApiKey: (nonnull NSString *) apiKey
1213
config: (nonnull NSDictionary *) config
1314
version: (nonnull NSString *) version
@@ -20,7 +21,7 @@ @interface RCT_EXTERN_REMAP_MODULE(RNIterableAPI, ReactIterableAPI, NSObject)
2021
version: (nonnull NSString *) version
2122
resolver: (RCTPromiseResolveBlock) resolve
2223
rejecter: (RCTPromiseRejectBlock) reject)
23-
24+
2425
RCT_EXTERN_METHOD(setEmail: (NSString *) email)
2526

2627
RCT_EXTERN_METHOD(getEmail: (RCTPromiseResolveBlock) resolve
@@ -32,6 +33,7 @@ @interface RCT_EXTERN_REMAP_MODULE(RNIterableAPI, ReactIterableAPI, NSObject)
3233
rejecter: (RCTPromiseRejectBlock) reject)
3334

3435
// MARK: - Iterable API Request Functions
36+
3537
RCT_EXTERN_METHOD(disableDeviceForCurrentUser)
3638

3739
RCT_EXTERN_METHOD(setInAppShowResponse: (nonnull NSNumber *) inAppShowResponse)
@@ -120,6 +122,14 @@ @interface RCT_EXTERN_REMAP_MODULE(RNIterableAPI, ReactIterableAPI, NSObject)
120122

121123
RCT_EXTERN_METHOD(setAutoDisplayPaused: (BOOL) paused)
122124

125+
// MARK: - SDK Inbox Session Tracking Functions
126+
127+
RCT_EXTERN_METHOD(startSession: (nonnull NSArray *) visibleRows)
128+
129+
RCT_EXTERN_METHOD(endSession)
130+
131+
RCT_EXTERN_METHOD(updateVisibleRows: (nonnull NSArray *) visibleRows)
132+
123133
// MARK: - SDK Auth Manager Functions
124134

125135
RCT_EXTERN_METHOD(passAlongAuthToken: (NSString *) authToken)

0 commit comments

Comments
 (0)