diff --git a/src/App.tsx b/src/App.tsx index d6e71d2..668e18e 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,4 +1,5 @@ import { useEffect, useRef, useState, useCallback, ReactNode } from "react"; +import { getVersion } from "@tauri-apps/api/app"; import { listen } from "@tauri-apps/api/event"; import { open } from "@tauri-apps/plugin-dialog"; import { @@ -168,10 +169,12 @@ function LibrarySummary({ ready, libStats, status, + title = "Your library", }: { ready: boolean; libStats: LibraryStats | null; status: Status | null; + title?: string; }) { if (!ready) { return ( @@ -185,7 +188,7 @@ function LibrarySummary({
- Your library + {title}
{!libStats ? (
Loading…
@@ -242,6 +245,12 @@ export default function App() { const [status, setStatus] = useState(null); const [libStats, setLibStats] = useState(null); const [tab, setTab] = usePersistedState("active-tab", "add"); + // The installed build's version, for the Info page. Release builds stamp + // it at build time, so it comes from Tauri rather than package.json. + const [appVersion, setAppVersion] = useState(null); + useEffect(() => { + getVersion().then(setAppVersion).catch(() => setAppVersion(null)); + }, []); // A deck a chip elsewhere asked to open; DeckView picks it up and clears it. const [openDeckId, setOpenDeckId] = useState(null); // Deck chips only carry the deck's name, which is unique per library. @@ -798,41 +807,64 @@ export default function App() { // rail it normally sits in is replaced by the bottom nav); // on desktop those also appear in the topbar and rail, but sync // lives only here. -
-

Card database

-
- - + // Two columns on wide screens — card data, library stats and the + // libraries on the left; sync and the version on the right. On + // narrow ones the columns dissolve into one list in the order + // set by `.info-*` (see styles.css). +
+
+
+

Card database

+
+ + +
+
+
+ +
+
+ +
+
+
+
+ {sync === null ? ( + <> +

Sync

+
Checking…
+ + ) : ( + + )} +
+
+

About

+
+ mtgc version + + {appVersion ?? "unknown"} + {import.meta.env.DEV && · development build} + +
+
-
- -
- {sync === null ? ( - <> -

Your library

-
Checking…
- - ) : ( - - )} -
-
)}
diff --git a/src/SyncPanel.tsx b/src/SyncPanel.tsx index 85405fc..0fe3a5f 100644 --- a/src/SyncPanel.tsx +++ b/src/SyncPanel.tsx @@ -208,7 +208,7 @@ export function SyncPanel({ return ( <> -

Your library

+

Sync

{!sync.signed_in ? ( <> diff --git a/src/styles.css b/src/styles.css index 00a4a19..cbbef75 100644 --- a/src/styles.css +++ b/src/styles.css @@ -805,11 +805,51 @@ input[type="checkbox"] { /* Mobile's Info tab — card-database management, which lives in the topbar instead on desktop (see INFO_TAB in App.tsx). */ -.info-panel { +/* Info page: a column of panels on narrow screens, two columns on wide ones. + Below the breakpoint the two `.info-col` wrappers dissolve (display: + contents) so `order` can interleave their panels into the reading order + the single column always had: card data, libraries, sync, summary, about. */ +.info-grid { + display: flex; + flex-direction: column; + gap: var(--space-4); +} +.info-col { + display: contents; +} +.info-section { display: flex; flex-direction: column; gap: var(--space-3); - max-width: 480px; + min-width: 0; +} +.info-db { order: 1; } +.info-libraries { order: 2; } +.info-sync { order: 3; } +.info-summary { order: 4; } +.info-about { order: 5; } +@media (min-width: 900px) { + .info-grid { + display: grid; + grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); + align-items: start; + max-width: 1200px; + } + .info-col { + display: flex; + flex-direction: column; + gap: var(--space-4); + min-width: 0; + } +} +.info-about-row { + display: flex; + justify-content: space-between; + gap: var(--space-3); +} +.info-version { + font-variant-numeric: tabular-nums; + font-weight: 600; } /* Top-bar sync state; opens the Info tab. Quiet when all is well, so it only draws the eye when something needs attention. */ diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts new file mode 100644 index 0000000..11f02fe --- /dev/null +++ b/src/vite-env.d.ts @@ -0,0 +1 @@ +///