Skip to content

(hub-client) Fix remote cursor cross-line flash when typing at end of line#110

Merged
shikokuchuo merged 1 commit intomainfrom
fix-cursor
Apr 9, 2026
Merged

(hub-client) Fix remote cursor cross-line flash when typing at end of line#110
shikokuchuo merged 1 commit intomainfrom
fix-cursor

Conversation

@shikokuchuo
Copy link
Copy Markdown
Member

Fixes #108. Remote cursor label flashing to the start of the next line when a collaborator types at the end of a line.

When a remote user types at the end of a line, their presence update (cursor offset in the post-edit document) can arrive before the corresponding content change. In the pre-edit document, that offset falls past the newline character, so model.getPositionAt() maps it to line N+1 column 1 instead of line N. This causes the cursor decoration to briefly
flash to the start of the next line before snapping back when the content change arrives.

The fix saves the previous cursor position before adopting the new one. If a small forward movement (1–2 chars, the signature of a keystroke) would place the cursor on a different line, we render at the previous position instead. The content change triggers onDidChangeContent → setModelVersion → re-render, at which point the offset maps correctly in the updated document.

No changes to the OT or anticipation mechanisms — this is a pure rendering-level override.

When a remote user types at the end of a line, their presence update
(with post-edit cursor offset) can arrive before the content change.
The offset maps past the newline in the pre-edit document, causing the
cursor to briefly flash to the start of the next line. Render at the
previous position when a small forward move would cross a line boundary.
@shikokuchuo shikokuchuo merged commit 3bd3ebc into main Apr 9, 2026
4 checks passed
@shikokuchuo shikokuchuo deleted the fix-cursor branch April 9, 2026 14:09
cscheid pushed a commit that referenced this pull request Apr 21, 2026
* test: cover OT cursor tracking race cases before refactor

Adds usePresence.test.ts with five regression tests covering PR #94
(cursor tracking across concurrent local edits) and PR #110 (end-of-line
cross-line flash guard). Tests are written at the decoration-position
level so they survive the Automerge cursor refactor tracked in #113.

* refactor(presence): replace OT offset tracking with Automerge cursors (#113)

Remote cursor/selection travel as Automerge cursor strings anchored to
['text'] and resolve on the receiver against its local doc. Deletes the
OT machinery (transformOffset, peerStateRef, anticipatingEditRef,
same-line guard) and the onDidChangeContent OT effect; modelVersion
stays as a re-render trigger.

`move: 'before'` for selection end is a no-op in automerge 2.2.9 — using
default 'after' everywhere; deviation recorded in the plan.

* test(presence): lock in sender-side cursor ordering

* test: pin automerge cursor semantics as probe fixture
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.

hub-client: cursors flicker

1 participant