feat(chat): suggest @mentions from the server's pool - #1647
Merged
Merged
Conversation
bmc08gt
force-pushed
the
feat/mention-suggestions
branch
from
October 1, 2026 18:34
0e7cfd6 to
9e8723c
Compare
bmc08gt
marked this pull request as ready for review
October 1, 2026 18:35
…ypes The composer's reply strip becomes one slot in an ordered accessory stack: mention suggestions, then the reply strip, then the input row. Both cards use the reply surface's enter and exit spring. The picker opens on the whitespace-free word ending at the cursor when it starts with "@" at the start of the text or after whitespace, so "a@b" never opens it. It searches RosterSearchSource with that word, cancelling the last search when the word changes, and lists only members with a username. It is for groups only and closes on whitespace, a moved cursor, a deleted "@", a send or a pick. A pick replaces the word with "@username " as plain text. The first page of the roster is refreshed once per screen visit, the first time the picker opens. The list shows up to 4 rows, 3 with a reply strip open, and 2 when that many would leave the transcript under 120dp. Row values come from the prototype; the visual pass against the design is still to do.
… loads The first-page roster refresh runs in the background the first time the picker opens, so its results reached the list only on the next keystroke. When it succeeds, the open word now searches again, so a member who joined since the last read shows up without more typing. A refresh that lands after the list closed leaves it closed.
Rows take the design's metrics (mention row set, node 10633:68; spec, node 10662:64911): 14dp side padding and a 10dp gap, dividers inset 56dp so they start under the name, the display name at 12/16 bold in the member's own colour from the palette the reply strip uses for a quoted author, and the username at 14/18 medium in #EBEBF5 at 60%. The card keeps the reply strip's radius and hairline so the two stacked cards match, and avatars without a picture keep the app's shared initials fallback.
Picking a member before an existing space or newline added a second space. The mention now takes no trailing space when whitespace already follows the word, and the cursor lands after that whitespace. At the end of the text or before any other character it still adds one.
The input field paints ChatInputDefaults.ContainerColor over its haze; the mention card and reply strip had the haze alone, so on the Seeker they sampled rgb 25 against the field's 30. Both now paint the same constant over the same haze.
Wire Chat.GetMentionSuggestions through ChatApi, ChatService, ChatRepository and ChatController. ServerRosterSearchSource, the only RosterSearchSource, fetches the pool once per composing session, filters it locally with a word-prefix rule while keeping the server's order, and moves each new message's sender to the front from the event stream. A failed fetch (DENIED, NOT_FOUND, transport) returns an empty result with no fallback; the user can still type a handle by hand.
Opening the mention list or the reply strip moved the transcript to its final inset on the first frame, ahead of the card. AnimatedVisibility's expandVertically reports the finished size to the lookahead pass, and the scaffold insets the transcript from that pass. ComposerAccessorySlot sizes the card from the reply spring in every pass instead, so the card, the input row and the transcript share one height each frame. The bar's fade was sized from the bar's height a frame late, which held the composer one frame high whenever a card above it closed. It now matches the bar's size. The mention list's height follows the rows on show, on the same spring: a narrower query shrinks the card instead of cutting rows, and opening the reply strip takes a row (4 to 3) without a jump. Dropped rows fade and the rest slide up into the gap. When the matches change, the list goes back to the top; keeping the old row in view scrolled the list while the card grew from 1 row to 4.
bmc08gt
force-pushed
the
feat/mention-suggestions
branch
from
October 2, 2026 13:17
9e8723c to
64d55ee
Compare
The server's pool is shown without a membership check, so a person it offers after they left the group still appears.
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.
Adds the @-mention picker to the group-chat composer, backed by the server's ranked pool from
Chat.GetMentionSuggestions(flipcash2-client-protocol 0.15.0, code-payments/flipcash2-client-protocol#22).ChatControllerwraps the RPC.ServerRosterSearchSourcefetches the pool once per composing session, filters it locally as the user types in the server's order, and moves the sender of each new message to the front throughMentionSuggestionPool, fed fromEventStreamDelegate.DENIEDorNOT_FOUNDreturns no suggestions. There's no local fallback, so the user can still type a handle by hand.RosterSearchSourcestays as the seam, with the server pool as its only implementation.MentionTextcarries the NFKD/lowercase folding used for local filtering.This doesn't depend on roster sync.
Chat.GetRosterstays private, #1622 is closed, and no Room schema or migration ships here.