Skip to content

fix(editor): a bare re-render no longer ejects the user from INSERT - #6

Merged
myrddian merged 1 commit into
feat/editor-input-ownershipfrom
feat/editor-repaint-preserves-mode
Aug 1, 2026
Merged

fix(editor): a bare re-render no longer ejects the user from INSERT#6
myrddian merged 1 commit into
feat/editor-input-ownershipfrom
feat/editor-repaint-preserves-mode

Conversation

@myrddian

@myrddian myrddian commented Aug 1, 2026

Copy link
Copy Markdown
Owner

Stacked on #5 — review that first; this diff is 3 files on top of it.

Problem

updateFromServer took the server's mode on every reuse. A screen re-sending its tree unchanged arrives here as a reuse, so any repaint dropped a live edit back to the screen's declared mode.

That is precisely what viewport.resize will do once the server honours it — and on mobile, the on-screen keyboard opening fires a resize. The keyboard appearing would have ejected the user from INSERT.

Change

Mode is taken from the server only when the server's declaration actually changed — mode, readOnly, or content. A genuine change is still a hard reset, exactly as before. A bare re-render leaves the user where they are.

Why this instead of the full reconciler

ADR-036's follow-up assumed reconciling paint was the prerequisite for safe resize. Testing the assumption first showed it isn't: the destructive part of a repaint is this mode reset, not the DOM teardown — the DOM already reuses the editor's node, and #5 restores focus after re-parenting.

Full tree reconciliation is still worth doing — DOM churn, and it would retire the activeEditor singleton and the findEditorId pre-scan so multiple editors can coexist. But it is not on the critical path to viewport.resize. This is.

Verification

  • 3 new tests; 71 passing across 11 files
  • tsc --noEmit clean, bundle builds
  • The test that isolates it: user presses i on a NORMAL-declared editor, an identical element is re-sent, and the mode stays [INSERT]

Still tests-in-happy-dom only — no real-browser resize verification yet.

Noticed in passing, not fixed

render.ts builds the editor's mode class with a bare toLowerCase(), producing mode-read_only, while status-line.ts normalises to mode-read-only. Separately, theme.css styles .widget-editor-mode.*, and nothing in the client ever emits that class — the editor root is widget-editor mode-*. So those rules are dead either way. Cosmetic, out of scope here.

updateFromServer took the server's mode on every reuse. But a screen
re-sending its tree unchanged arrives here as a reuse, so any repaint
dropped a live edit back to the screen's declared mode.

That is exactly what viewport.resize will do once the server honours it,
and on mobile the on-screen keyboard opening fires a resize — so the
keyboard appearing would have ejected the user from INSERT.

Mode is now taken from the server only when the server's declaration
actually changed (mode, readOnly, or content). A genuine change is still
a hard reset, as before; a bare re-render leaves the user alone.

This is the smaller half of ADR-036's sequenced follow-up. Full tree
reconciliation remains worthwhile for DOM churn and multiple concurrent
editors, but it is not a prerequisite for resize — this is.

Co-Authored-By: Claude Opus 5 <[email protected]>
@myrddian
myrddian merged commit 2fbab18 into feat/editor-input-ownership Aug 1, 2026
1 of 2 checks passed
myrddian added a commit that referenced this pull request Aug 1, 2026
fix(editor): a bare re-render no longer ejects the user from INSERT (re-land of #6)
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