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:
55
src/api.ts
55
src/api.ts
@@ -182,8 +182,11 @@ export interface LibraryFilter {
|
||||
}
|
||||
|
||||
export interface Status {
|
||||
/** Where the library syncs: "user @ host", or this device only. */
|
||||
/** The open library's name and where it syncs: "Main · user @ host", or
|
||||
* this device only. Changes whenever another library is opened. */
|
||||
library_label: string;
|
||||
/** The open library. */
|
||||
library: { id: string; name: string };
|
||||
reference_path: string;
|
||||
reference_ready: boolean;
|
||||
card_count: number;
|
||||
@@ -266,6 +269,39 @@ export interface SyncReport {
|
||||
/** The first sync is waiting on the user — see `SyncStatus.needs_choice`. */
|
||||
needs_choice: boolean;
|
||||
report: MergeReport;
|
||||
/** Libraries were added, renamed, or deleted on the server: re-list them. */
|
||||
libraries_changed: boolean;
|
||||
}
|
||||
|
||||
/** One of the libraries on this device. */
|
||||
export interface LibraryInfo {
|
||||
/** Local only; never shown. */
|
||||
id: string;
|
||||
name: string;
|
||||
/** The one that's open. */
|
||||
active: boolean;
|
||||
/** The library the device started with, which can't be deleted. */
|
||||
is_default: boolean;
|
||||
/** Whether it should be on the sync server. */
|
||||
sync: boolean;
|
||||
/** Whether it's linked to a library on the server yet. */
|
||||
linked: boolean;
|
||||
/** Another device deleted it from the server; this copy is all that's left. */
|
||||
server_deleted: boolean;
|
||||
}
|
||||
|
||||
/** The open library, for `libraryKey`. Set by `App` from each status. */
|
||||
let openLibraryId = "default";
|
||||
|
||||
export function setOpenLibrary(id: string) {
|
||||
openLibraryId = id;
|
||||
}
|
||||
|
||||
/** A localStorage key for something that belongs to the open library — a
|
||||
* selected deck, say — so each library remembers its own. The default
|
||||
* library keeps the bare key it always had. */
|
||||
export function libraryKey(key: string): string {
|
||||
return openLibraryId === "default" ? key : `${key}:${openLibraryId}`;
|
||||
}
|
||||
|
||||
/** A published or upcoming Magic set, from Scryfall. */
|
||||
@@ -399,9 +435,22 @@ export const api = {
|
||||
syncDevices: () => invoke<SyncDevice[]>("sync_devices"),
|
||||
/** Sign another device out (a lost phone, say); returns the remaining list. */
|
||||
syncRevokeDevice: (id: number) => invoke<SyncDevice[]>("sync_revoke_device", { id }),
|
||||
/** Merge a library file into this one: a JSON backup, or an old library.db. */
|
||||
listLibraries: () => invoke<LibraryInfo[]>("list_libraries"),
|
||||
/** Start a new, empty library and open it. Resolves with the new list. */
|
||||
createLibrary: (name: string, sync: boolean) =>
|
||||
invoke<LibraryInfo[]>("create_library", { name, sync }),
|
||||
/** Open another library. */
|
||||
switchLibrary: (id: string) => invoke<LibraryInfo[]>("switch_library", { id }),
|
||||
/** Rename a library, on the sync server too when it's there. */
|
||||
renameLibrary: (id: string, name: string) => invoke<LibraryInfo[]>("rename_library", { id, name }),
|
||||
/** Delete a library from this device; with `everywhere`, from the server too. */
|
||||
deleteLibrary: (id: string, everywhere: boolean) =>
|
||||
invoke<LibraryInfo[]>("delete_library", { id, everywhere }),
|
||||
/** Put a library on the sync server, or keep it on this device only. */
|
||||
setLibrarySync: (id: string, sync: boolean) => invoke<LibraryInfo[]>("set_library_sync", { id, sync }),
|
||||
/** Merge a library file into the open one: a JSON backup, or an old library.db. */
|
||||
importLibraryFile: (path: string) => invoke<ImportReport>("import_library_file", { path }),
|
||||
/** Save the whole library as JSON, as a backup. */
|
||||
/** Save the whole open library as JSON, as a backup. */
|
||||
exportLibraryDocument: (path: string) => invoke<void>("export_library_document", { path }),
|
||||
|
||||
/** Set releases and article links. `refresh` forces a fetch past the cache. */
|
||||
|
||||
Reference in New Issue
Block a user