feat(web): zoom du lecteur — contrôles +/−/reset (50–300 %) sur PDF et CBZ
This commit is contained in:
@ -5,7 +5,8 @@ import { CbzReader } from "../reader/CbzReader";
|
||||
import { EpubReader } from "../reader/EpubReader";
|
||||
import { pageLocator, parseCbrPageLocator, parseCbzPageLocator, parsePdfPageLocator, pdfPagePercent } from "../reader/locators";
|
||||
import { PdfReader } from "../reader/PdfReader";
|
||||
import { ReaderShell, type ReaderControls } from "../reader/ReaderShell";
|
||||
import { ReaderShell, type ReaderControls, type ReaderZoomControls } from "../reader/ReaderShell";
|
||||
import { clampReaderZoom, READER_ZOOM_DEFAULT, READER_ZOOM_STEP } from "../reader/readerLayout";
|
||||
import { useReaderProgress } from "../reader/useReaderProgress";
|
||||
|
||||
const idleControls: ReaderControls = {
|
||||
@ -21,6 +22,7 @@ export function ReaderPage({ bookId }: { bookId: number }) {
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string>();
|
||||
const [page, setPage] = useState(1);
|
||||
const [zoom, setZoom] = useState(READER_ZOOM_DEFAULT);
|
||||
const [readerControls, setReaderControls] = useState<ReaderControls>(idleControls);
|
||||
const { progress, error: progressError, save, queueSave } = useReaderProgress(bookId);
|
||||
|
||||
@ -44,6 +46,7 @@ export function ReaderPage({ bookId }: { bookId: number }) {
|
||||
|
||||
useEffect(() => {
|
||||
setReaderControls(idleControls);
|
||||
setZoom(READER_ZOOM_DEFAULT);
|
||||
}, [bookId]);
|
||||
|
||||
useEffect(() => {
|
||||
@ -77,6 +80,34 @@ export function ReaderPage({ bookId }: { bookId: number }) {
|
||||
);
|
||||
|
||||
const readerError = error ?? progressError;
|
||||
const supportsZoom = book?.format === "pdf" || book?.format === "cbz" || book?.format === "cbr";
|
||||
const changeZoom = useCallback((nextZoom: number | ((currentZoom: number) => number)) => {
|
||||
const stage = document.querySelector(".reader-stage") as HTMLElement | null;
|
||||
const scrollRatioX = stage && stage.scrollWidth > stage.clientWidth ? (stage.scrollLeft + stage.clientWidth / 2) / stage.scrollWidth : 0.5;
|
||||
const scrollRatioY = stage && stage.scrollHeight > stage.clientHeight ? (stage.scrollTop + stage.clientHeight / 2) / stage.scrollHeight : 0.5;
|
||||
|
||||
setZoom((currentZoom) => clampReaderZoom(typeof nextZoom === "function" ? nextZoom(currentZoom) : nextZoom));
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
requestAnimationFrame(() => {
|
||||
if (!stage) return;
|
||||
stage.scrollLeft = Math.max(0, stage.scrollWidth * scrollRatioX - stage.clientWidth / 2);
|
||||
stage.scrollTop = Math.max(0, stage.scrollHeight * scrollRatioY - stage.clientHeight / 2);
|
||||
});
|
||||
});
|
||||
}, []);
|
||||
const zoomControls = useMemo<ReaderZoomControls | undefined>(
|
||||
() =>
|
||||
supportsZoom
|
||||
? {
|
||||
zoom,
|
||||
onZoomOut: () => changeZoom((currentZoom) => currentZoom - READER_ZOOM_STEP),
|
||||
onZoomIn: () => changeZoom((currentZoom) => currentZoom + READER_ZOOM_STEP),
|
||||
onZoomReset: () => changeZoom(READER_ZOOM_DEFAULT)
|
||||
}
|
||||
: undefined,
|
||||
[changeZoom, supportsZoom, zoom]
|
||||
);
|
||||
|
||||
return (
|
||||
<ReaderShell
|
||||
@ -85,6 +116,7 @@ export function ReaderPage({ bookId }: { bookId: number }) {
|
||||
error={readerError}
|
||||
onRetry={error ? () => void loadBook() : undefined}
|
||||
controls={readerControls}
|
||||
zoomControls={zoomControls}
|
||||
>
|
||||
{!book ? (
|
||||
<div className="reader-fallback">
|
||||
@ -98,6 +130,7 @@ export function ReaderPage({ bookId }: { bookId: number }) {
|
||||
url={fileUrl}
|
||||
page={page}
|
||||
backHref={backHref}
|
||||
zoom={zoom}
|
||||
onPageCommit={savePdfPage}
|
||||
onControlsChange={setReaderControls}
|
||||
/>
|
||||
@ -105,6 +138,7 @@ export function ReaderPage({ bookId }: { bookId: number }) {
|
||||
<CbzReader
|
||||
bookId={book.id}
|
||||
page={page}
|
||||
zoom={zoom}
|
||||
onPageCommit={saveComicPage}
|
||||
onControlsChange={setReaderControls}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user