diff --git a/docs/wiki/Mobile-Guide.md b/docs/wiki/Mobile-Guide.md index bc986b5e..a8f47aaf 100644 --- a/docs/wiki/Mobile-Guide.md +++ b/docs/wiki/Mobile-Guide.md @@ -38,7 +38,7 @@ the hinge, and opening or closing the device is treated as the device changing s as the keyboard appearing. **Swipe left and right** on the terminal to switch sessions. A visible text selection pauses -the swipe, and a terminal wider than the screen pans sideways instead of switching. +the swipe, and a terminal wider than the screen pans sideways instead. ## The home screen diff --git a/src/web/public/terminal-ui.js b/src/web/public/terminal-ui.js index c4a7e846..c3778ffe 100644 --- a/src/web/public/terminal-ui.js +++ b/src/web/public/terminal-ui.js @@ -1233,7 +1233,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; @@ -1370,7 +1371,8 @@ Object.assign(CodemanApp.prototype, { ev.preventDefault(); 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: hand it to 'y'. + // 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'; diff --git a/test/session-swipe-gesture.test.ts b/test/session-swipe-gesture.test.ts index af8143a2..91d9757a 100644 --- a/test/session-swipe-gesture.test.ts +++ b/test/session-swipe-gesture.test.ts @@ -147,15 +147,20 @@ describe('terminal touch handler hands sideways drags to the swipe', () => { it('locks a dominant sideways drag as a swipe unless the terminal can pan', () => { expect(TERMINAL_SOURCE).toContain("panAxis = travelX > travelY ? (canPanHorizontally() ? 'x' : 'swipe') : 'y';"); expect(TERMINAL_SOURCE).toContain('this._terminalGestureAxis = panAxis;'); - // A 'swipe' is neither a scroll nor (didScroll is set) a tap, until the - // finger passes the swipe's own vertical drift limit: the swipe has given - // up by then, so the drag is handed back to the scroll. + // A 'swipe' is neither a scroll nor (didScroll is set) a tap. expect(TERMINAL_SOURCE).toContain("if (panAxis === 'swipe') {"); - expect(TERMINAL_SOURCE).toContain( - "const drift = typeof SwipeHandler !== 'undefined' ? SwipeHandler.maxVerticalDrift : 50;" - ); - expect(TERMINAL_SOURCE).toContain('if (Math.abs(touchY - touchStartY) <= drift) return;'); - expect(TERMINAL_SOURCE).toContain("this._terminalGestureAxis = 'y';"); + }); + + it("hands a 'swipe' drag back to the scroll once it passes the swipe's own drift limit", () => { + // A thumb arc whose first move leans sideways (+9 px across, +5 px down) locks + // as 'swipe'; SwipeHandler drops it past maxVerticalDrift, so without the + // handback the 300 px of downward travel that follows would do nothing. + const start = TERMINAL_SOURCE.indexOf("if (panAxis === 'swipe') {"); + const block = TERMINAL_SOURCE.slice(start, TERMINAL_SOURCE.indexOf("if (panAxis === 'x') {", start)); + expect(block).toContain('SwipeHandler.maxVerticalDrift'); + expect(block).toContain('if (Math.abs(touchY - touchStartY) <= drift) return;'); + expect(block).toContain("panAxis = 'y';"); + expect(block).toContain("this._terminalGestureAxis = 'y';"); // The terminal reads the swipe's limit by name; its fallback is the same value. expect(load().swipe.maxVerticalDrift).toBe(50); });