Skip to content

fix(composer): preserve caret when inserting mentions mid-message - #6531

Merged
wesbillman merged 2 commits into
mainfrom
tho/mention-caret-regression
Aug 22, 2026
Merged

fix(composer): preserve caret when inserting mentions mid-message#6531
wesbillman merged 2 commits into
mainfrom
tho/mention-caret-regression

Conversation

@tellaho

@tellaho tellaho commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

Category: fix
User Impact: Users can insert mentions earlier in a draft and continue typing without the caret corrupting the rest of the message.

Problem: Caret correction ran after every document change, so typing a mention before existing text repeatedly advanced across the mention separator and interleaved spaces into the draft. Solution: Limit correction to the autocomplete settlement it was designed for, with transaction-level and browser-level regression coverage for known and unregistered mentions.

File changes

desktop/src/features/messages/lib/mentionHighlightExtension.ts
Restricts trailing-space caret advancement to an armed autocomplete settlement instead of every document change.

desktop/src/features/messages/lib/mentionHighlightExtension.test.mjs
Exercises the real ProseMirror plugin state and verifies mid-draft mention typing, unknown tokens, end-of-message typing, and completed-mention separators.

desktop/tests/e2e/mentions.spec.ts
Reproduces the reported composer workflow in Chromium and covers the same corruption path for an unregistered @token.

Reproduction steps

  1. Open a channel and enter hello world in the composer.
  2. Move the caret between hello and world.
  3. Type @bo, select bob from autocomplete, and continue typing abc.
  4. Confirm the composer reads hello @bob abc world with the caret after abc.
  5. Repeat with an unregistered token such as @zzq and confirm the existing text remains intact.

Before / After

Before After
Typing after a mid-draft mention walks the caret through the existing message. Continued typing stays after the inserted mention.
Before: mention caret corrupts existing draft text After: caret remains after the inserted mention

tellaho and others added 2 commits August 21, 2026 17:02
…age typing

Caret correction advanced past a mention's trailing space whenever a
transaction changed the document, not only while autocomplete was
settling. Because the trailing-space scan is purely textual and never
consults the registered names, typing any `@token` before existing text
walked the caret across the separator on every keystroke and interleaved
spaces into the draft (`hello @q uworld`).

Gate the advance on an armed settlement, which is the case the
correction exists for. Autocomplete insertion and continued typing after
a settled mention are unchanged.

Co-authored-by: Mongo <5398c5fd039b963ce132b3e078e7c4af097dd997517bb5e14c2682fe68c25197@buzz.block.builderlab.xyz>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
The unit tests prove ProseMirror transaction behavior but run without a
DOM, so they cannot observe the browser's DOM-selection remap around a
decorated mention chip. Add the reported repro as an end-to-end test:
existing draft, caret moved earlier in the message, partial mention,
autocomplete pick, then continued typing.

Both cases fail against the pre-fix predicate in Chromium (`hello @z
zqworld`) and pass with settlement-only gating.

Co-authored-by: Mongo <5398c5fd039b963ce132b3e078e7c4af097dd997517bb5e14c2682fe68c25197@buzz.block.builderlab.xyz>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
@tellaho
tellaho marked this pull request as ready for review August 22, 2026 00:22
@tellaho
tellaho requested a review from a team as a code owner August 22, 2026 00:22

@wesbillman wesbillman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Carl, an automated reviewer, commenting via Wes’s GitHub account.

No blocking findings. I reviewed exact head cbbe2b9dd43329cc203800a539538081d60601c0 against base 0e48ff26915aa32d5f05208847b9aba75f4f19cd.

The change removes the invalid “any document change” caret advance while preserving the editor-local autocomplete settlement path and its cancellation boundaries. Coverage exercises the pure predicate, the real ProseMirror plugin transaction flow, and Chromium behavior for both selected and unregistered mid-draft mentions.

Focused validation at the exact head passed: all 41 mention-highlight unit tests, both new Playwright regressions, and Biome on the three changed files. Desktop Core, smoke E2E, integration E2E, macOS build, and DCO CI checks are green.

@wesbillman
wesbillman merged commit 0745612 into main Aug 22, 2026
24 checks passed
@wesbillman
wesbillman deleted the tho/mention-caret-regression branch August 22, 2026 00:48

@jedwards27 jedwards27 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:bot: Jude’s code review agent

Approved at exact head cbbe2b9dd43329cc203800a539538081d60601c0 against base 0e48ff26915aa32d5f05208847b9aba75f4f19cd.

No material findings. Independent systems/integration and product/UI/adversarial review lanes agree that the narrow predicate change in desktop/src/features/messages/lib/mentionHighlightExtension.ts preserves autocomplete settlement while preventing ordinary mid-draft document changes from advancing the caret. Deliberate ArrowLeft/click cancellation remains intact, surrounding text is preserved, and the change introduces no relay, schema, identity, persistence, dependency, Tauri, release, or accessibility-contract scope.

Exact-head validation:

  • pnpm --dir desktop test: 5,354 passed, 0 failed.
  • pnpm --dir desktop typecheck: passed.
  • Biome on all three changed files: passed.
  • Isolated Chromium E2E: both new mid-draft mention regressions passed.
  • Causal mutation restoring unconditional document-change advancement made both regressions fail; restoring the exact head returned them to 2/2 passing.
  • git diff --check: passed; working tree remained clean.
  • Applicable exact-head CI is green, including Desktop Core, four smoke shards, two integration shards, macOS build, aggregate Desktop, and DCO.

Residual risk: no native Tauri/WKWebView journey was run because shared-machine GUI launch/focus was not authorized. Platform-specific DOM-selection behavior therefore remains unproven natively, though the production change is narrow and the causal Chromium regressions substantially constrain the risk.

brow added a commit that referenced this pull request Aug 22, 2026
* origin/main: (65 commits)
  fix(composer): preserve caret when inserting mentions mid-message (#6531)
  chore(deps): update rust crate async-trait to v0.1.92 (#6094)
  chore(deps): update dependency sonner to v2.0.8 (#6093)
  chore(deps): update rust crate http-body-util to v0.1.4 (#5452)
  chore(deps): update rust crate http to v1.4.2 (#5451)
  chore(deps): update rust crate futures-util to v0.3.33 (#5448)
  chore(deps): update rust crate futures to v0.3.33 (#5445)
  chore(deps): update dependency @tauri-apps/api to v2.11.1 (#5444)
  chore(deps): update ubuntu:24.04 docker digest to 561618e (#5442)
  chore(deps): update swatinem/rust-cache digest to 6323deb (#5441)
  fix(desktop): restore true zoom by scaling the root rem (#6514)
  chore(desktop): drop unused ORIGINAL_CONTENT from empty-edit-delete spec (#6517)
  feat(workflows): clarify workflow setup and activation (#6470)
  perf(desktop): stop the Projects fan refetching on re-entry and running after leave (#6458)
  perf(desktop): keep the member roster off the channel-switch path (#6456)
  fix(deletion): allow IRSA S3 credentials (#6495)
  docs(nips): comprehensive NIP-FI — core + claimable profiles (EDGE/LIFECYCLE/DELEG/CONF) (#5946)
  fix(benchmarks): wait for scripted event delivery (#6487)
  Polish mobile channel navigation and message sends (#6488)
  Clarify huddle message destination (#6496)
  ...

Signed-off-by: leader <71e9f2c44a6932b6772caaaccda1911d010463c3e2c6c40410b8329956046801@buzz.block.builderlab.xyz>

Co-authored-by: Tom Brow <tomb@block.xyz>
Signed-off-by: Tom Brow <tomb@block.xyz>
brow added a commit that referenced this pull request Aug 22, 2026
…ifications-pr

* origin/main: (38 commits)
  fix(composer): preserve caret when inserting mentions mid-message (#6531)
  chore(deps): update rust crate async-trait to v0.1.92 (#6094)
  chore(deps): update dependency sonner to v2.0.8 (#6093)
  chore(deps): update rust crate http-body-util to v0.1.4 (#5452)
  chore(deps): update rust crate http to v1.4.2 (#5451)
  chore(deps): update rust crate futures-util to v0.3.33 (#5448)
  chore(deps): update rust crate futures to v0.3.33 (#5445)
  chore(deps): update dependency @tauri-apps/api to v2.11.1 (#5444)
  chore(deps): update ubuntu:24.04 docker digest to 561618e (#5442)
  chore(deps): update swatinem/rust-cache digest to 6323deb (#5441)
  fix(desktop): restore true zoom by scaling the root rem (#6514)
  chore(desktop): drop unused ORIGINAL_CONTENT from empty-edit-delete spec (#6517)
  feat(workflows): clarify workflow setup and activation (#6470)
  perf(desktop): stop the Projects fan refetching on re-entry and running after leave (#6458)
  perf(desktop): keep the member roster off the channel-switch path (#6456)
  fix(deletion): allow IRSA S3 credentials (#6495)
  docs(nips): comprehensive NIP-FI — core + claimable profiles (EDGE/LIFECYCLE/DELEG/CONF) (#5946)
  fix(benchmarks): wait for scripted event delivery (#6487)
  Polish mobile channel navigation and message sends (#6488)
  Clarify huddle message destination (#6496)
  ...

Signed-off-by: Tom Brow <tomb@block.xyz>
wpfleger96 pushed a commit that referenced this pull request Aug 22, 2026
…ake-fix

* origin/main: (33 commits)
  perf(desktop): make the Projects surface render-cheap (#6460)
  refactor(acp): clarify agent prompt sections (#6501)
  Add mobile Huddles voice MVP (#6056)
  feat(desktop-messages): keep agents addressed across messages (#6315)
  fix(desktop): remove Buzz entity link previews (#6512)
  fix(composer): preserve caret when inserting mentions mid-message (#6531)
  chore(deps): update rust crate async-trait to v0.1.92 (#6094)
  chore(deps): update dependency sonner to v2.0.8 (#6093)
  chore(deps): update rust crate http-body-util to v0.1.4 (#5452)
  chore(deps): update rust crate http to v1.4.2 (#5451)
  chore(deps): update rust crate futures-util to v0.3.33 (#5448)
  chore(deps): update rust crate futures to v0.3.33 (#5445)
  chore(deps): update dependency @tauri-apps/api to v2.11.1 (#5444)
  chore(deps): update ubuntu:24.04 docker digest to 561618e (#5442)
  chore(deps): update swatinem/rust-cache digest to 6323deb (#5441)
  fix(desktop): restore true zoom by scaling the root rem (#6514)
  chore(desktop): drop unused ORIGINAL_CONTENT from empty-edit-delete spec (#6517)
  feat(workflows): clarify workflow setup and activation (#6470)
  perf(desktop): stop the Projects fan refetching on re-entry and running after leave (#6458)
  perf(desktop): keep the member roster off the channel-switch path (#6456)
  ...

Signed-off-by: Duncan <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
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.

3 participants