feat(reader): touch & mobile — tap zones, gesture engine, mobile sheets

Phase 2 of the reader redesign:

- Fixed-layout touch engine (foliate-js e9e61d8): pinch-zoom around
  the midpoint, two-finger pan, single-finger pan while zoomed,
  horizontal swipe page-turn at fit (RTL-aware via next()/prev()),
  and double-tap to zoom 2.5x / reset. Touch events forwarded from
  page iframes with converted coordinates; preventDefault only when
  the engine consumes the gesture, so PDF text selection and native
  taps stay intact. touch-action: none on the host and in comic/pdf
  page documents keeps the browser from fighting the engine.
- Tap zones (Kindle-style) for touch devices: tap the outer margins
  to page, center to toggle chrome. Size configurable (10-50%) via
  the revived tap_zone_size setting; toggle via new tap_zones_enabled
  (Behavior section of the settings drawer). Pointer-based + passive
  so drags/swipes/selection never trigger; attached both to the
  viewport and inside every page document (iframe events don't
  bubble); debounced 280ms so double-tap zoom doesn't also page; no
  zone actions while a fixed-layout page is zoomed.
- Drawers become full-width sheets on screens <= 640px.
This commit is contained in:
2026-08-14 16:00:19 -04:00
parent a962342ee0
commit 24ea9d8a38
9 changed files with 134 additions and 3 deletions
+9
View File
@@ -362,6 +362,15 @@ templ ReaderSettingsDrawer() {
<option value="time-left">Time Left</option>
</select>
</label>
<label class="flex items-center mb-2">
<input type="checkbox" name="tap_zones_enabled" x-model="tapZonesEnabled" @change="applyTapZoneSettings()" class="mr-2"/>
Tap Zones <span class="text-xs ml-1" style="color: var(--text-secondary)">(touch)</span>
</label>
<label class="block mb-2" x-show="tapZonesEnabled">
Tap Zone Size
<input type="range" name="tap_zone_size" x-model.number="tapZoneSize" @change="applyTapZoneSettings()" min="10" max="50" class="w-full"/>
<span class="text-xs" x-text="tapZoneSize + '%'" style="color: var(--text-secondary)">30%</span>
</label>
</div>
<!-- Reading Theme (reflowable only) -->
<div class="mb-6" x-show="!isFixedLayout">