Skip to content

Commit 0826725

Browse files
authored
Merge pull request #83 from Iterable/MOB-2028-jwt-bindings
Mob 2028 jwt bindings
2 parents 2bdece7 + be516d6 commit 0826725

File tree

8 files changed

+254
-139
lines changed

8 files changed

+254
-139
lines changed

Iterable-React-Native-SDK.podspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,6 @@ Pod::Spec.new do |s|
2424

2525
s.swift_version = '5.2'
2626

27-
s.dependency 'Iterable-iOS-SDK', '~> 6.2.11'
27+
s.dependency 'Iterable-iOS-SDK', '~> 6.2.12'
2828
s.dependency 'React'
2929
end

android/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,5 @@ def getModuleVersion() {
2222

2323
dependencies {
2424
implementation 'com.facebook.react:react-native:+'
25-
api 'com.iterable:iterableapi:3.2.6'
25+
api 'com.iterable:iterableapi:3.2.7'
2626
}

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

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import com.iterable.iterableapi.IterableAction;
2121
import com.iterable.iterableapi.IterableActionContext;
2222
import com.iterable.iterableapi.IterableApi;
23+
import com.iterable.iterableapi.IterableAuthHandler;
2324
import com.iterable.iterableapi.IterableConfig;
2425
import com.iterable.iterableapi.IterableCustomActionHandler;
2526
import com.iterable.iterableapi.IterableAttributionInfo;
@@ -39,21 +40,27 @@
3940
import java.util.concurrent.CountDownLatch;
4041
import java.util.concurrent.TimeUnit;
4142

42-
public class RNIterableAPIModule extends ReactContextBaseJavaModule implements IterableUrlHandler, IterableCustomActionHandler, IterableInAppHandler {
43+
public class RNIterableAPIModule extends ReactContextBaseJavaModule implements IterableUrlHandler, IterableCustomActionHandler, IterableInAppHandler, IterableAuthHandler {
4344

4445
private final ReactApplicationContext reactContext;
4546
private static String TAG = "RNIterableAPIModule";
4647

4748
private InAppResponse inAppResponse = InAppResponse.SHOW;
4849

49-
//A CountDownlatch. This helps decide whether to handle the inapp in Default way by waiting for JS to respond in runtime.
50+
//A CountDownLatch. This helps decide whether to handle the in-app in Default way by waiting for JS to respond in runtime.
5051
private CountDownLatch jsCallBackLatch;
5152

53+
private CountDownLatch authHandlerCallbackLatch;
54+
private String passedAuthToken = null;
55+
5256
public RNIterableAPIModule(ReactApplicationContext reactContext) {
5357
super(reactContext);
5458
this.reactContext = reactContext;
5559
}
5660

61+
// ---------------------------------------------------------------------------------------
62+
// region IterableSDK calls
63+
5764
@Override
5865
public String getName() {
5966
return "RNIterableAPI";
@@ -76,6 +83,10 @@ public void initializeWithApiKey(String apiKey, ReadableMap configReadableMap, S
7683
configBuilder.setInAppHandler(this);
7784
}
7885

86+
if (configReadableMap.hasKey("authHandlerPresent") && configReadableMap.getBoolean("authHandlerPresent") == true) {
87+
configBuilder.setAuthHandler(this);
88+
}
89+
7990
IterableApi.initialize(reactContext, apiKey, configBuilder.build());
8091
IterableApi.getInstance().setDeviceAttribute("reactNativeSDKVersion", version);
8192
}
@@ -264,6 +275,9 @@ public void handleAppLink(String uri, Promise promise) {
264275
promise.resolve(IterableApi.getInstance().handleAppLink(uri));
265276
}
266277

278+
// ---------------------------------------------------------------------------------------
279+
// endregion
280+
267281
// region Track APIs
268282
// ---------------------------------------------------------------------------------------
269283
@ReactMethod
@@ -422,9 +436,34 @@ public boolean handleIterableURL(@NonNull Uri uri, @NonNull IterableActionContex
422436
return false;
423437
}
424438

439+
@Override
440+
public String onAuthTokenRequested() {
441+
IterableLogger.printInfo();
442+
443+
try {
444+
authHandlerCallbackLatch = new CountDownLatch(1);
445+
sendEvent(EventName.handleAuthCalled.name(), null);
446+
authHandlerCallbackLatch.await(30, TimeUnit.SECONDS);
447+
authHandlerCallbackLatch = null;
448+
return passedAuthToken;
449+
} catch (InterruptedException e) {
450+
IterableLogger.e(TAG, "auth handler module failed");
451+
return null;
452+
}
453+
}
454+
425455
// ---------------------------------------------------------------------------------------
426456
// endregion
427457

458+
@ReactMethod
459+
public void passAlongAuthToken(String authToken) {
460+
passedAuthToken = authToken;
461+
462+
if (authHandlerCallbackLatch != null) {
463+
authHandlerCallbackLatch.countDown();
464+
}
465+
}
466+
428467
public void sendEvent(@NonNull String eventName, @Nullable Object eventData) {
429468
reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit(eventName, eventData);
430469
}
@@ -434,5 +473,6 @@ public void sendEvent(@NonNull String eventName, @Nullable Object eventData) {
434473
enum EventName {
435474
handleUrlCalled,
436475
handleCustomActionCalled,
437-
handleInAppCalled
476+
handleInAppCalled,
477+
handleAuthCalled
438478
}

ios/RNIterableAPI/RNIterableAPI.m

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,4 +109,8 @@ @interface RCT_EXTERN_REMAP_MODULE(RNIterableAPI, ReactIterableAPI, NSObject)
109109

110110
RCT_EXTERN_METHOD(setAutoDisplayPaused: (BOOL) paused)
111111

112+
// MARK: - SDK Auth Manager Functions
113+
114+
RCT_EXTERN_METHOD(passAlongAuthToken: (NSString *) authToken)
115+
112116
@end

ios/RNIterableAPI/ReactIterableAPI.swift

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ class ReactIterableAPI: RCTEventEmitter {
2525
case handleUrlCalled
2626
case handleCustomActionCalled
2727
case handleInAppCalled
28+
case handleAuthCalled
2829
}
2930

3031
override func supportedEvents() -> [String]! {
@@ -67,6 +68,10 @@ class ReactIterableAPI: RCTEventEmitter {
6768
iterableConfig.inAppDelegate = self
6869
}
6970

71+
if let authHandlerPresent = configDict["authHandlerPresent"] as? Bool, authHandlerPresent {
72+
iterableConfig.authDelegate = self
73+
}
74+
7075
DispatchQueue.main.async {
7176
IterableAPI.initialize(apiKey: apiKey, launchOptions: launchOptions, config: iterableConfig)
7277
IterableAPI.setDeviceAttribute(name: "reactNativeSDKVersion", value: version)
@@ -292,7 +297,7 @@ class ReactIterableAPI: RCTEventEmitter {
292297
}
293298
}
294299

295-
// MARK: InApp Manager methods
300+
// MARK: In-App Manager methods
296301
@objc(getInAppMessages:rejecter:)
297302
func getInAppMessages(resolver: RCTPromiseResolveBlock, rejecter: RCTPromiseRejectBlock) {
298303
ITBInfo()
@@ -385,6 +390,15 @@ class ReactIterableAPI: RCTEventEmitter {
385390

386391
IterableAPI.inAppManager.isAutoDisplayPaused = autoDisplayPaused
387392
}
393+
394+
@objc(passAlongAuthToken:)
395+
func passAlong(authToken: String?) {
396+
ITBInfo()
397+
398+
passedAuthToken = authToken
399+
400+
authHandlerSemaphore.signal()
401+
}
388402

389403
// MARK: Private
390404
private var shouldEmit = false
@@ -394,6 +408,9 @@ class ReactIterableAPI: RCTEventEmitter {
394408
private var inAppShowResponse = InAppShowResponse.show
395409
private var inAppHandlerSemaphore = DispatchSemaphore(value: 0)
396410

411+
private var passedAuthToken: String?
412+
private var authHandlerSemaphore = DispatchSemaphore(value: 0)
413+
397414
private func createLaunchOptions() -> [UIApplication.LaunchOptionsKey: Any]? {
398415
guard let bridge = bridge else {
399416
return nil
@@ -493,3 +510,23 @@ extension ReactIterableAPI: IterableInAppDelegate {
493510
}
494511
}
495512

513+
extension ReactIterableAPI: IterableAuthDelegate {
514+
func onAuthTokenRequested(completion: @escaping AuthTokenRetrievalHandler) {
515+
ITBInfo()
516+
517+
DispatchQueue.global(qos: .userInitiated).async {
518+
self.sendEvent(withName: EventName.handleAuthCalled.rawValue,
519+
body: nil)
520+
521+
let authTokenRetrievalResult = self.authHandlerSemaphore.wait(timeout: .now() + 30.0)
522+
523+
if authTokenRetrievalResult == .success {
524+
ITBInfo("authTokenRetrieval successful")
525+
526+
DispatchQueue.main.async {
527+
completion(self.passedAuthToken)
528+
}
529+
}
530+
}
531+
}
532+
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@iterable/react-native-sdk",
3-
"version": "1.0.13",
3+
"version": "1.0.14",
44
"description": "Iterable SDK for React Native.",
55
"main": "./js/index.js",
66
"types": "./js/index.d.ts",

ts/Iterable.ts

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ const RNIterableAPI = NativeModules.RNIterableAPI
1414
const RNEventEmitter = new NativeEventEmitter(RNIterableAPI)
1515

1616
/**
17-
* Enum representing the source of IteraleAction.
17+
* Enum representing the source of IterableAction.
1818
*/
1919
enum IterableActionSource {
2020
push = 0,
@@ -31,7 +31,6 @@ enum IterableLogLevel {
3131
error = 3
3232
}
3333

34-
3534
/**
3635
Iterable Configuration Object. Use this when initializing the API.
3736
*/
@@ -42,39 +41,55 @@ class IterableConfig {
4241
* To view your existing integrations, navigate to Settings > Mobile Apps
4342
*/
4443
pushIntegrationName?: string
44+
4545
/**
4646
* When set to true, IterableSDK will automatically register and deregister notification tokens.
4747
*/
4848
autoPushRegistration = true
49+
4950
/**
5051
* When set to true, it will check for deferred deep links on first time app launch after installation from the App Store.
5152
*/
5253
checkForDeferredDeeplink = false
54+
5355
/**
5456
* How many seconds to wait before showing the next in-app, if there are more than one present
5557
*/
5658
inAppDisplayInterval: number = 30.0
59+
5760
/**
5861
* How many seconds to wait before showing the next in-app, if there are more than one present
5962
*/
6063
urlHandler?: (url: string, context: IterableActionContext) => boolean
64+
6165
/**
6266
* How to handle IterableActions which are other than 'openUrl'
6367
*/
6468
customActionHandler?: (action: IterableAction, context: IterableActionContext) => boolean
69+
6570
/**
6671
* Implement this protocol to override default in-app behavior.
6772
* By default, every single in-app will be shown as soon as it is available.
6873
* If more than 1 in-app is available, we show the first.
6974
*/
7075
inAppHandler?: (message: IterableInAppMessage) => IterableInAppShowResponse
7176

77+
/**
78+
* The handler with which your own calls to your backend containing the auth token happen
79+
*/
80+
authHandler?: () => Promise<string | undefined>
81+
7282
/**
7383
* Set the verbosity of Android and iOS project's log system.
7484
* By default, you will be able to see info level logs printed in IDE when running the app.
7585
*/
7686
logLevel: IterableLogLevel = IterableLogLevel.info
7787

88+
/**
89+
* Set the amount of time (in seconds) before the current auth token expires to make a call to retrieve a new one
90+
*/
91+
expiringAuthTokenRefreshPeriod: number = 60.0
92+
7893
toDict(): any {
7994
return {
8095
"pushIntegrationName": this.pushIntegrationName,
@@ -84,7 +99,9 @@ class IterableConfig {
8499
"urlHandlerPresent": this.urlHandler != undefined,
85100
"customActionHandlerPresent": this.customActionHandler != undefined,
86101
"inAppHandlerPresent": this.inAppHandler != undefined,
87-
"logLevel": this.logLevel
102+
"authHandlerPresent": this.authHandler != undefined,
103+
"logLevel": this.logLevel,
104+
"expiringAuthTokenRefreshPeriod": this.expiringAuthTokenRefreshPeriod
88105
}
89106
}
90107
}
@@ -137,9 +154,6 @@ class IterableAttributionInfo {
137154
}
138155
}
139156

140-
/**
141-
* How many seconds to wait before showing the next in-app, if there are more than one present
142-
*/
143157
class IterableCommerceItem {
144158
id: string
145159
name: string
@@ -158,6 +172,7 @@ enum EventName {
158172
handleUrlCalled = "handleUrlCalled",
159173
handleCustomActionCalled = "handleCustomActionCalled",
160174
handleInAppCalled = "handleInAppCalled",
175+
handleAuthCalled = "handleAuthCalled"
161176
}
162177

163178
class Iterable {
@@ -190,6 +205,7 @@ class Iterable {
190205
}
191206
)
192207
}
208+
193209
if (config.customActionHandler) {
194210
RNEventEmitter.addListener(
195211
EventName.handleCustomActionCalled,
@@ -200,6 +216,7 @@ class Iterable {
200216
}
201217
)
202218
}
219+
203220
if (config.inAppHandler) {
204221
RNEventEmitter.addListener(
205222
EventName.handleInAppCalled,
@@ -211,6 +228,18 @@ class Iterable {
211228
)
212229
}
213230

231+
if (config.authHandler) {
232+
RNEventEmitter.addListener(
233+
EventName.handleAuthCalled,
234+
() => {
235+
config.authHandler!()
236+
.then(authToken => {
237+
RNIterableAPI.passAlongAuthToken(authToken)
238+
})
239+
}
240+
)
241+
}
242+
214243
// Set version from package.json
215244
const json = require('../package.json')
216245
const version = json["version"] as string

0 commit comments

Comments
 (0)