fix(library): optimize image scanning, fast raw preview extraction and lazy thumbnail loading
This commit is contained in:
@@ -23,6 +23,7 @@
|
||||
import type { LibraryEdit, LibraryFolder } from './library';
|
||||
import {
|
||||
ensurePermission,
|
||||
getPhotoThumb,
|
||||
listEdits,
|
||||
listFolders,
|
||||
listPhotos,
|
||||
@@ -125,6 +126,7 @@ async function folderHandle(): Promise<FileSystemDirectoryHandle | null> {
|
||||
// without a click behind it is a prompt the browser may refuse outright, and the
|
||||
// buttons on the screen are where the click is.
|
||||
async function granted(handle: FileSystemHandle, write: boolean): Promise<boolean> {
|
||||
if (!handle) return false;
|
||||
const askable = handle as FileSystemHandle & {
|
||||
queryPermission?: (o: { mode: string }) => Promise<PermissionState>;
|
||||
};
|
||||
@@ -314,32 +316,22 @@ export async function backupNow(onProgress?: (p: BackupProgress) => void): Promi
|
||||
let done = 0;
|
||||
const rows: { id: string; size: number }[] = [];
|
||||
for (const photo of photos) {
|
||||
// Progress counts frames and not tiles: a folder of frames read without one
|
||||
// is still a reading, and a bar that does not move is a bar that reads as a
|
||||
// screen that has stopped.
|
||||
if (++done % 64 === 0) onProgress?.({ done, total: photos.length });
|
||||
if (!photo.thumb) continue;
|
||||
if (had.get(photo.id) === photo.thumb.size) continue;
|
||||
const blob = photo.thumb ?? (await getPhotoThumb(photo.id));
|
||||
if (!blob) continue;
|
||||
if (had.get(photo.id) === blob.size) continue;
|
||||
const parts = photo.id.split('/');
|
||||
parts.pop();
|
||||
const rel = [THUMBS, ...parts, photo.name].join('/');
|
||||
try {
|
||||
await put(root, rel, photo.thumb);
|
||||
await put(root, rel, blob);
|
||||
} catch (err) {
|
||||
// A frame the browser will not write is not a library that is never
|
||||
// written: the run goes on without it, and the name it stopped on goes to
|
||||
// the console, since the line on the screen is one line over a strip of
|
||||
// photographs. Whatever survives `spell` is a name longer than a folder
|
||||
// will hold, and a name spelled back is a name the restore still finds.
|
||||
if (skipped < 5) console.warn('backup: could not write', rel, err);
|
||||
skipped++;
|
||||
continue;
|
||||
}
|
||||
rows.push({ id: photo.id, size: photo.thumb.size });
|
||||
rows.push({ id: photo.id, size: blob.size });
|
||||
written++;
|
||||
// The list is kept in step with the writes: a run that is interrupted
|
||||
// continues from the frame it stopped at instead of writing the folder
|
||||
// again.
|
||||
if (rows.length >= 200) await keep(WRITTEN, rows.splice(0, rows.length));
|
||||
}
|
||||
await keep(WRITTEN, rows);
|
||||
|
||||
Reference in New Issue
Block a user