UNPKG

@iterable/react-native-sdk

Version:
890 lines (860 loc) 33.8 kB
"use strict"; import { Linking, NativeEventEmitter, Platform } from 'react-native'; import { buildInfo } from "../../itblBuildInfo.js"; import { IterableInAppManager, IterableInAppMessage } from "../../inApp/index.js"; import { IterableAuthResponseResult, IterableEventName } from "../enums/index.js"; import { IterableAction } from "./IterableAction.js"; import { IterableActionContext } from "./IterableActionContext.js"; import { IterableAttributionInfo } from "./IterableAttributionInfo.js"; import { IterableAuthResponse } from "./IterableAuthResponse.js"; import { IterableConfig } from "./IterableConfig.js"; import { IterableLogger } from "./IterableLogger.js"; import { RNIterableAPI } from "./RNIterableAPI.js"; const RNEventEmitter = new NativeEventEmitter(RNIterableAPI); /* eslint-disable tsdoc/syntax */ /** * The main class for the Iterable React Native SDK. * * The majority of the high-level functionality can be accomplished through the * static methods of this class. EG: initializing the SDK, logging in a user, * tracking purchases, etc. * * @example * // Initialize the SDK * Iterable.initialize(YOUR_API_KEY, new IterableConfig()); * * // Log in a user * Iterable.setEmail('my.email@company.com'); * // OR * Iterable.setUserId('myUserId'); */ /* eslint-enable tsdoc/syntax */ export class Iterable { /** * Manager for in app messages */ static inAppManager = new IterableInAppManager(); /** * Logger for the Iterable SDK * Log level is set with {@link IterableLogLevel} */ /** * Current configuration of the Iterable SDK */ /** * Initializes the Iterable React Native SDK in your app's Javascript or Typescript code. * * Pass in a mobile API key distributed with the mobile app. * Warning: never user server-side API keys with the React Native SDK, mobile API keys have minimal access for security purposes. * * Pass in an `IterableConfig` object with the various customization properties setup. * * **WARNING**: Never use server-side API keys with Iterable's mobile SDKs. * Since API keys are, by necessity, distributed with the mobile apps that * contain them, bad actors can potentially access them. For this reason, * Iterable provides mobile API keys, which have minimal access. * * @param apiKey - The [*mobile* API * key](https://support.iterable.com/hc/en-us/articles/360043464871-API-Keys) * for your application * @param config - Configuration object for the SDK * * @example * Initializing the app could look like this: * ```typescript * // Create a new IterableConfig object * const config = new IterableConfig(); * * // Set various properties on the config object * config.logLevel = IterableLogLevel.debug; * * // Initialize the SDK with the API key and config object * Iterable.initialize(API_KEY, config); * ``` */ static initialize(apiKey, config = new IterableConfig()) { Iterable.savedConfig = config; Iterable.logger = new IterableLogger(Iterable.savedConfig); Iterable.logger.log('initialize: ' + apiKey); this.setupEventHandlers(); const version = this.getVersionFromPackageJson(); return RNIterableAPI.initializeWithApiKey(apiKey, config.toDict(), version); } /** * DO NOT CALL THIS METHOD. * This method is used internally to connect to staging environment. * * @internal */ static initialize2(apiKey, config = new IterableConfig(), apiEndPoint) { Iterable.savedConfig = config; Iterable.logger = new IterableLogger(Iterable.savedConfig); Iterable.logger.log('initialize2: ' + apiKey); this.setupEventHandlers(); const version = this.getVersionFromPackageJson(); return RNIterableAPI.initialize2WithApiKey(apiKey, config.toDict(), version, apiEndPoint); } /** * Associate the current user with the passed in email parameter. * * Note: specify a user by calling `Iterable.setEmail` or * `Iterable.setUserId`, but **NOT** both * * @remarks * Iterable's React Native SDK persists the user across app sessions and * restarts, until you manually change the user using `Iterable.setEmail` or * `Iterable.setUserId`. * * ## User profile creation: * * If your Iterable project does not have a user with the passed in email, * `setEmail` creates one and adds the email address to the user's Iterable * profile. * * ## Registering device token: * * If `IterableConfig.autoPushRegisteration` is set to true, calling * `setEmail` automatically registers the device for push notifications and * sends the deviceId and token to Iterable. * * ## Optional JWT token parameter: * * An optional valid, pre-fetched JWT can be passed in to avoid race * conditions. The SDK uses this JWT to authenticate API requests for this * user. * * ## Signing out a user from the SDK: * * To tell the SDK to sign out the current user, pass null into * `Iterable.setEmail`. If IterableConfig.autoPushRegisteration is set to * true, calling `Iterable.setEmail`(null) prevents Iterable from sending * further push notifications to that user, for that app, on that device. On * the user's Iterable profile, `endpointEnabled` is set to false for the * device. * * @param email - Email address to associate with * the current user * @param authToken - Valid, pre-fetched JWT the SDK * can use to authenticate API requests, optional - If null/undefined, no JWT * related action will be taken * * @example * ```typescript * Iterable.setEmail('my.user.name@gmail.com'); * ``` */ static setEmail(email, authToken) { Iterable.logger.log('setEmail: ' + email); RNIterableAPI.setEmail(email, authToken); } /** * Get the email associated with the current user. * * @example * ```typescript * Iterable.getEmail().then((email) => { * // Do something with the email * }); * ``` */ static getEmail() { Iterable.logger.log('getEmail'); return RNIterableAPI.getEmail(); } /** * Associate the current user with the passed in `userId` parameter. * * Note: specify a user by calling `Iterable.setEmail` or * `Iterable.setUserId`, but **NOT** both. * * @remarks * Iterable's React Native SDK persists the user across app sessions and * restarts, until you manually change the user using `Iterable.setEmail` or * `Iterable.setUserId`. * * ## User profile creation: * * If your Iterable project does not have a user with the passed in `UserId`, * `setUserId` creates one and adds a placeholder email address to the user's * Iterable profile. * * ## Registering device token: * * If `IterableConfig.autoPushRegisteration` is set to `true`, calling * `setUserId` automatically registers the device for push notifications and * sends the `deviceId` and token to Iterable. * * ## Optional JWT token parameter: * * An optional valid, pre-fetched JWT can be passed in to avoid race * conditions. The SDK uses this JWT to authenticate API requests for this * user. * * ## Signing out a user from the SDK: * * To tell the SDK to sign out the current user, pass null into * `Iterable.setUserId`. If `IterableConfig.autoPushRegisteration` is set to * true, calling `Iterable.setUserId(null)` prevents Iterable from sending * further push notifications to that user, for that app, on that device. On * the user's Iterable profile, endpointEnabled is set to false for the * device. * * @param userId - User ID to associate with the current user * @param authToken - Valid, pre-fetched JWT the SDK can use to authenticate * API requests, optional - If null/undefined, no JWT related action will be * taken */ static setUserId(userId, authToken) { Iterable.logger.log('setUserId: ' + userId); RNIterableAPI.setUserId(userId, authToken); } /** * Get the `userId` associated with the current user. * * @example * ```typescript * Iterable.getUserId().then((userId) => { * // Do something with the userId * }); * ``` */ static getUserId() { Iterable.logger.log('getUserId'); return RNIterableAPI.getUserId(); } /** * Disable the device's token for the current user. This will disable push notifications for the current user. * * @example * ```typescript * Iterable.disableDeviceForCurrentUser(); * ``` */ static disableDeviceForCurrentUser() { Iterable.logger.log('disableDeviceForCurrentUser'); RNIterableAPI.disableDeviceForCurrentUser(); } /** * Get the payload of the last push notification with which the user * opened the application (by clicking an action button, etc.). * * @example * ```typescript * Iterable.getLastPushPayload().then((payload) => { * // Do something with the payload * }); * ``` */ static getLastPushPayload() { Iterable.logger.log('getLastPushPayload'); return RNIterableAPI.getLastPushPayload(); } /** * Get the stored attribution information -- possibly based on a recent deep link click. * * The attribution information contains the campaign ID, template ID, and message ID of the message * that prompted the user to recently click a link. * * @see {@link IterableAttributionInfo} * * @example * ```typescript * Iterable.getAttributionInfo().then((attributionInfo) => { * Iterable.updateSubscriptions( * null, * [33015, 33016, 33018], * null, * null, * attributionInfo.campaignId, * attributionInfo.templateId * ); * }); * ``` */ static getAttributionInfo() { Iterable.logger.log('getAttributionInfo'); return RNIterableAPI.getAttributionInfo().then(dict => { if (dict) { return new IterableAttributionInfo(dict.campaignId, dict.templateId, dict.messageId); } else { return undefined; } }); } /** * Manually set the current stored attribution information so that it can later be used when tracking events. * * The attribution information contains the campaign ID, template ID, and message ID of the message * that prompted the user to recently click a link. * * @see {@link IterableAttributionInfo} * * For deep link clicks, Iterable sets attribution information automatically. * However, use this method to set it manually if ever necessary. * * @param attributionInfo - Object storing current attribution info * * @example * ```typescript * const CAMPAIGN_ID = 1234; * const TEMPLATE_ID = 5678; * const MESSAGE_ID = 9012; * * const attributionInfo = new IterableAttributionInfo(CAMPAIGN_ID, TEMPLATE_ID, MESSAGE_ID); * * Iterable.setAttributionInfo(attributionInfo); * ``` */ static setAttributionInfo(attributionInfo) { Iterable.logger.log('setAttributionInfo'); RNIterableAPI.setAttributionInfo(attributionInfo); } /** * Create a `pushOpen` event on the current user's Iterable profile, populating * it with data provided to the method call. * * **NOTE**: Iterable's SDK automatically tracks push notification opens. * However, it's also possible to manually track these events by calling this * method. * * @param campaignId - The ID of the campaign to associate with the push open * @param templateId - The ID of the template to associate with the push open * @param messageId - The ID of the message to associate with the push open * @param appAlreadyRunning - Whether or not the app was already running when * the push notification arrived * @param dataFields - Information to store with the push open event * * @example * ```typescript * const CAMPAIGN_ID = 12345; * const TEMPLATE_ID = 67890; * const MESSAGE_ID = '0fc6657517c64014868ea2d15f23082b'; * const APP_ALREADY_RUNNING = false; * const DATA_FIELDS = { * "discount": 0.99, * "product": "cappuccino", * }; * * Iterable.trackPushOpen(CAMPAIGN_ID, TEMPLATE_ID, MESSAGE_ID, APP_ALREADY_RUNNING, DATA_FIELDS); * ``` */ static trackPushOpenWithCampaignId(campaignId, templateId, messageId, appAlreadyRunning, dataFields) { Iterable.logger.log('trackPushOpenWithCampaignId'); RNIterableAPI.trackPushOpenWithCampaignId(campaignId, templateId, messageId, appAlreadyRunning, dataFields); } /** * Update the items saved in the shopping cart (or equivalent). * * Represent each item in the updateCart event with an IterableCommerceItem object. * * @see {@link IterableCommerceItem} * * @param items - The items added to the shopping cart * * @example * ```typescript * const item = new IterableCommerceItem( * "TOY1", * "Red Racecar", * 4.99, * 1, * "RR123", * "A small, red racecar.", * "https://www.example.com/toys/racecar", * "https://www.example.com/toys/racecar/images/car.png", * ["Toy", "Inexpensive"], * ); * * Iterable.updateCart([item]); * ``` */ static updateCart(items) { Iterable.logger.log('updateCart'); RNIterableAPI.updateCart(items); } /** * Launch the application from the background in Android devices. * * @group Android Only * * @example * ```typescript * Iterable.wakeApp(); * ``` */ static wakeApp() { if (Platform.OS === 'android') { Iterable.logger.log('Attempting to wake the app'); RNIterableAPI.wakeApp(); } } /** * Create a purchase event on the current user's Iterable profile. * * Represent each item in the purchase event with an {@link IterableCommerceItem} object. * * @see {@link IterableCommerceItem} * * **NOTE**: `total` is a parameter that is passed in. Iterable does not sum the `price` fields of the various items in the purchase event. * * @param total - The total cost of the purchase * @param items - The items included in the purchase * @param dataFields - Descriptive data to store on the purchase event * * @example * ```typescript * const items = [ * new IterableCommerceItem('item1', 'Item 1', 10.0, 1), * new IterableCommerceItem('item2', 'Item 2', 20.0, 2), * ]; * const dataFields = { 'key1': 'value1', }; * * Iterable.trackPurchase(30.0, items, dataFields); * ``` */ static trackPurchase(total, items, dataFields) { Iterable.logger.log('trackPurchase'); RNIterableAPI.trackPurchase(total, items, dataFields); } /** * Create an `inAppOpen` event for the specified message on the current user's profile * for manual tracking purposes. Iterable's SDK automatically tracks in-app message opens when you use the * SDK's default rendering. * * @param message - The in-app message (an {@link IterableInAppMessage} object) * @param location - The location of the in-app message (an IterableInAppLocation enum) * * @example * ```typescript * const message = new IterableInAppMessage(1234, 4567, IterableInAppTrigger.auto, new Date(), new Date(), false, undefined, undefined, false, 0); * Iterable.trackInAppOpen(message, IterableInAppLocation.inApp); * ``` * * @remarks * Iterable's SDK automatically tracks in-app message opens when you use the * SDK's default rendering. However, it's also possible to manually track * these events by calling this method. */ static trackInAppOpen(message, location) { Iterable.logger.log('trackInAppOpen'); RNIterableAPI.trackInAppOpen(message.messageId, location); } /** * Create an `inAppClick` event for the specified message on the current user's profile * for manual tracking purposes. Iterable's SDK automatically tracks in-app message clicks when you use the * SDK's default rendering. Click events refer to click events within the in-app message to distinguish * from `inAppOpen` events. * * @param message - The in-app message. * @param location - The location of the in-app message. * @param clickedUrl - The URL clicked by the user. * * @example * ```typescript * const message = new IterableInAppMessage(1234, 4567, IterableInAppTrigger.auto, new Date(), new Date(), false, undefined, undefined, false, 0); * Iterable.trackInAppClick(message, IterableInAppLocation.inApp, 'https://www.example.com'); * ``` * * @remarks * Iterable's SDK automatically tracks in-app message clicks when you use the * SDK's default rendering. However, you can also manually track these events * by calling this method. */ static trackInAppClick(message, location, clickedUrl) { Iterable.logger.log('trackInAppClick'); RNIterableAPI.trackInAppClick(message.messageId, location, clickedUrl); } /** * Create an `inAppClose` event for the specified message on the current * user's profile for manual tracking purposes. Iterable's SDK automatically * tracks in-app message close events when you use the SDK's default * rendering. * * @param message - The in-app message. * @param location - The location of the in-app message. Useful for determining if the messages is in a mobile inbox. * @param source - The way the in-app was closed. * @param clickedUrl - The URL clicked by the user. * * @example * ```typescript * const message = new IterableInAppMessage(1234, 4567, IterableInAppTrigger.auto, new Date(), new Date(), false, undefined, undefined, false, 0); * Iterable.trackInAppClose(message, IterableInAppLocation.inApp, IterableInAppCloseSource.back, 'https://www.example.com'); * ``` * * @remarks * Iterable's SDK automatically tracks in-app message close events when you * use the SDK's default rendering. However, it's also possible to manually * track these events by calling this method. */ static trackInAppClose(message, location, source, clickedUrl) { Iterable.logger.log('trackInAppClose'); RNIterableAPI.trackInAppClose(message.messageId, location, source, clickedUrl); } /** * Remove the specified message from the current user's message queue. * * This creates an in-app delete event for the specified message on the current user's profile * unless otherwise specified (specifying a source of {@link IterableInAppDeleteSource.unknown} prevents * an `inAppDelete` event from being created). * * @param message - The in-app message (an {@link IterableInAppMessage} object) * @param location - The location of the in-app message (an {@link IterableInAppLocation} enum) * @param source - How the in-app message was deleted (an {@link IterableInAppDeleteSource} enum) * * @example * ```typescript * const message = new IterableInAppMessage( * 1234, * 4567, * IterableInAppTrigger.auto, * new Date(), * new Date(), * false, * undefined, * undefined, * false, * 0, * ); * * Iterable.inAppConsume(message, IterableInAppLocation.inApp, IterableInAppDeleteSource.delete); * ``` * * @remarks * After a user has read an in-app message, you can _consume_ it so that it's no * longer in their queue of messages. When you use the SDK's default rendering * for in-app messages, it handles this automatically. However, you can also * use this method to do it manually (for example, after rendering an in-app * message in a custom way). */ static inAppConsume(message, location, source) { Iterable.logger.log('inAppConsume'); RNIterableAPI.inAppConsume(message.messageId, location, source); } /** * Create a custom event to the current user's Iterable profile. * * Pass in the name of the event stored in eventName key and the data associated with the event. * The eventType is set to "customEvent". * * @param name - The event name of the custom event * @param dataFields - Descriptive data to store on the custom event * * @example * ```typescript * Iterable.trackEvent("completedOnboarding", * { * "includedProfilePhoto": true, * "favoriteColor": "red", * "favoriteFlavor": "cinnamon", * } * ); * ``` */ static trackEvent(name, dataFields) { Iterable.logger.log('trackEvent'); RNIterableAPI.trackEvent(name, dataFields); } /** * Save data to the current user's Iterable profile. * * If `mergeNestedObjects` is set to `true`, top-level objects in the passed in dataFields parameter * are merged with their counterparts that already exist on the user's profile. * Otherwise, they are added. * * If `mergeNestedObjects` is set to `false`, the top-level objects in the passed in dataFields parameter * overwrite their counterparts that already exist on the user's profile. * Otherwise, they are added. * * @param dataFields - Data fields to store in user profile * @param mergeNestedObjects - Whether to merge top-level objects included in * dataFields with analogous, existing objects on the user profile (if `true`) * or overwrite them (if `false`). * * @example * This call adds the `firstName` field and `favorites` object to the current * user's Iterable profile. Since `mergeNestedObjects` is `false`, this call will * overwrite the existing favorites object (if there is one), replacing it * with the value in the call (otherwise, it would have merged the two * `favorites` objects). * * ```typescript * Iterable.updateUser( * { * "firstName": "Joe", * "favorites": { * "color": "red", * "flavor": "cinnamon" * } * }, * false * ); * ``` * * @remarks * **IMPORTANT**: `mergeNestedObjects` only works for data that is stored up to one level deep within an object (for example, `{mySettings:{mobile:true}}`). Note that `mergeNestedObjects` applies to objects, not arrays. */ static updateUser(dataFields, mergeNestedObjects) { Iterable.logger.log('updateUser'); RNIterableAPI.updateUser(dataFields, mergeNestedObjects); } /** * Change the value of the email field on the current user's Iterable profile. * * If `Iterable.setUserId` was used to identify the current user, `Iterable.updateEmail` can be called to * give the current user a real (non-placeholder) email address. * * An optional valid, pre-fetched JWT can be passed in to avoid race conditions. * The SDK uses this JWT to authenticate API requests for this user. * * @param email - The new email to set * @param authToken - The new auth token (JWT) to set with the new email, optional - If null/undefined, no JWT-related action will be taken * * @example * ```typescript * Iterable.updateEmail('my.new.email@gmail.com', 'myAuthToken'); * ``` */ static updateEmail(email, authToken) { Iterable.logger.log('updateEmail'); RNIterableAPI.updateEmail(email, authToken); } /** * tsdoc/syntax needs to be disabled as it conflicts with the mermaid syntax. * unfortunately, disabling it inline does not appear to work. */ /* eslint-disable tsdoc/syntax */ /** * Handle a universal link. * * `handleAppLink` will hand the passed in URL to `IterableConfig.urlHandler`, where it is determined whether or not * the app can handle the clicked URL. * * This can be used to handle deep links, universal links, and other URLs that * the app should handle. * * @see [Handling Deep Links in the Iterable React Native SDK](https://support.iterable.com/hc/en-us/articles/360046134911-Deep-Links-and-Custom-Actions-with-Iterable-s-React-Native-SDK#configuring-your-app-to-support-deep-links) * * @remarks * When you call `Iterable.handleAppLink,` you'll pass a URL—the tracking URL * generated by Iterable for the link you included in your message content. * `handleAppLink` will fetch the original URL (the one you added to your * message) from `Iterable` and hand it to `IterableConfig.urlHandler`, where you * can analyze it and decide what to do (for example, you might navigate the * user to a particular screen in your app that has content related to the * link). * * @mermaid The flow goes like this: * graph TD; * A[Linking event listener] --> B[Iterable.handleAppLink] --> C[IterableConfig.urlHandler]; * * * @param link - The tracking URL generated by Iterable for the link you included in your message content. * * @example * Basic usage is as follows: * ```typescript * Iterable.handleAppLink('https://www.example.com').then((handled) => { * console.log('Link handled: ' + handled); * }); * ``` * * For deep linking, your code would look something like this: * ```tsx * import { Linking } from 'react-native'; * * const MyApp = () => { * // To handle deep links clicked when the app is not running, * // implement `Linking.getInitialURL`: * Linking.getInitialURL().then((url) => { * if (url) { * Iterable.handleAppLink(url); * } * }); * * // To handle deep links clicked when the app is already open * // (even if it's in the background), implement * // `Linking.addEventListener('url', callback)` * Linking.addEventListener('url', (event) => { * if (event.url) { * Iterable.handleAppLink(event.url); * } * }); * * // This, in turn, will call your `urlHandler` function on the * // `IterableConfig` object you used to initialize the SDK. * const config = new IterableConfig(); * config.urlHandler = (url) => { * const isCoffeeUrl = url.search(/coffee/i) !== -1; * if (isCoffeeUrl) { * // Navigate to the coffee screen * } * return isCoffeeUrl; * }; * * return ( /* Your app code here * / ); * } * ``` */ /* eslint-enable tsdoc/syntax */ static handleAppLink(link) { Iterable.logger.log('handleAppLink'); return RNIterableAPI.handleAppLink(link); } /** * Update the current user's subscribed email lists, unsubscribed channel IDs, * unsubscribed message type IDs (for opt-out message types), and subscribed message type IDs (for opt-in message types) * on the current user's profile. * * Pass in null for any of `emailListIds`, `unsubscribedChannelIds`, `unsubscribedMessageTypeIds`, or `subscribedMessageTypeIds` * to indicate that Iterable should not change the current value on the current user's profile. * * @param emailListIds - The list of email lists (by ID) to which the user should be subscribed * @param unsubscribedChannelIds - The list of message channels (by ID) to which the user should be unsubscribed * @param unsubscribedMessageTypeIds - The list of message types (by ID) to which the user should be unsubscribed (for opt-out message types) * @param subscribedMessageTypeIds - The list of message types (by ID) to which the user should be subscribed (for opt-in message types) * @param campaignId - The campaign ID to associate with events generated by this request, use `-1` if unknown or not applicable * @param templateId - The template ID to associate with events generated by this request, use `-1` if unknown or not applicable * * @example * ```typescript * const emailListIds = [1234, 5678]; * const unsubscribedChannelIds = [1234, 5678]; * const unsubscribedMessageTypeIds = [1234, 5678]; * const subscribedMessageTypeIds = [1234, 5678]; * const campaignId = 1234; * const templateId = 5678; * * Iterable.updateSubscriptions( * emailListIds, * unsubscribedChannelIds, * unsubscribedMessageTypeIds, * subscribedMessageTypeIds, * campaignId, * templateId, * ); * ``` */ static updateSubscriptions(emailListIds, unsubscribedChannelIds, unsubscribedMessageTypeIds, subscribedMessageTypeIds, campaignId, templateId) { Iterable.logger.log('updateSubscriptions'); RNIterableAPI.updateSubscriptions(emailListIds, unsubscribedChannelIds, unsubscribedMessageTypeIds, subscribedMessageTypeIds, campaignId, templateId); } /** * Sets up event handlers for various Iterable events. * * This method performs the following actions: * - Removes all existing listeners to avoid duplicate listeners. * - Adds listeners for URL handling, custom actions, in-app messages, and authentication. * * Event Handlers: * - `handleUrlCalled`: Invokes the URL handler if configured, with a delay on Android to allow the activity to wake up. * - `handleCustomActionCalled`: Invokes the custom action handler if configured. * - `handleInAppCalled`: Invokes the in-app handler if configured and sets the in-app show response. * - `handleAuthCalled`: Invokes the authentication handler if configured and handles the promise result. * - `handleAuthSuccessCalled`: Sets the authentication response callback to success. * - `handleAuthFailureCalled`: Sets the authentication response callback to failure. * * Helper Functions: * - `callUrlHandler`: Calls the URL handler and attempts to open the URL if the handler returns false. * * @internal */ static setupEventHandlers() { //Remove all listeners to avoid duplicate listeners RNEventEmitter.removeAllListeners(IterableEventName.handleUrlCalled); RNEventEmitter.removeAllListeners(IterableEventName.handleInAppCalled); RNEventEmitter.removeAllListeners(IterableEventName.handleCustomActionCalled); RNEventEmitter.removeAllListeners(IterableEventName.handleAuthCalled); if (Iterable.savedConfig.urlHandler) { RNEventEmitter.addListener(IterableEventName.handleUrlCalled, dict => { const url = dict.url; const context = IterableActionContext.fromDict(dict.context); Iterable.wakeApp(); if (Platform.OS === 'android') { //Give enough time for Activity to wake up. setTimeout(() => { callUrlHandler(url, context); }, 1000); } else { callUrlHandler(url, context); } }); } if (Iterable.savedConfig.customActionHandler) { RNEventEmitter.addListener(IterableEventName.handleCustomActionCalled, dict => { const action = IterableAction.fromDict(dict.action); const context = IterableActionContext.fromDict(dict.context); Iterable.savedConfig.customActionHandler(action, context); }); } if (Iterable.savedConfig.inAppHandler) { RNEventEmitter.addListener(IterableEventName.handleInAppCalled, messageDict => { const message = IterableInAppMessage.fromDict(messageDict); // MOB-10423: Check if we can use chain operator (?.) here instead const result = Iterable.savedConfig.inAppHandler(message); RNIterableAPI.setInAppShowResponse(result); }); } if (Iterable.savedConfig.authHandler) { let authResponseCallback; RNEventEmitter.addListener(IterableEventName.handleAuthCalled, () => { // MOB-10423: Check if we can use chain operator (?.) here instead Iterable.savedConfig.authHandler().then(promiseResult => { // Promise result can be either just String OR of type AuthResponse. // If type AuthReponse, authToken will be parsed looking for `authToken` within promised object. Two additional listeners will be registered for success and failure callbacks sent by native bridge layer. // Else it will be looked for as a String. if (typeof promiseResult === typeof new IterableAuthResponse()) { RNIterableAPI.passAlongAuthToken(promiseResult.authToken); setTimeout(() => { if (authResponseCallback === IterableAuthResponseResult.SUCCESS) { if (promiseResult.successCallback) { promiseResult.successCallback?.(); } } else if (authResponseCallback === IterableAuthResponseResult.FAILURE) { if (promiseResult.failureCallback) { promiseResult.failureCallback?.(); } } else { Iterable.logger.log('No callback received from native layer'); } }, 1000); } else if (typeof promiseResult === typeof '') { //If promise only returns string RNIterableAPI.passAlongAuthToken(promiseResult); } else { Iterable.logger.log('Unexpected promise returned. Auth token expects promise of String or AuthResponse type.'); } }).catch(e => Iterable.logger.log(e)); }); RNEventEmitter.addListener(IterableEventName.handleAuthSuccessCalled, () => { authResponseCallback = IterableAuthResponseResult.SUCCESS; }); RNEventEmitter.addListener(IterableEventName.handleAuthFailureCalled, () => { authResponseCallback = IterableAuthResponseResult.FAILURE; }); } function callUrlHandler(url, context) { // MOB-10424: Figure out if this is purposeful // eslint-disable-next-line eqeqeq if (Iterable.savedConfig.urlHandler?.(url, context) == false) { Linking.canOpenURL(url).then(canOpen => { if (canOpen) { Linking.openURL(url); } }).catch(reason => { Iterable.logger.log('could not open url: ' + reason); }); } } } /** * Retrieves the version number from the package.json file. * * @returns The version number as specified in the package.json file. * * @internal */ static getVersionFromPackageJson() { return buildInfo.version; } } //# sourceMappingURL=Iterable.js.map