fix(library): fix photo count live update and optimize scan speed
This commit is contained in:
@@ -943,25 +943,30 @@ function Catalogue() {
|
||||
// lies under it, with nothing at all to say about the rest of the roll: its
|
||||
// numbers drawn over the column would count a roll down to a branch of itself.
|
||||
// The column falls back on the catalogue until the reading is through.
|
||||
const read = live && !live.progress.from ? live.progress.counts : null;
|
||||
const read = live ? live.progress.counts : null;
|
||||
// Memoize photo count map derived from photos and dirs array separately so that
|
||||
// live scan progress ticks (every 200ms) do not re-scan tens of thousands of photos.
|
||||
const baseTreeInfo = useMemo(() => {
|
||||
const hits = new Map<string, number>();
|
||||
const foldersUnder = new Map<string, Set<string>>();
|
||||
const add = (folder: string, rel: string, counted: boolean) => {
|
||||
const set = foldersUnder.get(folder) ?? new Set<string>();
|
||||
foldersUnder.set(folder, set);
|
||||
const normF = (folder || '').replace(/\\/g, '/');
|
||||
const normRel = (rel || '').replace(/\\/g, '/');
|
||||
const set = foldersUnder.get(normF) ?? new Set<string>();
|
||||
foldersUnder.set(normF, set);
|
||||
let path = '';
|
||||
for (const part of rel.split('/')) {
|
||||
for (const part of normRel.split('/')) {
|
||||
if (!part) continue;
|
||||
path = path ? `${path}/${part}` : part;
|
||||
set.add(path);
|
||||
if (counted) hits.set(`${folder}/${path}`, (hits.get(`${folder}/${path}`) ?? 0) + 1);
|
||||
if (counted) hits.set(`${normF}/${path}`, (hits.get(`${normF}/${path}`) ?? 0) + 1);
|
||||
}
|
||||
};
|
||||
for (const photo of photos) {
|
||||
hits.set(photo.folder, (hits.get(photo.folder) ?? 0) + 1);
|
||||
if (photo.dir) add(photo.folder, photo.dir, true);
|
||||
const normF = (photo.folder || '').replace(/\\/g, '/');
|
||||
const normDir = (photo.dir || '').replace(/\\/g, '/');
|
||||
hits.set(normF, (hits.get(normF) ?? 0) + 1);
|
||||
if (normDir) add(normF, normDir, true);
|
||||
}
|
||||
for (const dir of dirs) add(dir.folder, dir.rel, false);
|
||||
return { hits, foldersUnder };
|
||||
@@ -969,19 +974,24 @@ function Catalogue() {
|
||||
|
||||
const nodes = useMemo<Node[]>(() => {
|
||||
const { hits, foldersUnder } = baseTreeInfo;
|
||||
const counted = (key: string, hit: number | undefined) => Math.max(hit ?? 0, read?.[key] ?? 0);
|
||||
const counted = (key: string, hit: number | undefined) => {
|
||||
const normKey = (key || '').replace(/\\/g, '/');
|
||||
return Math.max(hit ?? 0, read?.[normKey] ?? read?.[key] ?? 0);
|
||||
};
|
||||
const out: Node[] = [];
|
||||
for (const folder of folders) {
|
||||
out.push({ key: folder.name, label: folder.label || folder.name, depth: 0, count: counted(folder.name, hits.get(folder.name)) });
|
||||
const normF = (folder.name || '').replace(/\\/g, '/');
|
||||
out.push({ key: normF, label: folder.label || folder.name, depth: 0, count: counted(normF, hits.get(normF)) });
|
||||
// Path order puts a folder before its own children, which is the order the
|
||||
// indented rows have to come in.
|
||||
for (const dir of [...(foldersUnder.get(folder.name) ?? [])].sort((a, b) => a.localeCompare(b))) {
|
||||
for (const dir of [...(foldersUnder.get(normF) ?? [])].sort((a, b) => a.localeCompare(b))) {
|
||||
const parts = dir.split('/');
|
||||
const key = `${normF}/${dir}`;
|
||||
out.push({
|
||||
key: `${folder.name}/${dir}`,
|
||||
key,
|
||||
label: parts[parts.length - 1],
|
||||
depth: parts.length,
|
||||
count: counted(`${folder.name}/${dir}`, hits.get(`${folder.name}/${dir}`)),
|
||||
count: counted(key, hits.get(key)),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user