feat(example): channel-specific nicknames in mentions - #3262
Conversation
Mentions can be searched and rendered by a per-channel nickname stored on the
channel member (`member.nickname`), while `mentioned_users` keeps the real user
id. Covers the autocomplete dropdown, the composer textarea and the message
list. Inert for members without a nickname, so stock behaviour is unchanged.
Built entirely on public API — no patches to stream-chat or stream-chat-react:
- NicknameMentionsSearchSource subclasses MentionsSearchSource and is injected
through `createMentionsMiddleware({ searchSource })`. It matches on nickname
locally and, above the 100-member local-search threshold, server-side via
`$or` over `name` and `nickname`. `$autocomplete` on a custom member field is
supported by the API, contrary to the base implementation's comment; note the
member sort is a key/value map (`{ user_id: 1 }`), not `{ field, direction }`.
The server response is flattened to `member.user` by the base, so nicknames
are harvested before that to keep them available for suggestions.
- Suggestion `name` is set to the nickname, which drives both the dropdown label
and the inserted text. This is load-bearing: the composition middleware drops
a mention whose `id`/`name` is absent from the text, silently.
- Mention display text is frozen into `message.text` at send time, so a
composition middleware records `mention_display_names` on the message. The
renderer resolves `@nickname` from that map with no member lookup, which is
what makes rendering work past the 100-member threshold. Trade-off: renaming
does not rewrite mentions in existing messages.
- renderText emits two entities per mentioned user (nickname and username) so
both tokens highlight, satisfying "mention by nickname OR username".
- `withNicknameMentions` wraps the app's existing message UI rather than
replacing it, so inline editing and nickname mentions coexist.
Writing a nickname for another member is a server-side operation;
`updateMemberPartial` from a browser client only writes your own membership.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Size Change: 0 B Total Size: 890 kB ℹ️ View Unchanged
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #3262 +/- ##
==========================================
+ Coverage 85.23% 85.30% +0.06%
==========================================
Files 509 509
Lines 15982 15982
Branches 5038 5038
==========================================
+ Hits 13622 13633 +11
+ Misses 2360 2349 -11 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Mentions can be searched and rendered by a per-channel nickname stored on the channel member (
member.nickname), whilementioned_userskeeps the real user id. Covers the autocomplete dropdown, the composer textarea and the message list. Inert for members without a nickname, so stock behaviour is unchanged.Built entirely on public API — no patches to stream-chat or stream-chat-react:
NicknameMentionsSearchSource subclasses MentionsSearchSource and is injected through
createMentionsMiddleware({ searchSource }). It matches on nickname locally and, above the 100-member local-search threshold, server-side via$orovernameandnickname.$autocompleteon a custom member field is supported by the API, contrary to the base implementation's comment; note the member sort is a key/value map ({ user_id: 1 }), not{ field, direction }. The server response is flattened tomember.userby the base, so nicknames are harvested before that to keep them available for suggestions.Suggestion
nameis set to the nickname, which drives both the dropdown label and the inserted text. This is load-bearing: the composition middleware drops a mention whoseid/nameis absent from the text, silently.Mention display text is frozen into
message.textat send time, so a composition middleware recordsmention_display_nameson the message. The renderer resolves@nicknamefrom that map with no member lookup, which is what makes rendering work past the 100-member threshold. Trade-off: renaming does not rewrite mentions in existing messages.renderText emits two entities per mentioned user (nickname and username) so both tokens highlight, satisfying "mention by nickname OR username".
withNicknameMentionswraps the app's existing message UI rather than replacing it, so inline editing and nickname mentions coexist.Writing a nickname for another member is a server-side operation;
updateMemberPartialfrom a browser client only writes your own membership.