Skip to content

Commit 0d51259

Browse files
committed
Merge develop into main: release v1.7.1
2 parents be1a194 + c15f63f commit 0d51259

5 files changed

Lines changed: 24 additions & 10 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changelog
22

3+
## [1.7.1] - 2026-06-10
4+
5+
### Fixed
6+
7+
- Restore single-finger touch panning in paged mode (#227)
8+
39
## [1.7.0] - 2026-06-10
410

511
### Added

docs/superpowers/specs/2026-06-09-paged-zoom-quality-design.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ Element-free and unit-testable, shared with the e2e suite like `zoom-layout.ts`:
7171
A small explicit state machine in `PagedViewport`, preserving today's contracts:
7272

7373
- **All pointers always enter the pointer map**`.textBox` targets only suppress _pan initiation_ (selection/Yomitan), never pinch participation (today touch pinches work over text; `beforeMouseDown` only ever affected mouse).
74-
- **Single-finger touch never pans** (today's `onTouch: touches > 1` contract): one-finger touch is reserved for Reader's swipe-to-flip with its #186 edge gating and 200 ms multi-touch debounce — copying the scroll readers' any-pointer drag here would break page flipping. Mouse (and pen) drags pan.
74+
- **Single-finger touch pans** (correction, 2026-06-10): panzoom's `onTouch` option only gated `preventDefault``handleSingleFingerTouch` ran unconditionally, so production touch DID pan with one finger, coexisting with Reader's swipe-to-flip precisely because propagation wasn't stopped. Touch pan and the edge-gated (#186) swipe handlers coexist the same way here: pointer capture never retargets touch events, so the window-level swipe handlers still see them. Mouse/pen on `.textBox` defers to drag selection; touch pans everywhere (as in production).
7575
- **Pointer capture is deferred until `DRAG_THRESHOLD` is exceeded** — capturing on pointerdown would retarget `mouseup` away from the in-wrapper gutter page-turn buttons (the primary desktop navigation) and break text-selection drags. Below the threshold the press behaves exactly as today.
7676
- Transitions: a second pointer always upgrades pan → pinch (pan ends, pinch baselines); a pinch losing a finger down to one re-baselines as a fresh mouse-pan _only_ for mouse/pen (touch returns to idle); losing all pointers runs `pinchEnd`. Resize/reset mid-pinch clears controller state; the component re-baselines via `pinchStart` on the next move with ≥2 pointers (the established scroll-reader pattern).
7777

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "mokuro-reader",
3-
"version": "1.7.0",
3+
"version": "1.7.1",
44
"private": true,
55
"scripts": {
66
"dev": "vite dev",

src/lib/components/Reader/PagedViewport.svelte

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -155,12 +155,17 @@
155155
// ============================================================
156156
// Pointer state machine
157157
//
158-
// - every pointer enters the map; .textBox only suppresses PAN initiation
159-
// - single-finger touch never pans (reserved for Reader's swipe-to-flip)
158+
// - every pointer enters the map; .textBox suppresses PAN initiation for
159+
// mouse/pen only (drag selection) — touch pans everywhere, exactly like
160+
// the old panzoom touch path, which handled single-finger touches
161+
// unconditionally (its onTouch option only gated preventDefault)
162+
// - single-finger touch pan COEXISTS with Reader's swipe-to-flip: touch
163+
// events aren't retargeted by pointer capture, so the window-level swipe
164+
// handlers still see them and stay edge-gated (#186)
160165
// - capture is deferred until DRAG_THRESHOLD so gutter-button clicks and
161166
// text-selection drags behave exactly as before
162167
// - two pointers always upgrade to pinch; back down to one re-baselines
163-
// as a fresh mouse/pen pan, touch returns to idle
168+
// as a fresh pan with the remaining pointer
164169
// ============================================================
165170
166171
const DRAG_THRESHOLD = 5;
@@ -205,8 +210,9 @@
205210
return;
206211
}
207212
208-
if (e.pointerType === 'touch') return; // swipe-to-flip's domain
209-
if ((e.target as HTMLElement).closest('.textBox')) return; // selection
213+
// Mouse/pen on a text box is a selection drag, never a pan; touch has no
214+
// drag-selection gesture and panned over text in production too.
215+
if (e.pointerType !== 'touch' && (e.target as HTMLElement).closest('.textBox')) return;
210216
if (e.button !== 0) return;
211217
212218
if (controller.isActive) controller.finishNow();
@@ -254,9 +260,11 @@
254260
controller.pinchStart(points()); // re-baseline on the new pair
255261
} else {
256262
controller.pinchEnd();
263+
// The remaining pointer continues as a pan — for touch too, matching
264+
// the old panzoom pinch→drag handoff.
257265
const rest = points()[0];
258266
const restId = [...activePointers.keys()][0];
259-
if (rest && rest.type !== 'touch') {
267+
if (rest) {
260268
beginPan({ pointerId: restId, clientX: rest.x, clientY: rest.y });
261269
}
262270
}

0 commit comments

Comments
 (0)