fix(library): instant Lightroom-style catalog restore with lazy tile fallback

This commit is contained in:
2026-10-05 08:05:09 +07:00
parent b30c7403e3
commit c4d904a207
4 changed files with 106 additions and 40 deletions
+30 -17
View File
@@ -29,6 +29,7 @@ import {
listPhotos,
renameFolder,
restoreCatalogue,
setBackupTileFetcher,
type CatalogueRow,
} from './library';
@@ -47,6 +48,23 @@ const THUMBS = 'thumbs';
// row that was left behind in it is a frame that will not come back.
const VERSION = 1;
export async function readBackupTile(id: string): Promise<Blob | null> {
try {
const root = await folderHandle();
if (!root) return null;
const parts = id.split('/');
const name = parts.pop() as string;
const dir = await at(root, [THUMBS, ...parts].join('/'));
const file = await dir.getFileHandle(spell(name));
return new Blob([await (await file.getFile()).arrayBuffer()], { type: 'image/jpeg' });
} catch {
return null;
}
}
// Automatically register as lazy backup tile fetcher for library.ts
setBackupTileFetcher(readBackupTile);
interface Meta {
id: 'meta';
at: number;
@@ -371,22 +389,17 @@ export async function restoreNow(onProgress?: (p: BackupProgress) => void): Prom
const folder = here.get(f.name);
if (folder && f.label && folder.label !== f.label) await renameFolder(folder, f.label);
}
let done = 0;
const photos = await restoreCatalogue(cat.photos ?? [], cat.edits ?? [], async (id) => {
if (++done % 64 === 0) onProgress?.({ done, total: (cat.photos ?? []).length });
try {
const parts = id.split('/');
const name = parts.pop() as string;
const dir = await at(root, [THUMBS, ...parts].join('/'));
const file = await dir.getFileHandle(spell(name));
return new Blob([await (await file.getFile()).arrayBuffer()], { type: 'image/jpeg' });
} catch {
// A tile that is not there — or that has been taken away by hand — leaves
// the row without one, and the next scan of the folder reads the frame and
// paints it. Losing the picture is not worth losing the reading.
return null;
}
});
onProgress?.({ done: photos, total: photos });
const photoList = cat.photos ?? [];
const editList = cat.edits ?? [];
const total = photoList.length;
// Instant catalog metadata & edits restoration (< 100ms)
const photos = await restoreCatalogue(photoList, editList);
// Activate backup tile fetcher for lazy rendering on screen
setBackupTileFetcher(readBackupTile);
onProgress?.({ done: total, total });
return { photos, at: cat.at ?? 0 };
}