Skip to content

Fix: scrolling a note in Edit mode no longer snaps back to the caret (zennotes#891) - #44

Merged
adibhanna merged 2 commits into
mainfrom
fix/891-edit-scroll
Oct 5, 2026
Merged

adibhanna merged 2 commits into
mainfrom
fix/891-edit-scroll

Conversation

@adibhanna

Copy link
Copy Markdown
Contributor

The iOS side of ZenNotes/zennotes#891 (reported on Android, fixed there in ZenNotes/zennotesandroid#96). This shell has the same src/ui-mobile/editor-keyboard-scroll.ts, and it had the same bug: with the keyboard up, every swipe was pulled back to the caret.

Cause. The helper revealed the caret on every DOM change (a page-wide MutationObserver re-observed the toolbars, which re-reported their size, and called revealEditorCaret()). CodeMirror draws lines as a note scrolls, so each swipe asked for a reveal.

Change. The caret is revealed only when something can have covered it: the keyboard landing, the formatting toolbar or selection bubble appearing or growing, or the viewport getting smaller. Touch-driven scrolling of the note and its fling belong to the reader: no reveal runs during them, and they cancel the keyboard's pending settle steps. Both files are byte-identical to the Android shell's (cmp clean).

Tests. New src/ui-mobile/editor-keyboard-scroll.test.ts (6 tests) over the real module; 4 fail against the old file (20 page changes gave 20 reveals). npm test 186/186, typecheck clean.

Simulator (iPhone 17, iOS 27.0, real XCUITest swipes; caret on line 3 of a 250-line note, keyboard up).

Swipe Before (top line) After (top line)
1 027, snapped to the caret twice mid-fling 046
2 013, behind where it started 093
3 016 139
4 018 185
5 019 232

A tap on a line the keyboard will cover still lifts the caret above the toolbar, and typing near the bottom keeps it there, in both builds. With the keyboard dismissed there was no snap on iPhone in either build, because dismissing blurs the editor; an iPad with a hardware keyboard (editor focused, no on-screen keyboard) was not tested.

Also carries the sass override that keeps braces (GHSA-vfj7-8cjw-p6xm) out of the production tree, the same commit as on #42 and #43, so the audit gate passes.

…e caret

With the keyboard up and the caret in a note, every swipe was pulled back
to the caret mid-fling, so a long note could not be scrolled past it
(ZenNotes/zennotes#891, reported on Android; this shell has the same file).

The keyboard-scroll helper watched the whole page with a MutationObserver
and, on every DOM change, re-observed the toolbars and revealed the caret.
CodeMirror draws lines as a note scrolls, so each swipe asked for a reveal.

The caret is now revealed only when something can have covered it: the
keyboard landing, the formatting toolbar or the selection bubble appearing
or growing, or the viewport getting smaller. Touch-driven scrolling of the
note, and the fling that follows it, belongs to the reader: no reveal runs
during it, and it cancels the keyboard's pending settle steps. Both files
are byte-identical to the Android shell's (ZenNotes/zennotesandroid#96).

Verified on an iPhone 17 simulator (iOS 27.0) with real XCUITest swipes,
caret on line 3 of a 250-line note, keyboard up: before, five swipes ended
on line 19 with two to five snaps back per swipe; after, the same swipes
reached line 232 with none. A tap on a line the keyboard will cover still
lifts the caret above the toolbar, and typing near the bottom keeps it
there.
)

A high-severity advisory for braces (stack exhaustion on deeply nested
patterns, no fixed release) failed the production npm audit gate on every
pull request. It reached production through @excalidraw/excalidraw, which
lists sass 1.51.0 as a dependency; that sass pulls in chokidar 3, which
pulls in braces. Excalidraw never loads sass at runtime: nothing in its
build output imports it.

Excalidraw's sass is overridden to 1.103.1, the version the desktop repo
already carries. It watches files with a chokidar that has no braces, so
braces stays only under build tools. No existing package changes version.
@adibhanna
adibhanna merged commit 53843b8 into main Oct 5, 2026
1 check passed
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