Commit Graph
21 Commits
Author SHA1 Message Date
John O'Keefe 734ce41a50 chore: bump version to 0.1.0
npm's cache reuse keyed on name@version (stuck at 0.0.0) silently served
stale tarballs to Docker builds; bumping on every deploy-worthy change
forces fresh resolution.
2026-09-17 10:10:24 -04:00
John O'Keefe 1305a5280c Ignore small height-only viewport resizes in the fx renderer
Mobile browser toolbar transitions change the viewport height by a
fraction mid-gesture; re-rendering the PDF for that races with
active text selections and can blank the canvas (the old canvas is
cleared for the re-render, and the async pdf.js render can fail or
get interrupted by the next resize). Only re-render for real layout
changes — same threshold as the paginator.
2026-09-16 17:23:59 -04:00
John O'Keefe 94bb38453d Don't classify selection-extension drags as swipe/pan
The gesture classifier only checked whether the touch STARTED on a
.textLayer span. Chromium's long-press selects the nearest word even
when the finger landed between spans (on the .textLayer div, not a
span inside it), so the classifier saw a non-selectable target and
classified the drag as swipe/pan — preventDefault on the iframe's
touchmove then cancelled the native selection extension mid-drag
and could blank the PDF canvas. If any frame already has a
non-collapsed selection, the drag is extending it.
2026-09-16 10:40:24 -04:00
John O'Keefe 8a203996ef Merge branch 'zoom-control'
# Conflicts:
#	pdf.js
2026-09-15 20:06:16 -04:00
John O'Keefe 422e8e0ec0 Don't snap on taps that never panned
A tap goes through #onTouchEnd's snap, which emits a no-op
relocate; readers treat any relocate as a page turn and dismiss
popovers, so the highlight edit popover opened by the tap's
synthetic click was immediately hidden.
2026-09-15 12:56:08 -04:00
John O'Keefe f872a01d53 Dispatch a synthetic click on quick taps
touchstart's preventDefault suppresses the click events that
foliate's link handling and the overlayer's highlight hit-testing
depend on; dispatch one at the tapped element so internal links
and the highlight edit popover work on touch as on desktop.
2026-09-15 12:43:24 -04:00
John O'Keefe 914ade8a79 Custom touch selection: own the gesture, clamp to the page
Chromium's native touch selection cannot be used in the columned
layout: quick taps select words, the word iterator re-anchors at
page boundaries (jumping to other pages), and the browser
auto-scrolls the container when selections cross pages.
preventDefault on touchstart disables it; long-press selects the
word under the finger, drag extends word by word clamped to the
visible page, and pan/snap stand down while a selection gesture is
active. Native rendering still paints the selection.
2026-09-15 08:54:56 -04:00
John O'Keefe 9cfe266929 Ignore small height-only viewport resizes
Mobile browser toolbar transitions change the viewport height by a
fraction mid-gesture; re-rendering for them re-wraps the whole book
and reads as a page refresh. Re-render only for width changes or
height changes of 25% or more.
2026-09-14 19:45:50 -04:00
John O'Keefe ea34de5bf5 Revert experimental touch selection work back to the minimal auto-paging gate
The custom gesture system and the selection clamp/repair chain
replaced browser behavior with worse approximations. Keep only the
non-touch gate on selection auto-paging (de70103), which fixes
drag-selecting paging away mid-gesture; everything else returns to
upstream behavior.
2026-09-14 08:44:26 -04:00
John O'Keefe 28f1e78855 Replace native touch selection with a custom gesture
Chrome's native touch selection misbehaves in the paginated column
layout: quick taps select words, and dragging from a line-start word
re-anchors at a rendered line break, dropping the word and freezing
the gesture. preventDefault on touchstart disables it entirely; a
long-press timer selects the word under the finger instead and drag
moves extend word by word, clamped to the visible page and identical
for every word. Clean taps clear the selection or follow links
(click events being suppressed by the preventDefault).
2026-09-14 08:08:48 -04:00
John O'Keefe 4cae16013e Repair the anchor word only from the stability-gated deferred path
A selection write at the moment Chrome re-anchors the drag detaches
its touch selection controller; the same writes on a settled
selection are fine. Record the word synchronously, repair only when
the selection has been unchanged for 150ms.
2026-09-13 20:25:40 -04:00
John O'Keefe 1bd7e52417 Repair backward word clipping with extend, not setBaseAndExtent
Rewriting both selection boundaries mid-gesture detaches Chrome's
touch selection controller and the selection stops following the
finger. extend() moves only the focus, which the controller
tolerates.
2026-09-13 20:19:26 -04:00
John O'Keefe 3fcfc30bd0 Keep the long-pressed word covered when Chrome re-anchors a touch drag
Dragging just past a line-start word makes Chrome flip the touch
selection and re-anchor it at a rendered line break, silently
dropping the long-pressed word from the selection. Record the word
at the initial long-press and restore its start boundary whenever
the selection no longer covers it.
2026-09-13 20:16:10 -04:00
John O'Keefe 800fb2fa02 Fix inverted probe collapse in the touch selection clamp 2026-09-13 18:32:58 -04:00
John O'Keefe cae618ac87 Fix selectionIsBackward for iframe selections
The helper created its probe range in the module's own document
(the host, in the bundled web reader), so boundary points in the
content iframe collapsed the range and every selection read as
backward.
2026-09-13 18:30:09 -04:00
John O'Keefe 2e392e80d3 Retry the touch selection clamp after the gesture ends 2026-09-13 18:26:47 -04:00
John O'Keefe 5102fc70dd Clamp by geometry, not the visible range
The last visible range can extend past the visible column on text
nodes that span multiple columns (its end-offset bisect uses union
rects), so comparing DOM boundary points against it misses off-view
selection endpoints. Test the endpoint caret rect against the
visible column bounds instead.
2026-09-13 18:23:52 -04:00
John O'Keefe 2a54b52fdb Keep touchSelecting armed through collapsed selectionchange events
Chrome emits collapsed selectionchange events while the long-press
word selection is being set up; clearing the flag on them disarmed
the clamp before the selection ever became a Range.
2026-09-13 18:18:03 -04:00
John O'Keefe 8ac36efbda Fix clamp coordinates: caretRangeFromPoint needs content-space bounds 2026-09-13 18:14:25 -04:00
John O'Keefe e1fa4698c6 Clamp touch selection endpoints to the visible page
Chrome word-snapping during a touch selection drag can map the
endpoint past the visible column into the next (off-screen) page,
selecting the entire visible page at once. Re-map the endpoint via
caretRangeFromPoint at the same line height inside the visible
column whenever it lands outside the last visible range.
2026-09-13 18:07:36 -04:00
John O'Keefe de70103651 Fix touch selection paging away mid-drag: gate selection auto-paging to non-touch pointers 2026-09-13 17:18:47 -04:00