feat(downloads): browsable downloaded library with on-disk usage

Replace the flat download list with a Downloaded browse surface that
reuses the online grids/cards/detail pages, filtered to on-device media,
plus a demoted Transfers tab. Add repository browse commands
(getDownloadedLibraries/Items, disk usage) with offline/hybrid
implementations, a downloadedCatalog service, formatBytes helper, and
per-item/device disk-usage labels on cards and grids. Regenerated
bindings.

Also carries the inseparable UR-052 offline-filter hunks in
offline.rs/hybrid.rs.

TRACES: UR-055 | DR-081, DR-082, DR-083, DR-084; UR-056 | DR-085
This commit is contained in:
2026-07-23 20:02:55 +02:00
parent 8f4f651bac
commit f25deba824
14 changed files with 1418 additions and 224 deletions
+40
View File
@@ -337,6 +337,46 @@ describe("RepositoryClient", () => {
requestId: 0,
});
});
// Downloaded-only browse path (UR-055 | DR-082) — verifies command names and
// camelCase params per the Tauri v2 rule (CLAUDE.md).
it("should get downloaded libraries from backend", async () => {
const mockLibraries = [{ id: "lib1", name: "Music", collectionType: "music" }];
(invoke as any).mockResolvedValueOnce(mockLibraries);
const libraries = await client.getDownloadedLibraries();
expect(libraries).toEqual(mockLibraries);
expect(invoke).toHaveBeenCalledWith("repository_get_downloaded_libraries", {
handle: "test-handle-123",
});
});
it("should get downloaded items with camelCase params", async () => {
const mockResult = { items: [{ id: "t1", name: "Track", type: "Audio" }], totalRecordCount: 1 };
(invoke as any).mockResolvedValueOnce(mockResult);
const result = await client.getDownloadedItems("album1", { limit: 50 });
expect(result).toEqual(mockResult);
expect(invoke).toHaveBeenCalledWith("repository_get_downloaded_items", {
handle: "test-handle-123",
parentId: "album1",
options: { limit: 50 },
});
});
it("should get download disk usage from backend", async () => {
const mockUsage = { sizes: { t1: 1000 }, partialContainers: {}, deviceTotalBytes: 1000, itemCount: 1 };
(invoke as any).mockResolvedValueOnce(mockUsage);
const usage = await client.getDownloadDiskUsage();
expect(usage).toEqual(mockUsage);
expect(invoke).toHaveBeenCalledWith("repository_get_download_disk_usage", {
handle: "test-handle-123",
});
});
});
describe("Playback Methods", () => {