-
Notifications
You must be signed in to change notification settings - Fork 42
[SDK-223] - Embedded Listener RN Android Bridge #801
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -30,6 +30,7 @@ | |
| import com.iterable.iterableapi.IterableConfig; | ||
| import com.iterable.iterableapi.IterableCustomActionHandler; | ||
| import com.iterable.iterableapi.IterableEmbeddedMessage; | ||
| import com.iterable.iterableapi.IterableEmbeddedUpdateHandler; | ||
| import com.iterable.iterableapi.IterableHelper; | ||
| import com.iterable.iterableapi.IterableInAppCloseAction; | ||
| import com.iterable.iterableapi.IterableInAppHandler; | ||
|
|
@@ -52,7 +53,7 @@ | |
| import java.util.concurrent.CountDownLatch; | ||
| import java.util.concurrent.TimeUnit; | ||
|
|
||
| public class RNIterableAPIModuleImpl implements IterableUrlHandler, IterableCustomActionHandler, IterableInAppHandler, IterableAuthHandler, IterableInAppManager.Listener { | ||
| public class RNIterableAPIModuleImpl implements IterableUrlHandler, IterableCustomActionHandler, IterableInAppHandler, IterableAuthHandler, IterableInAppManager.Listener, IterableEmbeddedUpdateHandler { | ||
| public static final String NAME = "RNIterableAPI"; | ||
|
|
||
| private static String TAG = "RNIterableAPIModule"; | ||
|
|
@@ -125,6 +126,7 @@ public void initializeWithApiKey(String apiKey, ReadableMap configReadableMap, S | |
| IterableApi.getInstance().setDeviceAttribute("reactNativeSDKVersion", version); | ||
|
|
||
| IterableApi.getInstance().getInAppManager().addListener(this); | ||
| IterableApi.getInstance().getEmbeddedManager().addUpdateListener(this); | ||
| IterableApi.getInstance().getEmbeddedManager().syncMessages(); | ||
|
|
||
| // MOB-10421: Figure out what the error cases are and handle them appropriately | ||
|
|
@@ -189,6 +191,7 @@ public void initialize2WithApiKey(String apiKey, ReadableMap configReadableMap, | |
| IterableApi.getInstance().setDeviceAttribute("reactNativeSDKVersion", version); | ||
|
|
||
| IterableApi.getInstance().getInAppManager().addListener(this); | ||
| IterableApi.getInstance().getEmbeddedManager().addUpdateListener(this); | ||
| IterableApi.getInstance().getEmbeddedManager().syncMessages(); | ||
|
|
||
| // MOB-10421: Figure out what the error cases are and handle them appropriately | ||
|
|
@@ -781,6 +784,18 @@ public void trackEmbeddedClick(ReadableMap messageMap, String buttonId, String c | |
| } | ||
| } | ||
|
|
||
| @Override | ||
| public void onMessagesUpdated() { | ||
| IterableLogger.d(TAG, "onMessagesUpdated"); | ||
| sendEvent(EventName.receivedIterableEmbeddedMessagesChanged.name(), null); | ||
| } | ||
|
|
||
| @Override | ||
| public void onEmbeddedMessagingDisabled() { | ||
| IterableLogger.d(TAG, "onEmbeddedMessagingDisabled"); | ||
| sendEvent(EventName.receivedIterableEmbeddedMessagingDisabled.name(), null); | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. During the sync, if native code recognize feature disablement, this callback will be invoked. sendEvent will then call method on |
||
| } | ||
|
|
||
| // --------------------------------------------------------------------------------------- | ||
| // endregion | ||
| } | ||
|
|
@@ -793,5 +808,6 @@ enum EventName { | |
| handleInAppCalled, | ||
| handleUrlCalled, | ||
| receivedIterableEmbeddedMessagesChanged, | ||
| receivedIterableEmbeddedMessagingDisabled, | ||
| receivedIterableInboxChanged | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,13 +1,19 @@ | ||
| import { NativeEventEmitter } from 'react-native'; | ||
|
|
||
| import { RNIterableAPI } from '../../api'; | ||
| import { IterableAction } from '../../core/classes/IterableAction'; | ||
| import { IterableActionContext } from '../../core/classes/IterableActionContext'; | ||
| import { IterableApi } from '../../core/classes/IterableApi'; | ||
| import { IterableConfig } from '../../core/classes/IterableConfig'; | ||
| import { IterableLogger } from '../../core/classes/IterableLogger'; | ||
| import { IterableActionSource } from '../../core/enums/IterableActionSource'; | ||
| import { IterableEventName } from '../../core/enums/IterableEventName'; | ||
| import { callUrlHandler } from '../../core/utils/callUrlHandler'; | ||
| import { getActionPrefix } from '../../core/utils/getActionPrefix'; | ||
| import type { IterableEmbeddedMessage } from '../types/IterableEmbeddedMessage'; | ||
|
|
||
| const RNEventEmitter = new NativeEventEmitter(RNIterableAPI); | ||
|
|
||
| /** | ||
| * Manages embedded messages from Iterable. | ||
| * | ||
|
|
@@ -20,6 +26,16 @@ import type { IterableEmbeddedMessage } from '../types/IterableEmbeddedMessage'; | |
| * - [iOS Embedded Messaging](https://support.iterable.com/hc/en-us/articles/23061840746900-Embedded-Messages-with-Iterable-s-iOS-SDK) | ||
| */ | ||
| export class IterableEmbeddedManager { | ||
| /** | ||
| * List of listeners for embedded messages updated events. | ||
| */ | ||
| private _messagesUpdatedListeners: (() => void)[] = []; | ||
|
|
||
| /** | ||
| * List of listeners for embedded messaging disabled events. | ||
| */ | ||
| private _embeddedMessagingDisabledListeners: (() => void)[] = []; | ||
|
|
||
| /** | ||
| * Whether the embedded manager is enabled. | ||
| * | ||
|
|
@@ -57,6 +73,28 @@ export class IterableEmbeddedManager { | |
| this._isEnabled = config.enableEmbeddedMessaging ?? false; | ||
| } | ||
|
|
||
| /** | ||
| * Notifies all registered listeners that messages have been updated. | ||
| * | ||
| * @internal This method is for internal SDK use only. | ||
| */ | ||
| notifyMessagesUpdated() { | ||
| this._messagesUpdatedListeners.forEach((listener) => { | ||
| listener(); | ||
| }); | ||
| } | ||
|
|
||
| /** | ||
| * Notifies all registered listeners that embedded messaging has been disabled. | ||
| * | ||
| * @internal This method is for internal SDK use only. | ||
| */ | ||
| notifyEmbeddedMessagingDisabled() { | ||
| this._embeddedMessagingDisabledListeners.forEach((listener) => { | ||
| listener(); | ||
| }); | ||
| } | ||
|
|
||
| /** | ||
| * Syncs embedded local cache with the server. | ||
| * | ||
|
|
@@ -273,4 +311,131 @@ export class IterableEmbeddedManager { | |
| callUrlHandler(this._config, clickedUrl, context); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Adds a listener for when embedded messages are updated. | ||
| * | ||
| * This event fires when the embedded message cache is synced and messages | ||
| * have changed (new messages added, existing messages removed, etc.). | ||
| * | ||
| * The listener is added to an internal list and will be called when the | ||
| * native SDK detects that messages have been updated. | ||
| * | ||
| * @param callback - Function to call when messages are updated. | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * const callback = () => { | ||
| * // Refresh your UI with updated messages | ||
| * Iterable.embeddedManager.getMessages([1, 2, 3]).then(messages => { | ||
| * // Update UI with new messages | ||
| * }); | ||
| * }; | ||
| * Iterable.embeddedManager.addMessagesUpdatedListener(callback); | ||
| * | ||
| * // Later, remove the listener | ||
| * Iterable.embeddedManager.removeMessagesUpdatedListener(callback); | ||
| * ``` | ||
| */ | ||
| addMessagesUpdatedListener(callback: () => void) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we should instead have We can then add this to the |
||
| // Add to internal list | ||
| this._messagesUpdatedListeners.push(callback); | ||
| } | ||
|
|
||
| /** | ||
| * Adds a listener for when embedded messaging is disabled. | ||
| * | ||
| * This event fires when embedded messaging is disabled, typically due to | ||
| * subscription being inactive or invalid API key during sync. | ||
| * | ||
| * The listener is added to an internal list and will be called when the | ||
| * native SDK detects that embedded messaging has been disabled. | ||
| * | ||
| * @param callback - Function to call when embedded messaging is disabled. | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * const callback = () => { | ||
| * // Handle embedded messaging being disabled | ||
| * console.log('Embedded messaging has been disabled'); | ||
| * // Hide embedded message UI, etc. | ||
| * }; | ||
| * Iterable.embeddedManager.addEmbeddedMessagingDisabledListener(callback); | ||
| * | ||
| * // Later, remove the listener | ||
| * Iterable.embeddedManager.removeEmbeddedMessagingDisabledListener(callback); | ||
| * ``` | ||
| */ | ||
| addEmbeddedMessagingDisabledListener(callback: () => void) { | ||
| // Add to internal list | ||
| this._embeddedMessagingDisabledListeners.push(callback); | ||
| } | ||
|
|
||
| /** | ||
| * Removes a specific listener for when embedded messages are updated. | ||
| * | ||
| * @param callback - The callback function that was previously registered. | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * const listener = () => { | ||
| * console.log('Messages updated'); | ||
| * }; | ||
| * Iterable.embeddedManager.addMessagesUpdatedListener(listener); | ||
| * // Later, remove the specific listener | ||
| * Iterable.embeddedManager.removeMessagesUpdatedListener(listener); | ||
| * ``` | ||
| */ | ||
| removeMessagesUpdatedListener(callback: () => void) { | ||
| const index = this._messagesUpdatedListeners.indexOf(callback); | ||
| if (index > -1) { | ||
| this._messagesUpdatedListeners.splice(index, 1); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Removes a specific listener for when embedded messaging is disabled. | ||
| * | ||
| * @param callback - The callback function that was previously registered. | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * const listener = () => { | ||
| * console.log('Embedded messaging disabled'); | ||
| * }; | ||
| * Iterable.embeddedManager.addEmbeddedMessagingDisabledListener(listener); | ||
| * // Later, remove the specific listener | ||
| * Iterable.embeddedManager.removeEmbeddedMessagingDisabledListener(listener); | ||
| * ``` | ||
| */ | ||
| removeEmbeddedMessagingDisabledListener(callback: () => void) { | ||
| const index = this._embeddedMessagingDisabledListeners.indexOf(callback); | ||
| if (index > -1) { | ||
| this._embeddedMessagingDisabledListeners.splice(index, 1); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Removes all listeners for embedded message events. | ||
| * | ||
| * This removes all listeners for both `receivedIterableEmbeddedMessagesChanged` | ||
| * and `receivedIterableEmbeddedMessagingDisabled` events, including the | ||
| * internal lists of listeners. | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * Iterable.embeddedManager.removeAllListeners(); | ||
| * ``` | ||
| */ | ||
| removeAllListeners() { | ||
| RNEventEmitter.removeAllListeners( | ||
| IterableEventName.receivedIterableEmbeddedMessagesChanged | ||
| ); | ||
| RNEventEmitter.removeAllListeners( | ||
| IterableEventName.receivedIterableEmbeddedMessagingDisabled | ||
| ); | ||
| // Clear internal listener lists | ||
| this._messagesUpdatedListeners = []; | ||
| this._embeddedMessagingDisabledListeners = []; | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the callback that should trigger the call on TS level indicating its time to check local messages as sync has been performed.