fix(mobile): hand a swipe-locked drag back to the scroll past the swipe's drift limit

A scroll whose first move past the tap slop leaned sideways (a thumb arc) locked as 'swipe' for the whole contact, and SwipeHandler drops a swipe at 50 px of vertical drift, so the gesture did nothing. Past that limit the drag is now a 'y' scroll. Also brings the mobile-handlers fileoverview to the current 500 ms / 50 px limits and notes in the Mobile Guide that a selection pauses the swipe and a wide terminal pans instead.
This commit is contained in:
JD committed 2026-10-22 13:53:48 -04:00
1 parent 63cada938d
commit e8fc08beb3
4 files changed
+30 -5

No files matched your search

+1 -1
View File
@@ -9,7 +9,7 @@
* toolbar/accessory bar repositioning, terminal resize on keyboard open/close,
* and input scroll-into-view. Uses 100px threshold for iOS address bar drift.
* - SwipeHandler — Horizontal swipe detection on the terminal area for session switching.
* 80px minimum distance, 300ms maximum time, 100px max vertical drift.
* 80px minimum distance, 500ms maximum time, 50px max vertical drift.
*
* All three have init()/cleanup() lifecycle methods. They are re-initialized after SSE
* reconnect (in handleInit) to prevent stale closures.
+14 -2
View File
@@ -1200,7 +1200,8 @@ Object.assign(CodemanApp.prototype, {
// slop, so a diagonal drag cannot pan and scroll at the same time. 'swipe'
// is a sideways drag on a terminal that cannot pan: it is the session
// swipe's (SwipeHandler, mobile-handlers.js), so it neither scrolls nor
// ends as a tap on the session being left. Published per gesture as
// ends as a tap on the session being left, until it drifts past the
// swipe's vertical limit and becomes a 'y' scroll. Published per gesture as
// `this._terminalGestureAxis`, which SwipeHandler reads to stand aside
// for a scroll or a pan.
let panAxis = null;
@@ -1335,7 +1336,18 @@ Object.assign(CodemanApp.prototype, {
// fling, so a jittery tap would both position the cursor AND scroll.
if (!didScroll) return;
ev.preventDefault();
if (panAxis === 'swipe') return;
if (panAxis === 'swipe') {
// Past the swipe's own vertical drift limit the session swipe has
// given up, so the drag is a scroll after all (a thumb arc whose
// first move leaned sideways): hand it to 'y'.
const drift = typeof SwipeHandler !== 'undefined' ? SwipeHandler.maxVerticalDrift : 50;
if (Math.abs(touchY - touchStartY) <= drift) return;
panAxis = 'y';
this._terminalGestureAxis = 'y';
touchLastX = touchX;
touchLastY = touchY;
return;
}
if (panAxis === 'x') {
// Pan the container, and touch nothing the vertical path owns —
// no pixelAccum, no velocity, so touchend cannot turn a sideways