Skip to content

fix(mobile): restore PDF text selection - #625

Open
zsxink wants to merge 6 commits into
codedogQBY:mainfrom
zsxink:fix/mobile-pdf-text-selection-rebuild
Open

fix(mobile): restore PDF text selection#625
zsxink wants to merge 6 commits into
codedogQBY:mainfrom
zsxink:fix/mobile-pdf-text-selection-rebuild

Conversation

@zsxink

@zsxink zsxink commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Summary

  • restores selectable PDF text in the mobile reader
  • corrects text-layer font scaling and selection behavior
  • rebuilds the bundled mobile reader with a deterministic build ID

Verification

  • pnpm --dir packages/app-expo build:reader
  • Tested on a physical Android device: PDF text selection works as expected.

zsxink added 6 commits July 26, 2026 18:40
- Fix canvas DPI scaling for Retina displays (outputScale transform)
- Rewrite getSelectedText with geometric sorting for reliable extraction
- Dynamic endOfContent marker positioning for accurate selection bounds
- Custom copy handler using DOM-based text extraction
- Add letter-spacing/word-spacing normalization in text layer CSS
- Disable annotation layer pointer events during selection
- Replace <br> with newlines in range text extraction
- Proper event cleanup via AbortController
Mobile PDF text selection was broken because the committed reader.html
bundle (built 2026-07-04, 22 days before the macOS fix 9c601b8) embedded
pdfjs 4.10.38 with the buggy documentElement transform = scale(1/dpr) that
misplaces text selection. The desktop fix never reached mobile.

Root causes (all verified):
1. Stale committed bundle: reader.html had a hardcoded build id and the old
   scale(1/devicePixelRatio) rendering hack; rebuilt from current source.
2. The reader template injected EPUB reflow styles (font-size/font-family/
   line-height/color:inherit !important) into PDF fixed-layout iframes,
   breaking the pdf.js TextLayer glyph sizing and exposing its transparent
   glyphs. Desktop already guards this (FoliateViewer.tsx); mobile lacked it.
3. Missing readest mobile workarounds: iOS accessibility font-size scaling
   (getFontScale) and the WKWebView ~2GB memory ceiling (getRenderDpr).

Changes:
- foliate-js/pdf.js: add getFontScale / isMobileWebView / getRenderDpr with
  MAX_RENDER_DPR=2 and MAX_CANVAS_PIXELS=2048*1536; render() uses renderDpr
  (desktop isMobileWebView()=false -> real dpr, zero regression); divide
  fontScale out of --text-scale-factor (glyph lever only); annotation
  linkService getAnchorUrl.
- reader.template.html: buildFixedLayoutStyles() safe block + isFixedLayout
  guards in applySettings/applyDocStyles/setThemeColors; applyDocStyles syncs
  the freshly computed fixedLayoutStyles so a stale lastRendererStyles (never
  reset in openBook) can't leak EPUB reflow styles into the first PDF page on
  an EPUB->PDF switch in the same WebView.
- build-reader.js: stamp a real build id (git sha + timestamp) so stale
  bundles are detectable via the RN [ReaderBuild] debug message.
- reader.html: rebuilt with pdfjs 5.5.207 + all workarounds.
- pdfjs-dist unified to ^5.5.207 everywhere; delete npm leftover
  foliate-js/package-lock.json (pinned 4.7.76); remove dead @pdfjs vite alias
  and copyPDFJS rollup plugin.
- docs/mobile-pdf-text-selection-fix.md: root-cause analysis, solution,
  rationale, and independent review findings.
Rebuild after e494ecc so the [ReaderBuild] debug id matches the commit
containing the fix (previously 9c601b8, the pre-fix base), keeping the
bundle-drift detection mechanism honest.
…nt build id

- pdf.js: reset the inline --text-scale-factor and reapply the OS font-size
  correction before TextLayer.render() so a scale left by a previous
  accessibility-font-size render never leaks into the next page.
- build-reader.js: replace git-sha+timestamp build id with a deterministic
  SHA-256 of the placeholder-stripped HTML, so identical source and
  dependencies produce byte-identical reader.html and a stale bundle is
  detectable without depending on a commit SHA.
- docs: sync the mobile PDF text selection fix document with the above.
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.

1 participant