import { useCallback, useEffect, useMemo, useState } from "react"; import { ArrowLeft, RotateCcw, Save } from "lucide-react"; import type { BookDto } from "@readabook/shared"; import { api, getApiFallback } from "../api/client"; import { ErrorRibbon, Meter } from "../components/ui"; import { navigate } from "../router"; import { CbzReader } from "../reader/CbzReader"; import { EpubReader } from "../reader/EpubReader"; import { parseCbrPageLocator, parseCbzPageLocator, parsePdfPageLocator, pdfPagePercent } from "../reader/locators"; import { PdfReader } from "../reader/PdfReader"; import { useReaderProgress } from "../reader/useReaderProgress"; export function ReaderPage({ bookId }: { bookId: number }) { const [book, setBook] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(); const [page, setPage] = useState(1); const { progress, saving, error: progressError, save } = useReaderProgress(bookId); async function loadBook() { setLoading(true); setError(undefined); try { setBook(await api.book(bookId)); } catch (loadError) { const fallback = getApiFallback(loadError); setBook(fallback ?? null); setError(fallback ? "Lecteur ouvert en mode secours." : "Ouvrage indisponible."); } finally { setLoading(false); } } useEffect(() => { void loadBook(); }, [bookId]); useEffect(() => { const nextPage = parsePdfPageLocator(progress?.locator) ?? parseCbzPageLocator(progress?.locator) ?? parseCbrPageLocator(progress?.locator); if (nextPage) setPage((current) => (current === nextPage ? current : nextPage)); }, [progress]); const fileUrl = useMemo(() => api.bookFileUrl(bookId), [bookId]); const backHref = useMemo(() => (book ? `/book/${book.id}` : "/home"), [book]); const savePdfPage = useCallback( (nextPage: number, pages: number) => { setPage(nextPage); void save(`pdf:page:${nextPage}`, pdfPagePercent(nextPage, pages)); }, [save] ); const saveEpubLocator = useCallback((locator: string, percent: number) => void save(locator, percent), [save]); const saveComicPage = useCallback( (nextPage: number, pages: number) => { setPage(nextPage); const prefix = book?.format === "cbr" ? "cbr" : "cbz"; void save(`${prefix}:page:${nextPage}`, pdfPagePercent(nextPage, pages)); }, [book?.format, save] ); return (
{book?.title ?? "Ouverture du lecteur"} {loading ? "Chargement" : saving ? "Sauvegarde" : "Progression synchronisee"}
{error ? ( ) : ( )}
{!book ? (
{error ?? "Chargement du livre."}
) : book.format === "pdf" ? ( ) : book.format === "cbz" || book.format === "cbr" ? ( ) : ( )}
); }