Files
buzz/mobile/lib/features
Tom Brow a1efbf63bd fix(mobile): delete composer chips as one unit (#9133)
In the mobile composer, Buzz links (channel, message, repo, PR, issue)
and selected agent `@mentions` render as chips, with the source text
kept as invisible characters behind the chip. Backspace right after a
chip removed one of those hidden characters, so the chip turned into a
broken raw URL or partial name with no visible change for most of the
presses.

This PR gives chips one consistent editing model:

- **A link is a chip only once something follows it.** Its pattern runs
to whitespace or the end of the text, so in practice that is any time
the caret isn't at its end. Pasting exactly one link adds a space after
it (unless whitespace already follows), so it becomes a chip straight
away.
- **A link shows its raw URL while the caret is at its end.**
Backspacing the space after a chip, or moving the caret back past it,
reveals the URL for editing, one character at a time. Moving the caret
away turns it back into a chip. A caret at the link's start leaves it a
chip.
- **Agent `@mention` chips stay atomic.** Backspace right after one
removes the whole mention.
- **Chips are atomic for selection and forward delete.** A caret placed
inside a chip moves to its nearer edge, arrow keys step over it, and a
selection that covers part of a chip grows to cover all of it. Forward
delete just before a chip removes the whole chip. Typing, pasting,
deleting or cutting over a selection replaces exactly the (snapped)
selection.

The controller records each chip's source range while it builds the
spans, so only what is actually drawn as a chip behaves as a unit. Text
in code spans and IME compositions are never rewritten. Undo restores
the previous text: edits at the end of a revealed link are plain text
edits, so undo no longer looks like a backspace into a chip.

Human `@mentions` aren't chips today and are unchanged.

After this change, in the simulator: a link becomes a chip once a space
follows it, backspace reveals the raw URL, the next backspace removes
one character, and the arrow keys reveal the link and turn it back into
a chip.


https://github.com/user-attachments/assets/1d051dd7-92fa-47c9-b569-a7ef5e00ca6f

<img
src="https://github.com/user-attachments/assets/9980aa01-bcf2-4a1b-9c25-4349ce999e26"
width="300" alt="Composer with a channel link chip after a space"> <img
src="https://github.com/user-attachments/assets/5dfbaa44-a0f4-4917-b7ca-eeeb63e47dae"
width="300" alt="After one backspace the raw URL shows"> <img
src="https://github.com/user-attachments/assets/1a675d56-7310-4b13-9dd9-caa26ff99283"
width="300" alt="The next backspace removes one character">

### Validation

- Added tests: the composer permalink-chip test now covers the boundary
space and reveal (soft and hardware backspace, arrow keys), caret and
selection snapping, forward delete, paste adding a space, IME
composition, and undo after typing at the end of a link or after
completing a link. The agent-chip test covers whole-mention backspace,
selection snapping over a mention and a mention in a code span. Breaking
each rule (reveal, snapping, paste space, whole-chip delete, widening
only inside one chip) fails a test.
- Focused existing validation: the full mobile suite (`just mobile-check
mobile-test`) passes.
- Automated app run: iPhone 17 Pro simulator, iOS 27, debug build of
this branch, in a private test channel. Typed a Buzz channel link and a
space (chip), backspaced twice (raw URL, then one character removed),
retyped the character and space (chip again), then moved the caret left
past the space (raw URL) and right again (chip). Nothing was sent. The
run covered the composer only; the change touches nothing outside it.

buzz-review-completed

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Signed-off-by: Tom Brow <tomb@squareup.com>
Co-authored-by: Tom Brow <tomb@squareup.com>
Co-authored-by: studio <dc2fc481343672df31a689840c09299972e704dac592e0da6f18486646a7ee3e@buzz.block.builderlab.xyz>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 18:29:17 -08:00
..