fix(library): a drive is read again from the catalogue it is filed under

This commit is contained in:
locpham
2026-10-10 20:02:27 +07:00
parent 99e54835ba
commit d36fa78250
+26 -7
View File
@@ -379,10 +379,17 @@ export async function reconnectPhotosForFolders(
const folderTargets: { name: string; handle: FileSystemDirectoryHandle }[] = [];
folderTargets.push({ name: newFolderHandle.name, handle: newFolderHandle });
const knownFolderNames = new Set([
...existingFolders.filter((f) => !f.source).map((f) => f.name),
...allPhotos.filter((p) => !p.remoteId).map((p) => p.folder),
]);
const knownFolderNames = new Set(
[
...existingFolders.filter((f) => !f.source).map((f) => f.name),
...allPhotos.filter((p) => !p.remoteId).map((p) => p.folder),
]
// A row's folder is filed spelled the way `readPhotos` reads it, and the
// drive root's `\` spells as `''` — a name no folder can be opened at, and
// one that would leave a record for a folder with no name behind it.
.map(normPath)
.filter(Boolean)
);
for (const name of knownFolderNames) {
if (folderTargets.some((t) => t.name === name)) continue;
@@ -398,8 +405,12 @@ export async function reconnectPhotosForFolders(
await new Promise<void>((resolve, reject) => {
const tx = db.transaction(FOLDERS, 'readwrite');
const store = tx.objectStore(FOLDERS);
// The record goes back with the label it was given: the tree draws `D:` where
// the disk's own name for its root is `\`, and a put without the label hands
// the reader back the name the browser could not make sense of.
const labels = new Map(existingFolders.map((f) => [f.name, f.label]));
for (const target of folderTargets) {
store.put({ name: target.name, handle: target.handle });
store.put({ name: target.name, label: labels.get(target.name), handle: target.handle });
reconnectedFolders++;
}
tx.oncomplete = () => resolve();
@@ -408,7 +419,9 @@ export async function reconnectPhotosForFolders(
const photosToUpdate: LibraryPhoto[] = [];
for (const target of folderTargets) {
const matchingPhotos = allPhotos.filter((p) => p.folder === target.name && !p.handle && !p.remoteId);
const matchingPhotos = allPhotos.filter(
(p) => normPath(p.folder) === normPath(target.name) && !p.handle && !p.remoteId
);
if (!matchingPhotos.length) continue;
const dirCache = new Map<string, FileSystemDirectoryHandle>();
@@ -2280,8 +2293,14 @@ export async function makeThumbs(
export async function readPhotos(folder?: string): Promise<LibraryPhoto[] | null> {
try {
const db = await openDb();
// Every row is filed under `normPath(folder.name)`, and a drive root is the
// case that shows why that matters: the picker names `D:` `\\`, so `normPath`
// spells it `''`. Asking the index for the raw name is asking for a spelling
// nothing is filed under — the catalogue comes back empty, every frame of the
// roll is read as new, and a second reading of a drive it already holds drags
// a handle for every frame of it into memory at once. Ask for what is filed.
const rows = await ask<LibraryPhoto[]>(PHOTOS, 'readonly', (s) =>
folder ? s.index('folder').getAll(folder) : s.getAll()
folder ? s.index('folder').getAll(normPath(folder)) : s.getAll()
);
for (let i = 0; i < rows.length; i++) {
if (rows[i].thumb) delete (rows[i] as { thumb?: Blob | null }).thumb;