chore: notification inbox public apis#566
chore: notification inbox public apis#566mrehan27 wants to merge 6 commits intofeature/message-inbox-mvpfrom
Conversation
Sample app builds 📱Below you will find the list of the latest versions of the sample apps. It's recommended to always download the latest builds of the sample apps to accurately test the pull request. |
| customerio.reactnative.targetSdkVersion=36 | ||
| customerio.reactnative.minSdkVersion=21 | ||
| customerio.reactnative.cioSDKVersionAndroid=4.15.2 | ||
| customerio.reactnative.cioSDKVersionAndroid=feature-message-inbox-mvp-SNAPSHOT |
There was a problem hiding this comment.
TODO: Update this before pushing live
| # pod "customerio-reactnative/#{push_provider}", :path => cio_package_path | ||
| # install_non_production_ios_sdk_local_path(local_path: '~/code/customerio-ios/', is_app_extension: false, push_service: push_provider) | ||
| # install_non_production_ios_sdk_git_branch(branch_name: 'feature/wrappers-inline-support', is_app_extension: false, push_service: push_provider) | ||
| install_non_production_ios_sdk_git_branch(branch_name: 'feature/message-inbox-mvp', is_app_extension: false, push_service: push_provider) |
There was a problem hiding this comment.
TODO: Update this before pushing live
| // Set flag after successful setup (allows retry if setup was called before SDK initialized) | ||
| self.isInboxChangeListenerSetup = true | ||
| } | ||
| } |
There was a problem hiding this comment.
iOS listener setup has race condition with async flag
Medium Severity
setupInboxChangeListener checks isInboxChangeListenerSetup synchronously but sets it to true inside an asynchronous Task { @MainActor in }. If called twice before the first Task executes, both calls pass the guard and both add a listener, resulting in duplicate listeners and duplicate event emissions. The same pattern in clearInboxChangeListener means cleanup called before the setup Task runs will no-op, leaking the listener. The Android implementation correctly avoids this by using synchronized to make the check-and-set atomic.
Additional Locations (1)
android/src/main/java/io/customer/reactnative/sdk/messaginginapp/NotificationInboxExtensions.kt
Show resolved
Hide resolved
| // Reset flag after cleanup completes | ||
| self.isInboxChangeListenerSetup = false | ||
| } | ||
| } |
There was a problem hiding this comment.
iOS inbox listener cleanup has race condition
Medium Severity
The clearInboxChangeListener method has a race condition where the guard check on isInboxChangeListenerSetup happens on the calling thread, but the flag reset occurs asynchronously inside a Task on MainActor. If clearInboxChangeListener and setupInboxChangeListener are called concurrently during module invalidation and reinitialization, the flag state can become inconsistent, potentially leaving listeners registered but marked as unregistered, or blocking future listener setups.


closes: MBL-1550
Summary
Implements Notification Inbox feature for React Native SDK, enabling customers to display and manage inbox messages. Includes TypeScript APIs, Android/iOS native implementations with real time change listeners, and native SDK topic filtering support.
Changes
NotificationInboxclass in TypeScript with methods for managing inbox messagesInboxMessageandNotificationInboxChangeListenertype definitionssubscribeToUpdates()method withEventEmitterfor real time message updatesgetMessages(),markMessageOpened(),markMessageUnopened(),markMessageDeleted(), andtrackMessageClicked()methodsTurboModulespec with inbox methods andsubscribeToMessagesChangedEventEmitterNativeMessagingInAppModuleReactNotificationInboxChangeListenersingleton for Android with thread safe listener setupNotificationInboxExtensions.ktwithInboxMessage.toWritableMap()conversion helperNativeMessagingInApp.swiftReactNotificationInboxChangeListener.swiftto listen to notification inbox changesInboxMessage+Conversion.swiftextension for converting inbox messages to dictionariessubscribeToUpdates()callNotes
Note
Medium Risk
Introduces new cross-platform TurboModule methods and event emitters plus native listener lifecycle/serialization logic; bugs could surface as runtime bridge errors or missed/duplicated inbox updates.
Overview
Adds a new Notification Inbox public API to the React Native in-app module via
CustomerIO.inAppMessaging.inbox(), including typedInboxMessage/NotificationInboxChangeListenerand aNotificationInboxwrapper that can fetch messages, update read/deleted state, track clicks, and subscribe to real-time updates (with optional client-side topic filtering).Extends the TurboModule spec and implements the new inbox bridge on Android and iOS, including lazy, one-time setup/teardown of native change listeners that emit
subscribeToMessagesChangedevents and message serialization helpers for RN interop (recursive map/array conversion andInboxMessagemapping). Also switches the sample/native dependency pins to a message-inbox feature snapshot/branch for testing.Written by Cursor Bugbot for commit 2cba428. This will update automatically on new commits. Configure here.