Skip to content

Select area no longer freezes the document on a phone - #164

Merged
JamesmarkeyUK merged 1 commit into
mainfrom
claude/universal-pdf-mobile-select-9tqk3z
Sep 7, 2026
Merged

JamesmarkeyUK merged 1 commit into
mainfrom
claude/universal-pdf-mobile-select-9tqk3z

Conversation

@JamesmarkeyUK

Copy link
Copy Markdown
Collaborator

Fixes the reported problem with Select area on mobile: "my guess would be it's linked to the touchscreen tap and swipe to move up and down on multiple pages" — the guess was right.

The cause

Select area needs a one-finger drag to draw its box. So does scrolling through the document, and the page could only give that gesture to one of them. It gave it to the box outright — touch-action: none on every page's Konva Stage — so picking Select area on a phone froze the document. Every swipe drew an empty selection box instead of scrolling, an empty sweep deliberately leaves the tool armed for another try, and there was no way to reach page 4 (or to get out) short of going back to the toolbar and picking a different tool.

Measured in a 390×844 touch context, one swipe up:

Tool active Document moves
Hand 414px
Select 385px
Select text 385px
Select area 0px

This is the same mistake the one-shot placement tools made, and it takes the same shape of answer.

The fix

  • On a coarse pointer the Stage keeps pan-y pinch-zoom with Select area active, so swiping and pinching work exactly as they do with Select.
  • The box is started by a 350ms press-and-hold, then drag — what a phone already means by "start selecting". An orange anchor dot marks the moment the hold lands, so the gesture is not invisible while it waits.
  • touch-action is read once when the finger lands, so it cannot be flipped at hold time. A native non-passive touchmove listener claims the gesture with preventDefault instead, which works because the finger has not moved and the scroll has not begun. A move that arrives non-cancelable means the browser kept the gesture, and the box is abandoned rather than drawn over a page sliding underneath it.
  • Mouse and pen are untouched: a plain drag still marquees on contact, and on a fine pointer the Stage still reserves the gesture.
  • The gesture is named where the tool is picked — "hold, then drag" under the mobile panel's button, and the full sentence in the desktop panel's help text on a coarse pointer. No placement banner: PlacementHint is for armed payloads, not tools.

Testing

npm run test:select-area is new and covers both halves — a plain swipe scrolls; a press-and-hold draws the box, catches what is inside it, and does not scroll — plus a tap still deselecting and a mouse still marqueeing without a hold. It goes red on the previous code on exactly the two scroll checks.

Verified in headless Chromium at 390×844 with CDP touch: the four touch checks and the two mouse checks pass, pinch-to-zoom still zooms with the tool active, tsc -b --noEmit is clean, and shape-tap / line-tap / word-dblclick / placement-hint / panel-dodge / actions-menu / qr-star / redact-hint-follow / link-click / external-links still pass.

⚠️ Not verified on WebKit or a real device. The fix rests on a touchmove staying cancelable after a still hold — proven in Chromium, only reasoned about for iOS Safari and the Capacitor WKWebView. It fails safe: a non-cancelable move abandons the box, so the worst iOS outcome is "the box won't draw", never the frozen document this fixes. Worth trying on the iPhone once it is live.

🤖 Generated with Claude Code

https://claude.ai/code/session_01AEHtbSEGwEPNcfGjJJSBV2


Generated by Claude Code

Reported: "there seems to be problems with the select area on mobile ...
my guess would be it's linked to the touchscreen tap and swipe to move up
and down on multiple pages". The guess was right.

Select area needs a one-finger drag to draw its box; so does scrolling
through the document, and the page could only give that gesture to one of
them. It gave it to the box outright -- `touch-action: none` on every
page's Konva Stage -- so picking Select area on a phone froze the
document. Every swipe drew an empty selection box instead of scrolling, an
empty sweep leaves the tool armed for another try, and there was no way to
reach page 4, or to get out, short of going back to the toolbar and
picking a different tool. Measured on a 390x844 touch context: a swipe
with Select / Select text / Hand active moved the document ~385px, and
with Select area active it moved 0.

This is the same mistake the one-shot placement tools made and it takes
the same shape of answer -- hand the plain swipe back to the document and
ask for a gesture a swipe is not:

* On a coarse pointer the Stage keeps `pan-y pinch-zoom` with Select area
  active, so swiping and pinching work exactly as they do with Select.
* The box is started by a press-and-hold (350ms), then drag -- what a
  phone already means by "start selecting" everywhere else. An orange
  anchor dot marks the moment the hold lands, so the gesture is not
  invisible while it waits.
* `touch-action` is read once, when the finger lands, so it cannot be
  flipped at hold time. A native non-passive touchmove listener claims the
  gesture with preventDefault instead, which still works because the
  finger has not moved and the scroll has not begun. A move that arrives
  non-cancelable means the browser kept the gesture, and the box is
  abandoned rather than drawn over a page sliding underneath it.
* Mouse and pen are untouched: a plain drag still marquees on contact, and
  on a fine pointer the Stage still reserves the gesture.

The gesture is named where the tool is picked -- "hold, then drag" under
the mobile panel's button, and the full sentence in the desktop panel's
help text on a coarse pointer. No placement banner: PlacementHint is for
armed payloads, not tools.

e2e/select-area-touch.e2e.mjs covers both halves (a plain swipe scrolls; a
press-and-hold draws the box, catches what is inside it, and does not
scroll), plus a tap still deselecting and a mouse still marqueeing without
a hold. It fails on the previous code on exactly the two scroll checks.

Verified in headless Chromium at 390x844 with CDP touch: the four touch
checks and the two mouse checks pass, pinch-to-zoom still zooms with the
tool active, and shape-tap / line-tap / word-dblclick / placement-hint /
panel-dodge / actions-menu / qr-star / redact-hint-follow / link-click /
external-links still pass. NOT verified on WebKit or on a real device --
the preventDefault claim is the part that would differ, and the iOS build
needs eyeballing before this is trusted there.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AEHtbSEGwEPNcfGjJJSBV2
@JamesmarkeyUK
JamesmarkeyUK merged commit b2f67e6 into main Sep 7, 2026
1 of 2 checks passed
@JamesmarkeyUK
JamesmarkeyUK deleted the claude/universal-pdf-mobile-select-9tqk3z branch September 7, 2026 09:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants