fix(library): add one-time DB cursor migration to clean legacy Blobs and implement hierarchical Add Folder tree matching
This commit is contained in:
@@ -10,6 +10,7 @@ import {
|
||||
canBrowseFolders,
|
||||
clearLibraryCache,
|
||||
ensurePermission,
|
||||
findFolderRelationship,
|
||||
getPhoto,
|
||||
getPhotoThumbs,
|
||||
HEAD_BYTES,
|
||||
@@ -659,16 +660,54 @@ export function Library() {
|
||||
try {
|
||||
const folder = await pickFolder();
|
||||
if (!folder) return;
|
||||
setFolders((prev) => [...prev.filter((f) => f.name !== folder.name), folder].sort((a, b) => a.name.localeCompare(b.name)));
|
||||
setReady((prev) => new Set(prev).add(folder.name));
|
||||
setNode(folder.name);
|
||||
await scan(folder);
|
||||
|
||||
const relInfo = await findFolderRelationship(folder.handle, folders);
|
||||
|
||||
if (relInfo.type === 'subfolder') {
|
||||
const { parent, relPath } = relInfo;
|
||||
const subNodeKey = `${parent.name}/${relPath}`;
|
||||
const parts = relPath.split('/');
|
||||
|
||||
setExpanded((prev) => {
|
||||
const next = new Set(prev);
|
||||
let curr = parent.name;
|
||||
next.add(curr);
|
||||
for (let i = 0; i < parts.length; i++) {
|
||||
curr = `${curr}/${parts[i]}`;
|
||||
next.add(curr);
|
||||
}
|
||||
return next;
|
||||
});
|
||||
|
||||
setDirs((prev) => {
|
||||
if (prev.some((d) => d.id === subNodeKey)) return prev;
|
||||
return [...prev, { id: subNodeKey, folder: parent.name, rel: relPath }];
|
||||
});
|
||||
|
||||
setNode(subNodeKey);
|
||||
await scan(parent, false, relPath + '/');
|
||||
} else if (relInfo.type === 'parent') {
|
||||
const { child } = relInfo;
|
||||
const nextFolders = [...folders.filter((f) => f.name !== child.name), folder].sort((a, b) =>
|
||||
a.name.localeCompare(b.name)
|
||||
);
|
||||
setFolders(nextFolders);
|
||||
setReady((prev) => new Set(prev).add(folder.name));
|
||||
setNode(folder.name);
|
||||
await scan(folder);
|
||||
} else {
|
||||
setFolders((prev) =>
|
||||
[...prev.filter((f) => f.name !== folder.name), folder].sort((a, b) => a.name.localeCompare(b.name))
|
||||
);
|
||||
setReady((prev) => new Set(prev).add(folder.name));
|
||||
setNode(folder.name);
|
||||
await scan(folder);
|
||||
}
|
||||
} catch (err) {
|
||||
// Closing the picker is a "not now", not a failure worth a line of text.
|
||||
if (err instanceof DOMException && err.name === 'AbortError') return;
|
||||
setNote(t('lib.failed'));
|
||||
}
|
||||
}, [scan, t]);
|
||||
}, [folders, scan, t]);
|
||||
|
||||
const reconnect = useCallback(
|
||||
async (folder: LibraryFolder) => {
|
||||
@@ -1107,7 +1146,7 @@ export function Library() {
|
||||
same row and ellipsises — the catalogue is the content, this bar
|
||||
is furniture. */}
|
||||
<div className="chip-row lib-bar">
|
||||
<button type="button" className="btn primary" data-key="lib-add" disabled={!!live} onClick={() => void add()}>
|
||||
<button type="button" className="btn primary" data-key="lib-add" onClick={() => void add()}>
|
||||
{t('lib.add')}
|
||||
</button>
|
||||
{live || scanQueue().length ? (
|
||||
@@ -1732,7 +1771,6 @@ export function Library() {
|
||||
type="button"
|
||||
className="lib-menu-item"
|
||||
data-key="lib-menu-add"
|
||||
disabled={!!live}
|
||||
onClick={() => {
|
||||
setMenu(null);
|
||||
void add();
|
||||
|
||||
Reference in New Issue
Block a user