Files
chitai/frontend/src/lib/state/library.svelte.ts
T
patrick 3a29294f96 chore: clear the mechanical lint and type findings
Dead imports and locals removed, each blocks keyed, `any` narrowed to unknown.
Two context setters kept their calls and lost only the unused binding; the
settings redirect no longer awaits a parent whose data it discards. A leading
underscore now marks a binding that only holds a position.
2026-08-17 17:55:21 -04:00

90 lines
2.7 KiB
TypeScript

import { resolve } from '$app/paths';
import { browser } from '$app/environment';
import { goto } from '$app/navigation';
import { page } from '$app/state';
import { deleteLibrary } from '$lib/api';
import type { Library } from '$lib/schema';
import { getContext, setContext } from 'svelte';
import { toast } from 'svelte-sonner';
export class LibraryState {
libraries = $state<Library[]>([]);
activeLibrary = $state<Library | undefined>(undefined);
createDialogOpen = $state(false);
constructor(libraries: Library[]) {
this.libraries = libraries;
const activeLibrary = this.libraries.find((lib) => lib.id.toString() === page.params.libraryId);
let previousLibrary: Library | undefined;
if (browser) {
previousLibrary = this.libraries.find(
(lib) => lib.id.toString() === localStorage.getItem('previousLibraryId')
);
}
this.activeLibrary = activeLibrary || previousLibrary || libraries[0];
}
async setActive(libraryId: number) {
this.activeLibrary = this.libraries.find((lib) => lib.id === libraryId) || this.libraries[0];
if (browser) {
localStorage.setItem('previousLibraryId', this.activeLibrary.id.toString());
await goto(
resolve('/(root)/(library)/library/[libraryId]/view', { libraryId: String(libraryId) }),
{
invalidate: ['app:libraries']
}
);
}
}
updateLibraries(libraries: Library[]) {
this.libraries = libraries;
// Update the current library as it may have been removed
if (!this.libraries.find((lib) => this.activeLibrary?.id === lib.id))
this.activeLibrary = libraries[0] || undefined;
}
async deleteLibrary(libraryId: number) {
// Store library with its original index
const libIndex = this.libraries.findIndex((lib) => lib.id === libraryId);
const deletionSnapshot = { library: this.libraries[libIndex], index: libIndex };
// Optimistically delete the library
this.libraries = this.libraries.filter((lib) => lib.id !== libraryId);
try {
// Delete library via API
await deleteLibrary(libraryId);
toast.success(`Deleted library '${deletionSnapshot.library}'`);
} catch (err) {
// Delete failed; restore library at its original position
this.libraries.splice(deletionSnapshot.index, 0, deletionSnapshot.library);
toast.error('Failed to delete library');
console.error('Failed to delete library: ', err);
}
}
addLibrary(library: Library) {
this.libraries.push(library);
}
openLibraryCreateDialog() {
this.createDialogOpen = true;
}
}
const LIBRARY_KEY = Symbol('LIBRARY');
export function setLibraryState(libraries: Library[]) {
return setContext(LIBRARY_KEY, new LibraryState(libraries));
}
export function getLibraryState() {
return getContext<ReturnType<typeof setLibraryState>>(LIBRARY_KEY);
}