feat(inbox): let apps configure visual inbox accessibility labels - #658
Merged
Merged
Conversation
The native SDKs stopped shipping hardcoded English labels for the visual
notification inbox, so apps now supply their own. Expose that config through
the wrapper: four optional strings on `inApp`, with the unread-count label as
a `{count}` template because the bridge carries data but not callbacks.
iOS needs no native change — the whole config already reaches
MessagingInAppConfigBuilder.build(from:), which parses these keys. Android
builds the labels and converts the template into the closure the SDK expects.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Contributor
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. Builds are in progress. This comment will be updated when they finish.
|
Review of the wrapper PRs found two ways the example lost the accessibility
labels it exists to demonstrate:
- loadFromStorage merged persisted config over defaults shallowly, so any
device that had ever opened Settings replaced the defaults' `inApp` wholesale
and demonstrated the unlabeled inbox.
- Toggling in-app messaging off clears `inApp`, so re-enabling had nothing to
spread and dropped the labels permanently.
Also corrects the `loadingIndicator` doc, which described Android's behaviour
as if it were cross-platform: on iOS an unset label makes the spinner not an
accessibility element at all, so VoiceOver skips it rather than announcing a
progress role.
Adds a debug log when `bellWithUnreadCount` carries no `{count}` placeholder —
a typo like `{COUNT}` or `%d` is otherwise read aloud verbatim with the count
never announced, and nothing else in the stack can surface that.
Pins Android to 4.21.1, which adds an in-app open-url query fix at no cost, and
narrows the test docstring to what it actually verifies: the JavaScript half,
not the native key names.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The empty state is driven entirely by SDK data — NotificationInboxView takes no props that could force it — so seeing the dimmed bell previously meant finding a profile that happened to have no messages. Identifying a fresh random user reaches it through the real SDK path instead of faking a view state. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…nges
The mistyped-placeholder warning lived in the Android mapper at debug level,
which the default ERROR log level discards, and iOS had no check at all — so a
typo like `{COUNT}` produced a screen reader announcing the template verbatim
with no diagnostic on either platform. The check now runs in param-validation
alongside the other config checks, warning rather than throwing since a label
typo must not fail initialization.
The sample app now supplies the labels at its single initialize() call instead
of storing them in the editable Settings config, which keeps Settings and
storage untouched. Drops the debug identify button: testers reach the empty
state by logging in with a profile that has no inbox messages.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…alize The previous commit put the labels in `onSetConfig`, describing it as the sample's single initialize() call. It is not called at all: the callback is defined, typed and given a no-op default, but no screen consumes it. The live paths are app start, which initializes from stored config, and the Settings save. Native initialize ignores every call after the first, so the app-start path won and the labels never reached the SDK — the sample demonstrated an unlabeled inbox on every launch. Moves the labels into a shared helper and applies it at every initialize call site, the unused callback included, so wiring that callback up later cannot silently lose them again. They stay out of the persisted, user-editable Settings config. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
mahmoud-elmorabea
marked this pull request as ready for review
September 15, 2026 12:39
Shahroz16
approved these changes
Sep 15, 2026
cio-mobile-release Bot
pushed a commit
that referenced
this pull request
Sep 15, 2026
## [6.11.0](6.10.0...6.11.0) (2026-09-15) ### Features * **inbox:** let apps configure visual inbox accessibility labels ([#658](#658)) ([1d911c2](1d911c2))
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Exposes the visual notification inbox accessibility labels through the React Native config, so host apps supply their own localized strings instead of the SDK shipping English text.
Fixes MBL-2366
Notes
MessagingInAppConfigBuilder.build(from:), which parses these keys.{count}template into the(Int) -> Stringclosure the SDK takes — the bridge carries data, not callbacks.bellWithUnreadCountmissing its{count}placeholder is announced verbatim with no count.param-validationwarns about it rather than throwing, since a label typo must degrade an announcement and never fail initialization. The check lives in JavaScript because neither native layer can report it where the developer would see it: Android would log at debug, which the default ERROR level discards, and iOS does not check at all.jest.config.jsnow defines__DEV__, which the bare node test environment lacks; without it any test reachingassert.*throws a ReferenceError instead of exercising the validation.initialize()call rather than storing them in the editable Settings config, which leaves Settings and storage untouched. No other sample changes: the inbox screen already exists on main, and the empty state is reached by logging in with a profile that has no inbox messages.Verification
npm test— 25 passed (8 new)npx tsc --noEmit,eslint,npx api-extractor runall cleanNot covered
The Android mapper has no unit test. This package has no Kotlin test source set and no CI job that runs Gradle unit tests, so adding one is its own change rather than a rider on this PR. The equivalent mapper is covered on the Flutter side, and the placeholder validation — the part with real logic — is now in JavaScript, where Jest covers it.
🤖 Generated with Claude Code