import { useEffect, useState, useCallback, ReactNode } from "react"; import { listen } from "@tauri-apps/api/event"; import { open } from "@tauri-apps/plugin-dialog"; import { api, Status } from "./api"; import { HoverPreviewProvider, usePersistedState } from "./components"; import { CardEntry } from "./views/CardEntry"; import { LibraryBrowser } from "./views/LibraryBrowser"; import { DeckView } from "./views/DeckView"; type Tab = "add" | "library" | "decks"; const svg = (children: ReactNode) => ( {children} ); const NAV: { id: Tab; label: string; icon: ReactNode }[] = [ { id: "add", label: "Add Cards", icon: svg() }, { id: "library", label: "Library", icon: svg( <> >, ), }, { id: "decks", label: "Decks", icon: svg( <> >, ), }, ]; export default function App() { const [status, setStatus] = useState(null); const [tab, setTab] = usePersistedState("active-tab", "add"); const [progress, setProgress] = useState(null); const [busy, setBusy] = useState(false); const refreshStatus = useCallback(async () => { setStatus(await api.getStatus()); }, []); useEffect(() => { refreshStatus(); const un = listen("ingest-progress", (e) => setProgress(e.payload)); return () => { un.then((f) => f()); }; }, [refreshStatus]); async function updateCardData() { setBusy(true); setProgress("Starting…"); try { const s = await api.updateCardData(); setStatus(s); setProgress(`Loaded ${s.card_count.toLocaleString()} cards.`); } catch (err) { setProgress(`Failed: ${String(err)}`); } finally { setBusy(false); } } async function chooseLibrary() { const path = await open({ title: "Choose or create library.db (put it in a synced folder)", filters: [{ name: "SQLite", extensions: ["db", "sqlite"] }], }); if (typeof path === "string") { setStatus(await api.setLibraryPath(path)); } } const ready = status?.reference_ready ?? false; return ( M MTG Library {NAV.map((n) => ( setTab(n.id)} > {n.icon} {n.label} ))} {ready ? `${status?.card_count.toLocaleString()} cards` : "No card data"} {status && ( {status.library_path} )} {progress && {progress}} Choose library… {ready ? "Update card data" : "Download card data"} {!ready ? ( ✦ Welcome to your MTG library No card database yet. Click Download card data to fetch the latest cards from Scryfall (a few hundred MB, about a minute). The reference data stays on this device — only your library file is meant to be synced. {busy ? "Downloading…" : "Download card data"} ) : tab === "add" ? ( ) : tab === "library" ? ( ) : ( )} ); }
No card database yet. Click Download card data to fetch the latest cards from Scryfall (a few hundred MB, about a minute). The reference data stays on this device — only your library file is meant to be synced.