feat(reader): open image gallery & table zoom on single tap (#4600)

* feat(reader): open image gallery & table zoom on single tap

In reflowable EPUBs, a single tap on an image or table now opens the same
viewer a long-press opens, so the image gallery / table zoom is reachable by
both gestures. Fixed-layout books (PDF/comics/manga) keep tap-to-turn, and
long-press is unchanged everywhere.

Reuses the existing iframe-long-press -> handleImagePress/handleTablePress
flow via a new shared detectMediaTarget() helper (also adopted by the
long-press path so the two entry points can't drift). handleClick now takes
an isFixedLayout flag; the tap branch sits after the link/footnote/drag/
long-hold/Word-Wise guards so linked images still follow links and a
long-hold or double-tap won't double-trigger.

Context: #4584 (single taps stop registering after picture zoom on some
WebView builds) - this adds a second, independent way into the viewer rather
than fixing that root cause.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* refactor(reader): rename iframe-long-press message to iframe-open-media

The message is now posted for both a long-press (any book) and a single tap on
an image/table (reflowable books), so the long-press-specific name was
misleading. Rename the message type to `iframe-open-media` and the consumer
hook `useLongPressEvent` -> `useOpenMediaEvent`. The long-press detector
(`addLongPressListeners`/`handleLongPress`) keeps its name since it still
detects a long-press specifically.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Huang Xin
2026-06-16 12:58:37 +08:00
committed by GitHub
parent 675ee78bc9
commit e145eb835a
4 changed files with 150 additions and 53 deletions
@@ -13,7 +13,7 @@ import { useBookDataStore } from '@/store/bookDataStore';
import { useSettingsStore } from '@/store/settingsStore';
import { useCustomFontStore } from '@/store/customFontStore';
import { useParallelViewStore } from '@/store/parallelViewStore';
import { useMouseEvent, useTouchEvent, useLongPressEvent } from '../hooks/useIframeEvents';
import { useMouseEvent, useTouchEvent, useOpenMediaEvent } from '../hooks/useIframeEvents';
import { useBrightnessGesture } from '../hooks/useBrightnessGesture';
import BrightnessOverlay from './BrightnessOverlay';
import { usePagination, viewPagination } from '../hooks/usePagination';
@@ -381,7 +381,10 @@ const FoliateViewer: React.FC<{
detail.doc.addEventListener('keyup', handleKeyup.bind(null, bookKey));
detail.doc.addEventListener('mousedown', handleMousedown.bind(null, bookKey));
detail.doc.addEventListener('mouseup', handleMouseup.bind(null, bookKey));
detail.doc.addEventListener('click', handleClick.bind(null, bookKey, doubleClickDisabled));
detail.doc.addEventListener(
'click',
handleClick.bind(null, bookKey, doubleClickDisabled, !!bookData?.isFixedLayout),
);
detail.doc.addEventListener('wheel', handleWheel.bind(null, bookKey));
detail.doc.addEventListener('touchstart', handleTouchStart.bind(null, bookKey));
detail.doc.addEventListener('touchmove', handleTouchMove.bind(null, bookKey));
@@ -585,7 +588,7 @@ const FoliateViewer: React.FC<{
setCurrentImageIndex(0);
}, []);
useLongPressEvent(bookKey, handleImagePress, handleTablePress);
useOpenMediaEvent(bookKey, handleImagePress, handleTablePress);
useFoliateEvents(viewRef.current, {
onLoad: docLoadHandler,