mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-11-14 18:39:33 +01:00
fix(mobile): hand a sideways-opening drag back to the scroll past the swipe's drift limit
Merge-time fix for #674: the first travel past the tap slop decided the axis for the whole contact, so a scroll that opened on a thumb arc (+9 px across, +5 px down, then straight down) locked as 'swipe'. Every later touchmove returned before the scroll code and SwipeHandler gave the swipe up at its 50 px drift limit, so the gesture did nothing. Past SwipeHandler.maxVerticalDrift the drag is now handed to 'y' (and the published axis with it), so it scrolls; a clean sideways swipe, a vertical scroll and a long-press drag are unchanged. The source pin in test/session-swipe-gesture.test.ts moves with the code and also pins the drift value, and a new browser test drives the real touch listeners: the thumb-arc drag ends as a scroll (it fails without the fallback, axis stays 'swipe') and a clean sideways swipe stays a swipe with nothing scrolled. The architecture note and src/web/CLAUDE.md now say a swipe drag is consumed only up to that limit. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
63cada938d
commit
6fb9c4ed8a
6 files changed
+176
-6
No files matched your search
@@ -928,9 +928,9 @@ Further detail: the design follows Apple's [Designing for iPhone Duo](https://de
|
||||
|
||||
⚠️ **Long-press selects** by driving xterm's public `select()` (renderer-independent — under WebGL the glyphs are pixels and native selection cannot exist), drag or a further tap extends, and Copy goes through `copyTerminalSelection()` for its execCommand fallback on plain-HTTP installs. Three guards are load-bearing and each came from a real phone: the compat mouse pair after `touchend` (xterm focuses on mousedown and SelectionService resets the model there, so the keyboard sprang up and the selection vanished on lift), the platform's own ~500ms long-press (Android Chrome focuses the nearest editable element — the helper textarea — through no event a handler can preventDefault, so a bounded focus guard blurs it and `contextmenu` is suppressed for the gesture window), and `copyTerminalSelection()`'s closing `terminal.focus()` (right on desktop, wrong on a phone).
|
||||
|
||||
⚠️ **A sideways drag belongs to the session swipe**, never to a tap or a scroll. The touch handler locks the dominant axis on the first travel past the tap slop (`panAxis`: `y` scrolls the buffer, `x` pans a terminal wider than its box, `swipe` when it cannot pan) and publishes it per gesture as `app._terminalGestureAxis`; a `swipe` drag is consumed without scrolling and never ends as a tap, which used to activate a link, a CLI click or a keyboard toggle on the session being left. `SwipeHandler` (mobile-handlers.js) reads that axis and stands aside for `x` and `y`, for a touch selection, after a second finger, and on surfaces with controls of their own (`IGNORE_SELECTOR`: the tile grid, the selection bar, the CJK input, the history banner); the phone overview and the welcome screen are deliberately not listed, since swiping from home into a session is a feature. A swipe is 80 px of travel within 500 ms (300 ms rejected an unhurried but deliberate swipe outright) with at most 50 px of vertical drift at any point: `touchmove` cancels it mid-gesture rather than only at the lift. Two more rules came from walking the sequences: a touch that starts outside the terminal (a swipe over the home screen) resets the published axis, so a terminal scroll a moment earlier cannot veto it, and a lift the terminal consumed (`defaultPrevented`: its long-press selection gesture, which on blank space leaves no selection behind to check) is never a swipe; the second-finger cancel stays set until the next touchstart, so the first finger lifting cannot clear it.
|
||||
⚠️ **A sideways drag belongs to the session swipe**, never to a tap or a scroll. The touch handler locks the dominant axis on the first travel past the tap slop (`panAxis`: `y` scrolls the buffer, `x` pans a terminal wider than its box, `swipe` when it cannot pan) and publishes it per gesture as `app._terminalGestureAxis`; a `swipe` drag is consumed without scrolling and never ends as a tap, which used to activate a link, a CLI click or a keyboard toggle on the session being left. ⚠️ Only up to the swipe's own drift limit (`SwipeHandler.maxVerticalDrift`): past it the swipe has given up, so the drag is handed back to the scroll (`y`). Otherwise a scroll whose first few pixels lean sideways (a thumb arc) locked as `swipe` and did nothing at all. `SwipeHandler` (mobile-handlers.js) reads that axis and stands aside for `x` and `y`, for a touch selection, after a second finger, and on surfaces with controls of their own (`IGNORE_SELECTOR`: the tile grid, the selection bar, the CJK input, the history banner); the phone overview and the welcome screen are deliberately not listed, since swiping from home into a session is a feature. A swipe is 80 px of travel within 500 ms (300 ms rejected an unhurried but deliberate swipe outright) with at most 50 px of vertical drift at any point: `touchmove` cancels it mid-gesture rather than only at the lift. Two more rules came from walking the sequences: a touch that starts outside the terminal (a swipe over the home screen) resets the published axis, so a terminal scroll a moment earlier cannot veto it, and a lift the terminal consumed (`defaultPrevented`: its long-press selection gesture, which on blank space leaves no selection behind to check) is never a swipe; the second-finger cancel stays set until the next touchstart, so the first finger lifting cannot clear it.
|
||||
|
||||
Tests: `test/terminal-touch-tap.test.ts`, `test/session-swipe-gesture.test.ts` (the real `SwipeHandler` and the terminal's axis lock), `test/mobile/tabs.test.ts` (CDP swipes, mobile suite).
|
||||
Tests: `test/terminal-touch-tap.test.ts`, `test/session-swipe-gesture.test.ts` (the real `SwipeHandler` and the terminal's axis lock), `test/terminal-touch-swipe-axis.browser.test.ts` (the real touch listeners: the drift handback and a clean swipe, browser suite), `test/mobile/tabs.test.ts` (CDP swipes, mobile suite).
|
||||
|
||||
### Entrance animations
|
||||
|
||||
|
||||
Reference in new issue
Block a user