import { useEffect, useState } from "react"; import { type BookSummary, createAndOpenBook, deleteBook, exampleBook, listBooks, loadBook, saveBook } from "../library"; import type { Book } from "../model/book"; import { importEpub } from "../import/epub"; import { isDesktop } from "../ipc"; import { ConfirmDialog } from "./ConfirmDialog"; import { Icon } from "./Icon"; import { RowMenu } from "./RowMenu"; export function Library({ onOpen }: { onOpen: (book: Book) => void }) { const [books, setBooks] = useState([]); const [loaded, setLoaded] = useState(false); const [busy, setBusy] = useState(false); const [notice, setNotice] = useState(null); const [pendingDelete, setPendingDelete] = useState(null); const refresh = () => listBooks() .then(setBooks) .catch(() => setBooks([])) .finally(() => setLoaded(true)); useEffect(() => { refresh(); }, []); const handleExample = async () => { const copy = exampleBook(); if (isDesktop) { try { await saveBook(copy); } catch (e) { setNotice(`Could not save copy: ${e}`); } } onOpen(copy); }; const removeBook = async () => { if (!pendingDelete) return; await deleteBook(pendingDelete.id); setPendingDelete(null); refresh(); }; const handleImport = async () => { if (!isDesktop) { setNotice('Import runs in the desktop app only — open the window from "pnpm tauri dev".'); return; } setBusy(true); try { const book = await importEpub(); if (!book) return; await saveBook(book); onOpen(book); } catch (e) { setNotice(`Import failed: ${e}`); } finally { setBusy(false); } }; return (
{loaded && books.length === 0 && ( )} {books.map((b) => (
loadBook(b.id).then(onOpen).catch((e) => setNotice(`Could not open book: ${e}`))} > {b.title || "Untitled"} {b.author && {b.author}} setPendingDelete(b)} />
))}
{notice && (
setNotice(null)}> {notice}
)} {pendingDelete && ( Delete {pendingDelete.title || "Untitled"}? This permanently removes the book and all its chapters. } onConfirm={removeBook} onClose={() => setPendingDelete(null)} /> )}
); }