Named libraries: switch between several, each syncing on its own
The app can keep any number of named libraries and switch between them from the top bar or Info → Libraries. Each can sync to the account's other devices or stay on this one (a scratch library to try things in). The sync server now keeps several libraries per user under /api/libraries; a migration makes each existing library the user's default "Main", which /api/library keeps serving for older app builds. Every sync lines the device's libraries up with the account's: new ones elsewhere are downloaded, new ones here created on the server, ones deleted elsewhere flagged rather than thrown away. The existing library keeps its files and merge base, so upgrading asks nothing.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { api, CardRef } from "../api";
|
||||
import { api, CardRef, libraryKey } from "../api";
|
||||
import { CardSearchBox, QtyStepper } from "../components";
|
||||
|
||||
/** Rapid card entry: fuzzy search-as-you-type, ↑/↓ + Enter (or click) adds one copy. */
|
||||
@@ -10,11 +10,12 @@ export function CardEntry() {
|
||||
{ oracleId: string; name: string; qty: number; location: string }[]
|
||||
>([]);
|
||||
// Persisted so a "box" location sticks while entering a stack of cards.
|
||||
const [location, setLocation] = useState(() => localStorage.getItem("add-location") || "");
|
||||
// Each library has its own boxes.
|
||||
const [location, setLocation] = useState(() => localStorage.getItem(libraryKey("add-location")) || "");
|
||||
const searchInputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
localStorage.setItem("add-location", location);
|
||||
localStorage.setItem(libraryKey("add-location"), location);
|
||||
}, [location]);
|
||||
|
||||
// Typing anywhere on this tab — without having clicked into another field
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { open, save } from "@tauri-apps/plugin-dialog";
|
||||
import { useEffect, useMemo, useRef, useState, useCallback } from "react";
|
||||
import { api, CardRef, COLORS, Deck, DeckEntry, DeckImportResult, legalStatusFor, PreviewContext } from "../api";
|
||||
import { api, CardRef, COLORS, Deck, DeckEntry, DeckImportResult, legalStatusFor, libraryKey, PreviewContext } from "../api";
|
||||
import {
|
||||
CardSearchBox,
|
||||
CardThumb,
|
||||
@@ -361,7 +361,7 @@ function computeDeckLegality(deck: Deck | null | undefined, contents: DeckEntry[
|
||||
*/
|
||||
export function DeckView({ refreshSignal }: { refreshSignal?: number }) {
|
||||
const [decks, setDecks] = useState<Deck[]>([]);
|
||||
const [selected, setSelected] = usePersistedState<number | null>("deck-selected", null);
|
||||
const [selected, setSelected] = usePersistedState<number | null>(libraryKey("deck-selected"), null);
|
||||
const [newName, setNewName] = useState("");
|
||||
const [contents, setContents] = useState<DeckEntry[]>([]);
|
||||
const [view, setView] = useViewMode("deck-view");
|
||||
|
||||
Reference in New Issue
Block a user