feat(react-native-uikit-docs): Pin & Save, Pin Conversation and Thread Subscription - #536
Conversation
…d subscription
The React Native UI Kit shipped Pin Message, Save Message, Pin Conversation and
Thread Subscription in v5.5.0, but the docs only covered the two panel components.
This brings React Native to parity with the Android and React kits.
Core features (ui-kit/react-native/core-features.mdx)
Three sections, placed in the same order Android uses:
Mentions -> Pin & Save Messages -> Pin Conversations -> Rich Text Formatting
Threaded Conversations -> Thread Subscription -> Group Chat
Thread Subscription sits directly after Threaded Conversations, matching Android.
New guides
guide-pin-and-save-messages.mdx modelled on the React guide
guide-thread-subscription.mdx modelled on the Android guide
Both are wired into docs.json in Android's relative order — threaded-messages,
then thread-subscription, then pin-and-save.
Thread header component (threaded-messages-header.mdx)
Adds a Thread Subscription section, mirroring the React thread-header page.
Two platform differences are documented rather than copied over:
* The bell is on CometChatMessageHeader, NOT CometChatThreadHeader. React puts
its toggle on the thread header; the landed React Native design places it in
the thread screen's top bar, driven by `parentMessage` +
`threadSubscriptionVisibility`. CometChatThreadHeader's TrailingView is the
escape hatch for a custom control there and does not host the bell.
* Thread Subscription is ON by default on React Native and has no dashboard
flag, so it is documented as opt-OUT via ThreadSubscriptionConfig.setEnabled(false).
Android documents the same feature as opt-in because its default differs.
The text matches what v5.5.0 actually ships and the published release notes.
Pin is documented as available to every member with the server enforcing
permission, matching React — the React Native role gate was removed in ENG-38197,
so canPin() now only asserts that somebody is logged in.
Verified: 0 dangling navigation refs, and 100 internal links across the changed
files all resolve.
The section had drifted from the Android original: different table headers (Components/Functionality vs Component/Role), a shortened link label, and two extra paragraphs about the dashboard flag and server-owned ordering. Now byte-identical to ui-kit/android/core-features.mdx, with only the platform path in the link differing.
…ve and Thread Subscription Pin Conversations was aligned in 984ef98; these two had drifted the same way — "Components/Functionality" table headers instead of "Component/Role", shortened link labels, and extra "Hide it with ..." clauses and paragraphs Android does not carry. Both now follow the Android sections verbatim. Three differences remain, each a real platform fact rather than drift: * Pin & Save — "Pinned messages entry point", not "menu entry point": on React Native it is a header button (showPinnedMessagesButton), not a menu item. * Thread Subscription — "Enabled by default" rather than Android's "Opt-in". React Native ships ThreadSubscriptionConfig with enabled = true. * Thread Subscription — the bell is on CometChatMessageHeader, not CometChatThreadHeader, per the landed React Native design.
…nedMessages prop table
…vedMessages prop table
Removes all 12 mentions across four pages. Thread subscription is now documented
purely through its two per-surface props:
hideThreadSubscriptionOption CometChatMessageList
threadSubscriptionVisibility CometChatMessageHeader
message-list.mdx dropped the opt-out paragraph, the TypeScript/JavaScript
tabs that only demonstrated setEnabled, and the mention
in the hideThreadSubscriptionOption prop description
guide-thread-subscription "Enable the Feature" rewritten around the two props
threaded-messages-header dropped the global row from the controls table
core-features points at the two props instead
The feature is still described as enabled by default, which is what 5.5.0 ships.
… Android
The five bullets specify per-section references, and Pin & Save in core features
is a React one — it had been switched to Android's format along with the other
two sections.
Now follows ui-kit/react/core-features.mdx: React's heading ("Pin and Save
Messages"), intro, Components/Functionality table, and — the part Android's
version does not carry — the app-settings limits table and its closing paragraph
on cap toasts.
Five deliberate differences:
* the Storybook <Info> + <iframe> block is dropped; React Native has no
Storybook to embed
* the #pin-and-save-options deep link is dropped; that anchor does not exist on
the React Native message-list page
* "message options menu" -> "message options": React Native uses an action sheet
* "panel" -> "screen": React Native navigates rather than opening a panel
* the Conversations row is dropped; Pin Conversations is its own section here,
per the Android reference, so listing it twice would duplicate
The heading change moves the anchor, so the inbound link in the guide is updated
to #pin-and-save-messages — which is also React's own anchor.
…has it
CometChatThreadHeader was carrying the thread-subscription section, but on React
Native it renders no bell — the control belongs to CometChatMessageHeader, which
said nothing about it. Every other platform documents the bell on the component
that owns it: React and Android on their thread header, iOS on both because iOS
supports both.
message-header.mdx gains two sections, with worked examples:
Pinned Messages showPinnedMessagesButton (OFF by default) and
onPinnedMessagesPress. The guide tells integrators to use
these while the component's own page never listed them.
Thread Subscription parentMessage as the thread-mode switch that renders the
bell, threadSubscriptionVisibility, and
onThreadSubscriptionChange — the last of which was
undocumented anywhere, though React documents its own.
Both toggles are added to the Visibility Props table too.
threaded-messages-header.mdx keeps a Thread Subscription section, but it is now a
pointer rather than a duplicate: it states plainly that this component renders no
bell, shows the two components side by side as a thread screen actually composes
them, and links to the message header for the props. Its TrailingView note stays —
that slot is the escape hatch for a custom control and is easily mistaken for the
bell's home.
All five props shipped in 5.5.0 are now documented on the component that has them.
…ubscription section Leads with where the bell is rather than where it is not.
Thread subscription was a top-level entry in both places. It belongs inside threaded
messages, which is how the other kits structure it.
Core features
`## Thread Subscription` becomes `### Thread Subscription` inside
`## Threaded Conversations`, matching iOS — its core-features page nests the same
section at h3 under the same parent.
Guides
The standalone guide-thread-subscription.mdx is removed and its content folded into
guide-threaded-messages.mdx as a `## Thread Subscription` section, matching React —
its threaded-messages guide carries the feature with the same three subsections:
Automatic subscription
Reacting to changes
Hiding the controls
The React Native text differs where the platform does: the bell is on
CometChatMessageHeader rather than the thread header, and CometChatMessageList takes
the whole `parentMessage` rather than an id, since a reply arriving over the socket
carries no subscription flag of its own and is stamped from the parent.
onThreadSubscriptionChange is documented here as well as on the component page —
React documents its own equivalent in both places.
The nav entry is dropped and all three inbound links now point at
guide-threaded-messages#thread-subscription.
Verified: 0 dangling navigation refs, and 413 internal links across the React Native
pages all resolve.
The React component pages carry a live Storybook iframe so a reader can see the panel before wiring it up. There is no React Native Storybook to embed, so these pages had no visual at all — and neither do Android's or iOS's. Static screenshots are the closest equivalent. pinned-messages.mdx the Pinned Messages screen saved-messages.mdx the Saved Messages screen guide-pin-and-save-messages.mdx both, beside the step that builds each screen Placed right after "Where It Fits", which is where React puts its preview. Each carries descriptive alt text rather than a label. React's iframe has none, and on these pages the screenshot is the only visual explanation of what the feature looks like — so it needs to work for a reader who cannot see it. Verified: all four references resolve, and 175 image references across the React Native pages were checked. The one miss, compact-message-composer-overview.png, is untouched by this branch and is already broken on main.
The pin & save pages documented kit-internal plumbing alongside the public surface. Nothing here is API a customer writes against: - `## Enabling the feature` (PinSaveConfig / getPinSaveFeatures / refreshPinSaveFeatures) — the kit resolves these itself at login and re-reads them on every reconnection (CometChatUIKit onLoggedIn + ConnectionListener.onConnected), so there is nothing to call. The page's opening <Warning> already states the Dashboard requirement. - `## Reading pin state yourself` / `## Reading save state yourself` (isPinned / isSaved / isSystemPin / SYSTEM_PINNER) and the matching "helpers" blocks in the AI Integration Quick Reference accordions. - Two implementation asides: how the panel routes local vs SDK save events, and that the RN SDK has no isPinned() of its own. Also corrects a stale instruction on conversations.mdx: Pin Conversation no longer needs `PinConversationConfig.enable(true)` from the integrator — PinSaveFeatureGates applies it from the server flag. The <Warning> framed it as a required setup step, so anyone following it was writing dead code. React, Android and iOS document none of these APIs; this brings React Native into line. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ndard Both pages were missing sections every other React Native component page has, and ordered the ones they did have differently. They now follow the house order used by conversations / message-list / users / groups: Where It Fits -> Minimal Render -> Actions and Events -> Custom View Slots -> Common Patterns -> Styling -> Props -> Next Steps Added: - `## Styling` with a worked example and a Style Properties table for every key of PinnedMessagesStyle and SavedMessagesStyle, including `closeButtonIcon`, the saved row's `previewIconStyle`, and the empty/error state styles. None of this was documented; the pages just listed `style` as one row with an opaque DeepPartial type. - `## Custom View Slots` for ItemView, noting that empty/error/loading are restyled rather than replaced on these two components. - `## Opening from the Message Header` (pinned), stating that `showPinnedMessagesButton` adds an item to the header's overflow menu rather than rendering a standalone button, and that it is a silent no-op without `onPinnedMessagesPress`. - Per-prop `### name` entries with Type/Default tables, replacing the single flat table — matches every other RN component page. - The SavedMessageSource field table, so `onItemPress`'s second argument is usable. The type is not exported from the package, so the example no longer annotates with it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1. (must) Saved Messages guide read `source?.user` / `source?.group`,
which SavedMessageSource does not have — it is
{ receiverType, receiverId, label, name, avatar? }. The snippet failed
typecheck and at runtime navigated with both undefined. Now resolves
the User/Group from receiverId + receiverType before navigating, and
the prose lists the real fields.
2. (should) Threads guide wired `onThreadRepliesClick`; the RN prop is
`onThreadRepliesPress` (CometChatMessageList.tsx:346), so navigation
to the thread screen never fired. Renamed in all 3 places.
3. (should) Both guide screens passed `messageId` back to Messages with a
"jump to this message" comment, but the Complete Example never used
it. Wired `goToMessageId` on CometChatMessageList, which is the prop
that actually performs the jump.
Nits 4-6 deliberately left for a follow-up.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
React has a Custom Text Formatter guide that builds a color button in the
composer toolbar. React Native had no equivalent, and its toolbar slot
was undocumented even though it shipped in 5.5.0.
- New guide `guide-text-color`: a swatch color button in
`ToolbarTrailingButtonsView`, driven by the `composer` handle's
`applyInlineStyle("color", …)`. Based on the masterapp sample covered
by e2e/color-richtext.e2e.js. Unlike React, no custom formatter is
needed: color is part of the built-in rich-text wire format
(`<color=#rrggbb>`), and CometChatRichTextFormatter already renders it.
Documents what does not survive send: backgroundColor, color inside a
code block.
- compact-message-composer: `ToolbarTrailingButtonsView` slot row,
section with example, and the `ComposerInputHandle` method table.
- Fix the Toolbar Visibility Modes table, which was inverted. The
toolbar renders when `enableRichTextEditor && !hideRichTextFormattingOptions`
(CometChatCompactMessageComposer.tsx), so `hideRichTextFormattingOptions`
true hides it. The new guide depends on this being right.
- Nav entry after Pin & Save (matches React's placement) and a row in
the guides overview.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
… matching React The base-class guide already used that title in the same sidebar group, so it gets sidebarTitle "Text Formatter Base Class" to avoid two identical entries. Cross-links and the guides overview updated to the new names. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…lpha Verified against the 5.5.0 native editors: applyInlineStyle with no selection arms the color for the next typed text (RichTextEditorView.kt applyInlineStyle, RichTextEditorView.swift applyInlineStyle), and the reported color is masked to 6-digit hex (hexOf: #%06x), so alpha is lost. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The guide's example kept the picker's open state inside a child component. CometChatCompactMessageComposer mounts ToolbarTrailingButtonsView as a component, and an inline render function is a new function on every host re-render, so that child remounted and the picker closed on its own. The masterapp sample (Messages.tsx, covered by e2e/color-richtext.e2e.js) keeps colorPickerOpen in the screen; the guide now does the same, with the same swatches, code-block disable and clear button. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
React's Custom Text Formatter guide builds an app-owned color formatter: a marker the
integrator defines, a toolbar button that writes it, and a formatter that renders it
everywhere the message appears. React Native had no equivalent — only the built-in
rich-text route in guide-text-color, where the UI Kit owns the format.
This adds the twin, section for section, with the SAME marker React publishes —
{color=#e5484d}...{/color} — so one token works across platforms with a matching
formatter on each.
The React Native mechanism differs where it has to:
React React Native
format() -> <span style> formatRawText() -> <color=...>
priority = 20 runs before markdown automatically
toolbarTrailingView ToolbarTrailingButtonsView + composer.replaceSelection()
- handlePreMessageSend() for the round trip
formatRawText() is the part that makes it reliable: it receives the raw string before the
built-in Markdown formatter runs. A formatter that only overrides getFormattedText() is
handed JSX instead, so it silently does nothing on any message containing _, **, '- ', [
or a backtick.
Verified: the guide's own code block was extracted and run against the release branch —
6-digit hex, 3-digit hex and named colors all render, markdown around the marker is
unaffected, and handlePreMessageSend round-trips <color=...> back to {color=...}. Every
symbol used is exported from the package, and all four internal links resolve on this
branch.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The hashtag example did its matching in getFormattedText(). That method runs AFTER the
built-in Markdown formatter, which hands it JSX rather than a string — so the guide's own
first line returned early and the formatter did nothing.
Run verbatim from the live page, against the shipped kit:
hashtag styled: YES "hello #world"
hashtag styled: NO "hello #world _ok_"
hashtag styled: NO "hello #world **bold**"
hashtag styled: NO "- hello #world"
hashtag styled: NO "hello #world `code`"
hashtag styled: NO "hello #world [a](b)"
It works only on a message with no Markdown at all — which is exactly what someone tests
first, so the failure ships.
The matching now happens in formatRawText(), which receives the raw string before any UI
Kit parsing and returns markup the kit already draws. Same six inputs, after:
styled: YES every one, {"color":"#5dff05","fontWeight":"700"}
Changes:
- Step 2 and 3 rewritten around formatRawText; a Warning explains why getFormattedText is
the wrong place, so nobody reintroduces it
- Example is a complete, copy-pasteable pair of files, with the formatter registered on the
message list, the composer and the conversation list
- formatRawText added to the base-class listing and the methods table
- Links to the new color formatter guide
Structure follows the React and Android formatter guides; the mechanism is ours.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Switches the marker in the color formatter guide from {color=#hex} to {color:#hex}, as
decided.
Only the APP-owned marker changed. The UI Kit's own <color=...> markup is untouched — the
formatter still maps to it, because that is the one color syntax the React Native renderer
understands.
Verified by extracting the guide's code block from the .mdx and running it against the
release branch: 6-digit hex, 3-digit hex and named colors all render, markdown around the
marker is unaffected, and handlePreMessageSend round-trips to {color:#e5484d}world{/color}.
NOTE for whoever picks up cross-platform parity: React and Angular both publish
{color=#hex} today (ui-kit/react/guide-custom-text-formatter.mdx and
ui-kit/angular/guides/custom-text-formatter.mdx). Android publishes no color marker at all.
With this change React Native differs from React and Angular by one character, so those two
guides need the same switch for the token to be shared across platforms.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…arker" This reverts commit a316c0f.
…pping alpha
The regex was /{3,6}/ while React and Angular publish /{3,8}/. A message written on the web
with an alpha color — {color=#e5484dff}text{/color} — did not match here, so the marker was
left untouched and the reader saw the raw text rather than colored text.
Now /{3,8}/, with the alpha dropped before the value reaches the UI Kit:
#rgba -> #rgb
#rrggbbaa -> #rrggbb
That step is needed because the UI Kit renders #rgb and #rrggbb only, and an unrecognised
value is not silently uncolored — it leaves the raw <color=...> tag visible in the message,
which is the worse failure.
Verified by extracting the guide's code from the .mdx and running it against the release
branch — all five forms the marker allows now render:
3 #rgb -> #f00
4 #rgba -> #f00
6 #rrggbb -> #e5484d
8 #rrggbbaa -> #e5484d
name -> #e5484d
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…tter', as React does Three React Native pages all carried title: "Custom Text Formatter", and the sidebar name was held by guide-text-color — the page whose own first section says "In React Native you do not need to write a text formatter for this". The one page that IS React's counterpart was called "Color Formatter". Sorted out so each page is named for what it teaches: guide-color-formatter Custom Text Formatter <- matches React and Angular guide-text-color Text Color <- built-in toolbar, no formatter custom-text-formatter-guide Text Formatter Base Class <- the base class guide-text-color also had title: "Custom Text Formatter", which is now "Text Color" — three pages sharing one title made them indistinguishable in search. Also updated the link TEXT that still called guide-text-color the Custom Text Formatter guide, in compact-message-composer and guide-overview, and added the new guide to the guide-overview table, where it was missing. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ct's parity
Four public APIs land in the React Native UI Kit that the docs never mentioned,
three of which React has documented since its own pin/save shipped. Reading only
the React Native docs, an integrator could not discover any of them.
messagesRequestBuilder CometChatPinnedMessages, CometChatSavedMessages
textFormatters the same two, plus CometChatSearch and
CometChatMessageInformation
replaceSelection(text) ComposerInputHandle — the one method the color
formatter guide already tells the reader to call
onError(e) CometChatGroupMembers now receives the exception
Pinned and Saved each gain a Filtering section and two reference entries,
matching React's pinned-messages / saved-messages pages heading for heading. The
prose is React Native's own, because the two kits differ where it matters: the
builder methods are setPinnedOnly() / setSavedOnly(), the component works on a
prototype-preserving COPY so one builder can feed both panels, the limit falls
back prop -> builder -> 30, and the saved panel clears any uid/guid because a
save is account-wide. All four are stated, since each one is a way to be
surprised.
CometChatMessageInformation had no v5 page at all — only the v4 one — while
React, Angular and Vue all carry theirs, so its new textFormatters prop had
nowhere to live. Added the page: what it shows for a group (server receipts, one
row per recipient) versus a one-on-one (the timestamps already on the message),
why you normally do not render it yourself, and the one case where you must pass
textFormatters — a standalone screen, which has no template to inherit them
from. Its style type is spelled DeepPartial<CometChatTheme["messageInformation
Styles"]> and the ListItemView receipt shape is written out, because neither
MessageInformationStyle nor Recipient is an exported name.
Verified against the shipping source on bugfixes/release-2026-09-week-4-v5, not
from the commit messages: every prop read off its own interface, the builder
invariants off buildPinnedMessagesRequest / buildSavedMessagesRequest, and
setPinnedOnly/setSavedOnly confirmed public in the SDK's CometChat.d.ts. Both
Accordion JSON blocks and docs.json re-parse, and every internal link in the
seven files resolves to a page that exists.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Both the composer snippet in Step 3 and four of the five components in Step 4
were written with `user={user} group={group}` on the same element. They are
mutually exclusive on every one of those components — CometChatPinnedMessages
picks the group and ignores the user, and a reader following the guide's own
instruction to copy the block gets a panel scoped to the wrong conversation with
nothing on screen saying why.
This guide exists to be pasted, so it now shows one scope with the alternative in
a comment.
Verified the rest of the guide by running it: ColorFormatter.ts extracted
verbatim from this page, with only its import path redirected to the real class,
passes 24 assertions through the shipping code — the bubble, conversation-row and
search chains each render red for the plain example and for text that also
carries bold, italics, a link, a bullet and a code span; alpha hex narrows to
what HEX_COLOR_REGEX accepts; an unknown color name leaves the marker alone
instead of leaking a raw <color=> tag; and handlePreMessageSend converts the kit
token back to the marker. Also confirmed against source that the toolbar hosting
the button is on by default, that a consumer's array is added to the built-in
formatters rather than replacing them, and that a formatter with no tracking
character is keyed by id so its send hook still runs.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
….5.1
The blocking item is retired by the release, not by an edit. Every API the review
called "5.5.1-only, unreleased" is in the published tarball, which is now npm
`latest`: formatRawText (CometChatTextFormatter.ts:235), replaceSelection
(compact composer :566, :3652), textFormatters on Pinned, Saved, Search and
MessageInformation, messagesRequestBuilder on Pinned and Saved, and
GroupMembers `onError?: (e: CometChat.CometChatException) => void` (:190). The
review's own remedy was "hold until 5.5.1 is on npm"; that has happened, so no
version callouts were added — no RN page carries one, and inventing the
convention here would be inconsistent.
Everything else was checked against that same tarball and fixed:
* Moderation. isPinSaveEligible() explicitly allows `pending`
(PinSaveHelper.ts:308) — the guide claimed the options were hidden until a
verdict arrived. Rewritten to say what the kit does: offer the option, let the
server refuse, render the refusal.
* ThreadSubscriptionConfig. Still exported, still ON by default
(ThreadSubscriptionHelper.ts:82-102), and setEnabled(false) is the only
app-wide opt-out — it was undocumented anywhere after the rewrite. Documented
on message-list beside hideThreadSubscriptionOption, with the AND relationship
between the two spelled out.
* The pinned entry point is a ⋮ overflow-menu item, not a button
(CometChatMessageHeader.tsx:343-346 pushes `{ text: 'Pinned Messages' }` into
the options list), and needs BOTH showPinnedMessagesButton and
onPinnedMessagesPress — setting one does nothing. Corrected in all four places.
* Menu labels are "Subscribe to thread" / "Unsubscribe from thread"
(translation.json:231-232), not Follow / Unfollow.
* SavedMessageSource is not exported from the package root, so the callback's
parameter is now shown as an inline type with its real fields instead of a name
a reader cannot import.
* The five pin/save helpers — isPinned, isSystemPin, isSaved, getPinSaveFeatures,
refreshPinSaveFeatures — are all still exported and correct. Restored as a
Helpers section, with a note that refreshPinSaveFeatures is not needed in
normal use because the kit re-resolves on every reconnect.
* custom-text-formatter-guide: title was "Custom Text Formatter", the same as
guide-color-formatter — now "Text Formatter Base Class", matching its own
sidebar entry. The stray top-level `<CometChatConversations …/>;` expression is
now a comment, since it was neither valid at that position nor part of the
component above it.
Checked after the edits: every in-page anchor on the five files resolves to a
heading that exists, every internal link resolves to a page that exists, and the
Custom Text Formatter title collision is gone.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The last nit from the review that cc26136 missed: both guides declared `function ChatScreen({ user, group })` in a .tsx block, which is an implicit-any error under the strict settings the rest of the samples assume. Annotated with the SDK types, and guide-text-color gains the `CometChat` import the annotation needs — custom-text-formatter-guide already had it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…othing Self-review of #516 against the published 5.5.1 tarball. Three props were documented as working that the component never reads — each is declared in CometChatMessageInformationInterface, destructured at the top of the component, and then not referenced again. emptyStateText removed. The default empty view is `<></>`; there is no string to override (:343-346). errorStateText removed. The error view hard-codes t("WRONG_TEXT") and t("WRONG_TEXT_TRY_AGAIN") (:329-330). onBack kept, with a warning. Unlike the other two it appears in both code samples and in the public type, so removing it silently would leave a reader to rediscover it in autocomplete with no explanation. The screen renders no back control at all — its header is a centred <Text> (:350-354) — so the page now says plainly that 5.5.1 accepts the callback and never calls it, and to give the screen a navigator that provides its own back. Two smaller corrections on the same page: * The default title was documented as Localized "Message Information". The en bundle maps MESSAGE_INFORMATION to "Message Info" (translation.json:278). * EmptyStateView was described as replacing the empty state. There is no default empty state to replace — without the prop the screen renders nothing in that condition — so it ADDS one. Found by checking each documented prop's occurrence count in the shipped source rather than trusting the interface: a prop that appears exactly twice is declared and destructured and never used. onBack surfaced from that same check while verifying the first two fixes. The new #onback anchor was checked against IDs scraped from the rendered preview, not a slug rule. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… the opt-out
Three things from jitvarpatil's review, plus a build break my previous commit
introduced and the review predates.
## The deployment was failing — message-information.mdx
"Failed to parse page content: Unexpected end of file in expression, expected a
corresponding closing brace for `{`". The cause is one table row:
| Type | `(… receipt: { sender: CometChat.User | CometChat.Group; … })` |
Markdown splits a table row on unescaped pipes BEFORE inline code is parsed, so
the `|` inside the backticks cut the code span in half. The left fragment ends
with an open backtick and an unclosed `{`, which MDX then reads as a JSX
expression that never closes. Escaped as `\|`, the form already used on the
saved-messages page.
Worth recording how it was found: a per-line brace check said the file was
balanced, because it stripped intact inline code — and the span only breaks
AFTER markdown splits the row. The check that finds it splits each table row on
unescaped pipes first, then looks for a cell with an odd number of backticks.
That sweep now runs over every changed page; this was the only occurrence.
## Version notes (blocker 1)
`replaceSelection`, `textFormatters` on Pinned/Saved/Search/MessageInformation,
and `messagesRequestBuilder` on Pinned/Saved all landed in 5.5.1. 5.5.1 is npm
`latest`, but nothing told a reader still on 5.5.0 why the samples fail, and on
that version the colour guide's Step 4 silently renders the raw marker on four of
five surfaces — the exact failure that section warns about.
Each note names only the APIs that are actually 5.5.1-only on that page, and says
the rest of the page works on either version. The colour-formatter guide is the
exception: it is built on the new hook end to end, so the whole guide needs 5.5.1
and the note says so.
I declined this when raj-dubey1 first raised it, reasoning that 5.5.1 being
`latest` made it moot and no RN page carries a version callout. Two reviewers
asking for the same thing is the answer: a reader on a pinned 5.5.0 has no other
way to find out.
## App-wide thread-subscription opt-out (should-fix)
`ThreadSubscriptionConfig.setEnabled(false)` was documented on message-list in
cc26136, but a reader wanting the feature off app-wide looks in the threaded-
messages guide, next to the per-surface flags. Added there as "Turning the feature
off app-wide", with the actual gate expression the bell evaluates.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…nformation page
The page had drifted into the worst of both: two samples passing
`onBack={() => navigation.goBack()}`, and three separate notices saying the
callback is never invoked. It told a reader to use the prop and then told them
three times that it does nothing.
Customer docs describe the product, not its defect list, and "not called in
5.5.1" is prose that rots the moment the kit wires it up. Removed all of it —
the JSON entry, the Actions and Events section, the props entry, and the prop
from both samples.
In its place, one positive sentence that answers the question the warnings were
circling: the screen draws no header controls of its own, so put it on a route
whose navigator supplies the back affordance, or render it in a sheet you close
yourself. That is true on any version and needs no correction when onBack starts
working — only an addition.
The underlying defect is a kit issue, not a docs one: onBack, emptyStateText and
errorStateText are all declared in CometChatMessageInformationInterface,
destructured, and never read. Raising separately.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
@jitvarpatil @raj-dubey1 — ready for re-review. Everything from both of your reviews on #516 is addressed here. Why the PR number changed: the branch was @jitvarpatil
You were right on the version notes and I'd argued against them when @raj-dubey1 first raised it — reasoning that 5.5.1 being @raj-dubey1Everything from your list landed in Found while verifying, not in either review
Checks: |
…guide The page already carried React's title, sidebar title and all eight headings verbatim. The URL was the last thing that differed: react /ui-kit/react/guide-custom-text-formatter react-native /ui-kit/react-native/guide-color-formatter <- now matches Renamed the file and repointed all three references — the docs.json nav entry, the table row in guide-overview, and the Card in custom-text-formatter-guide. No redirect needed: the page is added by this PR and has never been published, so the old slug has no live URL to break. Checked against main before renaming rather than assuming. Verified after: docs.json parses, every react-native nav ref resolves to a file that exists, and no internal link on any react-native page points at the old slug. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…act and Android do Both reference platforms use the same name for this page, and React Native was the only one that didn't: react ui-kit/react/plugins/text-formatters "Text Formatters" android ui-kit/android/customization-text-formatters "Text Formatters" RN custom-text-formatter-guide "Text Formatter Base Class" <- renamed With the previous commit that makes the pair line up across all three: this page is "Text Formatters", and the worked guide beside it is "Custom Text Formatter" on every platform. Retitled the page and updated all 11 occurrences of the old label across 7 files, so link text matches the page it points at rather than naming something that no longer exists. Also renamed the one section heading React has a direct counterpart for — "Base Class Overview" -> "The Formatter Interface"; nothing linked to the old anchor. The SLUG is deliberately unchanged. It is published on main with 25 inbound references, so renaming needs a redirect — and there is no single slug to match anyway, since React uses plugins/text-formatters and Android uses customization-text-formatters. The visible name is what a reader navigates by. Full heading parity would be a content rewrite, not a rename: React's page also documents the built-in formatters, which React Native splits into its own mentions/URL/shortcut pages. Left alone. Verified: no duplicate titles across the react-native pages, every in-page anchor and internal link still resolves, docs.json parses. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
969aa91 renamed guide-color-formatter.mdx to guide-custom-text-formatter.mdx but shipped ONLY the rename. docs.json line 1214, the guide-overview table row and the Card in custom-text-formatter-guide were all left pointing at a file that no longer exists — a dangling nav ref, which is a build break, plus two 404 links. My mistake, twice over. The `git add` that was meant to stage them listed the old path as well; that path was gone after `git mv`, so git rejected the whole pathspec and staged nothing — and `2>/dev/null` swallowed the error. Then I read the `git status --porcelain` output as confirmation, missing that a leading space means UNSTAGED: only the `R ` row was staged, the three ` M` rows were not. The `git reset --hard` at the start of the next turn then discarded them. The check that would have caught it existed and ran — it reported `guide-overview.mdx -> /ui-kit/react-native/guide-color-formatter` — but it ran in the same command as the commit, so I saw the failure only after pushing. It now gates the commit instead of reporting beside it. Verified before committing: every react-native nav ref resolves to a file that exists, and every in-page anchor and internal link across the react-native pages resolves. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Verified each finding against the shipped source before changing anything; two of the five do not apply to these pages. ## Thread subscription default was stated without a version iOS gates it from v5.2.0 and Android from v6.1.0, while React Native said only "Enabled by default". For React Native the flip landed in `48ff1569` and first shipped in **v5.5.0** (`git tag --contains` gives v5.5.0, v5.5.1). Both places that state the default now say so, and core-features also points at `ThreadSubscriptionConfig.setEnabled(false)` as the app-wide opt-out. ## Step 5 renamed and corrected React's #518 deliberately renames this section to "App Settings and Limits"; React Native still had the older "Step 5: Limits". Renamed, and brought over the app-settings table so both pages name the same six `features.ux.*` keys. The bigger problem was the sentence under it. It said the toast carries "the server-provided limit" and implied a number is always present. `resolveCapLimit` (PinSaveHelper.ts:405-460) says otherwise: `errorParams.limit` is "documented, but rarely present", the usual source is the app settings cached at login, and the function returns NULL when neither has a value — deliberately, so callers show copy without a figure "rather than printing a guess". The SDK agrees: ErrorModel.ts warns "Do NOT assume a cap breach carries its limit" (ENG-37690). Now describes both sources in order and adds a Note that the toast may name no number at all. ## Two findings that are not ours * Error codes — the review is right that `ERR_PERMISSION_DENIED` is the RBAC/SBAC denial code (ErrorModel.ts:18 documents it carrying `{action, role, restrictionSource, guid, scope}`), and `ERR_SYSTEM_PINNED_CONVERSATION` does not exist anywhere in the React Native SDK. No react-native UI Kit page cites any of these codes, so there is nothing to fix here. The stale `ERR_ACTION_NOT_ALLOWED` reference is in the SDK's own pinMessage JSDoc (CometChat.ts:2365) — an SDK fix, not a docs one. * System vs user pin budgets — the SDK settles it: "system pins do not consume a user's allowance" (CometChat.ts:2564), so the budgets ARE independent and articles/error-guide.mdx is the page that is wrong. No react-native UI Kit page makes a claim either way. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
raj-dubey1
left a comment
There was a problem hiding this comment.
Approving. Every point from the #516 review is addressed, and @cometchat/chat-uikit-react-native@5.5.1 is now published as latest. I checked the 5.5.1 tarball: formatRawText, replaceSelection, textFormatters and messagesRequestBuilder on Pinned/Saved, textFormatters on Search and MessageInformation, and GroupMembers onError(e) are all present, and the pages carry clear "5.5.1+" callouts. The moderation note, ThreadSubscriptionConfig, the overflow-menu wording, titles, labels, the SavedMessageSource note and the helpers table are all fixed. Build is safe: 0 dangling nav refs, 0 broken links, images resolve.
Optional follow-ups (non-blocking):
- The
custom-text-formatter-guideandguide-custom-text-formatterslugs are easy to confuse. llms-react-native-v5.mdxdoesn't list the new pages and still says 5.4.0 (pre-existing).- The PR body still says "shipped in 5.5.0" and "read from 5.5.0 source".
🤖 Generated with Claude Code
jitvarpatil
left a comment
There was a problem hiding this comment.
Approving
Both blockers from #516 are cleared, and the should-fix was taken further than I asked.
1. Version mismatch — fixed thoroughly. All six affected surfaces carry an explicit 5.5.1 note, each naming the actual failure mode rather than hand-waving: compact-message-composer (composer.replaceSelection()), guide-custom-text-formatter (spelling out that on 5.5.0 the toolbar button does not compile and four of the five Step 4 surfaces silently render the raw marker), pinned-messages / saved-messages (messagesRequestBuilder + textFormatters), search and message-information (textFormatters).
2. Branch name — fixed. validate-branch-name passes; all other checks green.
3. The app-wide opt-out is now documented. guide-threaded-messages gains "Turning the feature off app-wide" with ThreadSubscriptionConfig.setEnabled(false), the import, and the real gate expression; core-features points at it. Verified in the published 5.5.0 tarball — private static enabled: boolean = true — so "Enabled by default from 5.5.0" is correct, and the source comment explains why the default flipped (RN's extra global gate defaulted to false, so identical integration code showed the control on web and nothing on mobile).
Spot-checks on the parity pass (af12d1d8)
resolveCapLimit in PinSaveHelper.ts does return null when neither errorParams.limit nor the cached app settings carry a figure, and readCapLimit's own comment says the cap is "Usually absent". So the corrected wording — the toast may name no number at all — is accurate where the previous text implied a number is always present.
Structure
- Nav: all three guides plus
message-informationwired in, no orphans; the rename left no staleguide-color-formatterreferences. - In-page anchors: 0 unresolved across every React Native page, checked with Mintlify's slug rule (a dot in a numbered heading becomes a hyphen — a GitHub-style slugger strips it and reports false passes).
- The two similarly-named formatter pages mirror React's own slugs, so the parity claim holds.
Thanks for the care on the version notes in particular — they turn a silent runtime failure into something a reader can diagnose.
The two cross-platform findings in af12d1d8 that belong to other pages (the error-guide pin-budget statement and ERR_SYSTEM_PINNED_CONVERSATION) I have carried over to #517, with the published-SDK evidence.
… React's #518 React's open PR #518 rewrites its custom text formatter guide to store colored text as `{color:#e5484d}text{/color}` — a colon, not the equals sign its merged page still publishes. The marker is app-owned and travels on the message as plain text, so a React Native app writing `{color=…}` would show as raw text in a React client reading `{color:…}`. Same class of break as the Web/React Native mismatch in Rekha's ticket. All 8 occurrences switch: the prose in Steps 1 and 3, the <Warning>, the round-trip diagram, and the three code sites (COLOR_REGEX, handlePreMessageSend, replaceSelection). The UI Kit's own wire format `<color=#rrggbb>` is deliberately untouched — that one is fixed in richTextWireFormat.ts (COLOR_OPEN_TAG = '<color='), not app-owned, and #518 keeps its equivalent too. Also drops a comment claiming React and Angular publish the same pattern. Angular is not in #518's scope and keeps `{color=`, so the claim stops being true once this lands; replaced with a platform-neutral note. Verified by extracting COLOR_REGEX, KIT_REGEX and toKitHex from the edited page with a script and running them: 6 assertions green, including a negative control proving the old `{color=…}` form now passes through untouched. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
c287a0f
…when the component re-asserts them Both Filtering sections said opposite things about fifteen lines apart. The prose and the code comment told the reader the flag is mandatory — "without it the request is an ordinary history read", "// required" — while the Note below said the component re-asserts it "so those are safe even if you omit them". The Note is the correct one. buildPinnedMessagesRequest calls setPinnedOnly(true) and setSavedOnly(false) with no condition in front of them (PinnedMessagesHelper.ts:40-41), buildSavedMessagesRequest does the mirror (SavedMessagesHelper.ts:245-246), and CometChatPinnedMessages.tsx:252 is the only site the prop is used, so no builder reaches the SDK unprocessed. Proved it rather than reading it: three throwaway jest cases against the real helpers, all green. The load-bearing one passes a builder with setPinnedOnly(false) set deliberately and the built request still comes out pinnedOnly=true — the component overrides the caller, it does not merely fill a gap. The ambiguity is in the phrase itself. The FLAG is required — without it anywhere in the chain the SDK does an ordinary history read — but setting it YOURSELF is not, and "without it" reads as the second. Prose now recommends writing it for explicit intent and drops the claim that omitting it breaks the fetch. Same wording is on React's components/pinned-messages.mdx:206 and components/saved-messages.mdx:165, which is where I took it from. React's kit 7.2.2 re-asserts too — its own JSDoc says setPinned(true) is "re-asserted because without it this is an ordinary history read" — so that page has the same defect. Left for its owner alongside #518. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Brings the React Native UI Kit docs to parity with the Android and React kits for the four features shipped in
@cometchat/chat-uikit-react-native@5.5.0.Before this, React Native had the two panel component pages (
pinned-messages,saved-messages) but no core-features entries, no guides, and no mention of the thread-subscription bell anywhere.Core features
ui-kit/react-native/core-features.mdxgains three sections, placed in the same order Android uses:Thread Subscription sits directly after Threaded Conversations, as requested.
New guides
guide-pin-and-save-messages.mdxui-kit/react/guide-pin-and-save-messages.mdxguide-threaded-messages.mdx(thread-subscription section)ui-kit/android/guide-thread-subscription.mdxBoth are added to
docs.jsonin Android's relative order. Note RN keeps thread subscription insideguide-threaded-messages.mdxrather than as its own page, so there is noguide-thread-subscription.mdxon this branch.Thread header component
threaded-messages-header.mdxgains a Thread Subscription section, mirroring the React thread-header page.Two deliberate divergences from the reference platforms
These are real platform differences, documented rather than copied:
1. The bell is on
CometChatMessageHeader, notCometChatThreadHeader.React puts its toggle on the thread header. The landed React Native design places it in the thread screen's top bar, driven by
parentMessage+threadSubscriptionVisibility.CometChatThreadHeader'sTrailingViewis the escape hatch for a custom control there and explicitly does not host the bell. The section says so, so nobody goes looking for a prop that isn't there.2. Thread Subscription is ON by default on React Native, and has no dashboard flag — so it is documented as opt-out via
ThreadSubscriptionConfig.setEnabled(false). Android documents the same feature as opt-in because its default differs. The React Native text matches what v5.5.0 actually ships and the published release notes.Pin is documented as available to every member, with the server enforcing permission — matching React. The React Native role gate was removed in ENG-38197, so
canPin()now only asserts that somebody is logged in.Verification
docs.json— build is safedocs.jsondiff is 3 insertions / 1 deletion — no reformat churn🤖 Generated with Claude Code