Skip to content

feat(ios): @-mention picker in the composer (web parity)#274

Merged
haowei2000 merged 1 commit into
developfrom
claude/ios-mention-feature-54304f
Jul 19, 2026
Merged

feat(ios): @-mention picker in the composer (web parity)#274
haowei2000 merged 1 commit into
developfrom
claude/ios-mention-feature-54304f

Conversation

@haowei2000

Copy link
Copy Markdown
Collaborator

Problem

The iOS app could render incoming mentions (bubble highlighting) but could never send one: SendMessageRequest.mention_ids was never populated and the composer had no "@" typeahead. A message typed on iOS therefore never triggered a bot.

Changes

  • ComposerView: typing @ opens a picker over the channel's members plus the group tokens (@all/@bots/@humans/@here), ranked bots → groups → people, filtered by label/username; tapping a row inserts @label . The trigger token is detected assuming the caret sits at the end of the draft — SwiftUI's TextField exposes no caret position, and appending is where mobile typing overwhelmingly happens.
  • ChatModel: builds the mention pool from channel members, tracks picked mentions, and on send keeps only tokens whose @label still survives in the text, splitting them into mention_ids (real members) and mention_names (group tokens) — the same contract as the web MessageComposer.
  • DTOs: SendMessageRequest gains mention_names.
  • ChatView: wires the pool and pick callback into the composer.

Verification (live, kind stack)

Installed the build on an iPhone 17 simulator against localhost:30080:

  1. @ opens the picker with correct ranking; @bo filters down to bots.
  2. Sent @Codex reply with exactly: iOS mention test ok → API shows the persisted message with mentions: [Codex], and the gateway dispatched the bot (it answered [bot offline] — the Codex connector wasn't running, but the dispatch path fired, which never happened before this fix).
  3. Sent @bots → server expanded the group token to the channel's bot and dispatched.

xcodebuild (Debug, iOS Simulator) passes.

🤖 Generated with Claude Code

The iOS app rendered incoming mentions but could never send one:
SendMessageRequest.mention_ids was never populated and the composer had
no "@" typeahead, so a message typed on iOS never triggered a bot.

- ComposerView: "@" opens a picker over the channel's members plus the
  group tokens (@all/@bots/@humans/@here), ranked bots -> groups ->
  people; tapping a row inserts "@Label " (caret assumed at end of
  draft - SwiftUI TextField exposes no caret position).
- ChatModel: builds the mention pool from channel members, tracks picked
  mentions, and on send keeps only tokens still present in the text,
  splitting them into mention_ids (members) and mention_names (group
  tokens), same contract as the web MessageComposer.
- DTOs: SendMessageRequest gains mention_names.

Verified live against the kind stack: @codex persisted the mention and
dispatched the bot; @Bots expanded server-side to the channel's bot.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@haowei2000
haowei2000 merged commit 20f1186 into develop Jul 19, 2026
6 checks passed
haowei2000 added a commit that referenced this pull request Jul 20, 2026
Conflict in apps/ios/Sources/State/ChatModel.swift: #274 (iOS @-mention
picker) built its `mentionPool` inside the members-fetch block of
loadInitial, which this branch had extracted into refreshMembers().

Resolved by keeping this branch's loadInitial (offline-first seed +
contiguity check) and moving #274's mentionPool construction into
refreshMembers(). Strictly better than either side: refreshMembers()
also runs on warm re-entry, so a member who joined while the user was
away now appears in the mention picker without a cold reload — #274's
version only built the pool on a cold load.

DTOs.swift, ChatView.swift and ComposerView.swift auto-merged.
xcodebuild (Debug, iOS Simulator) succeeds; SwiftData harness and
frontend vitest (83/83) still pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant