fix(terminal): don't scroll/fling on a sub-threshold tap

The touchmove handler accumulated pixelAccum/velocity and could scrollLines
on every move — including micro-drift below the 8px tap threshold. A jittery
tap (<8px) stayed classified as a tap (didScroll=false, so tap-to-position
fired) yet still left a non-zero velocity, which touchend turned into a
momentum fling. Result: one tap both positioned the cursor and scrolled.

Gate the scroll/velocity accumulation behind didScroll so sub-threshold
movement is inert, matching the handler's stated tap-vs-scroll intent.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Codeman maintainer
2026-06-17 18:02:21 +02:00
parent 2c81bbc08b
commit 57eefd7aa5
+8 -5
View File
@@ -401,11 +401,14 @@ Object.assign(CodemanApp.prototype, {
if (!didScroll && Math.abs(touchY - touchStartY) >= TAP_THRESHOLD) { if (!didScroll && Math.abs(touchY - touchStartY) >= TAP_THRESHOLD) {
didScroll = true; didScroll = true;
} }
// Only preventDefault once it's a real scroll — preventing micro-drift // Below the tap threshold, treat the gesture as a potential tap:
// touchmove kills click synthesis, which iOS needs to show the keyboard. // don't preventDefault (iOS needs click synthesis to show the
if (didScroll) { // keyboard) and don't accumulate scroll distance or velocity. Without
ev.preventDefault(); // this guard, sub-threshold micro-drift still scrolls a line and
} // leaves a non-zero velocity that touchend turns into a momentum
// fling, so a jittery tap would both position the cursor AND scroll.
if (!didScroll) return;
ev.preventDefault();
const delta = touchLastY - touchY; // positive = scroll down const delta = touchLastY - touchY; // positive = scroll down
pixelAccum += delta; pixelAccum += delta;
velocity = delta * 1.2; velocity = delta * 1.2;