import { useCallback, useEffect, useState } from "react"; import { api } from "../api/client"; import type { CbzPagesDto, ReaderMode } from "../api/types"; import type { ReaderControls } from "./ReaderShell"; export function CbzReader({ bookId, page, mode, onPageCommit, onControlsChange }: { bookId: number; page: number; mode: ReaderMode; onPageCommit: (page: number, pages: number) => void; onControlsChange: (controls: ReaderControls) => void; }) { const [pages, setPages] = useState(null); const [error, setError] = useState(); const [imageError, setImageError] = useState(false); useEffect(() => { let alive = true; setError(undefined); api .cbzPages(bookId) .then((nextPages) => { if (!alive) return; setPages(nextPages); if (page > nextPages.pageCount) onPageCommit(nextPages.pageCount, nextPages.pageCount); }) .catch(() => { if (alive) setError("Archive CBZ indisponible."); }); return () => { alive = false; }; }, [bookId]); const pageCount = pages?.pageCount ?? 1; const currentPage = Math.max(1, Math.min(page, pageCount)); const currentName = pages?.pages.find((item) => item.page === currentPage)?.name; const go = useCallback((nextPage: number) => { setImageError(false); onPageCommit(Math.max(1, Math.min(nextPage, pageCount)), pageCount); }, [onPageCommit, pageCount]); useEffect(() => { onControlsChange({ canPrevious: !error && !imageError && currentPage > 1, canNext: !error && !imageError && currentPage < pageCount, positionLabel: pages ? `${currentPage} / ${pageCount}` : "Ouverture archive", onPrevious: () => go(currentPage - 1), onNext: () => go(currentPage + 1) }); }, [currentPage, error, go, imageError, onControlsChange, pageCount, pages]); return (
{error || imageError ? (
{error ?? "Page CBZ indisponible."}
) : ( {currentName setImageError(true)} /> )}
); }