Web frontend

This commit is contained in:
2026-08-27 12:32:20 +02:00
parent d44c24ec97
commit edb6e5e027
97 changed files with 9535 additions and 195 deletions

View File

@@ -0,0 +1,38 @@
/** The whole album index, fetched once.
At roughly 90 kB for a real collection this is cheaper than a search endpoint and makes
type-to-search instant, which is what the keyboard-first design needs.
*/
import { useCallback, useEffect, useState } from "react";
import { api } from "../api/client";
import type { Album } from "../api/types";
export interface Library {
albums: Album[];
loading: boolean;
error: string | null;
reload: () => void;
}
export function useLibrary(): Library {
const [albums, setAlbums] = useState<Album[]>([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const reload = useCallback(() => {
api
.library()
.then((loaded) => {
setAlbums(loaded);
setError(null);
})
.catch((cause: unknown) => setError(String(cause)))
.finally(() => setLoading(false));
}, []);
useEffect(reload, [reload]);
return { albums, loading, error, reload };
}