fix(genre): single notification when loading descendants

- Add silent parameter to loadChildren to skip notification
- loadAllDescendants now loads children and grandchildren in parallel
- Only one notification after all loads complete (no triple reload)
This commit is contained in:
vicrodh committed 2026-02-02 10:56:26 -06:00
1 parent 023d88cce1
commit df85bc9fba
1 file changed
+31 -16
+31 -16
View File
@@ -148,8 +148,8 @@ export async function loadGenres(): Promise<void> {
} }
} }
/** Lazy load children for a specific genre */ /** Lazy load children for a specific genre (silent = don't notify) */
export async function loadChildren(genreId: number): Promise<GenreInfo[]> { export async function loadChildren(genreId: number, silent = false): Promise<GenreInfo[]> {
// Check if already loaded // Check if already loaded
if (state.childrenByParent.has(genreId)) { if (state.childrenByParent.has(genreId)) {
return state.childrenByParent.get(genreId) || []; return state.childrenByParent.get(genreId) || [];
@@ -171,7 +171,9 @@ export async function loadChildren(genreId: number): Promise<GenreInfo[]> {
// Update tree node // Update tree node
updateTreeNode(genreId, taggedChildren); updateTreeNode(genreId, taggedChildren);
notifyAll(); if (!silent) {
notifyAll();
}
return taggedChildren; return taggedChildren;
} catch (e) { } catch (e) {
console.error(`Failed to load children for genre ${genreId}:`, e); console.error(`Failed to load children for genre ${genreId}:`, e);
@@ -322,26 +324,39 @@ export function toggleGenre(genreId: number, context?: GenreFilterContext): void
notify(ctx); notify(ctx);
} }
/** Load all descendants (children and grandchildren) for a genre */ /** Load all descendants (children and grandchildren) for a genre - single notification */
async function loadAllDescendants(genreId: number): Promise<void> { async function loadAllDescendants(genreId: number): Promise<void> {
// Load children if not loaded let loaded = false;
// Load children if not loaded (silent)
if (!state.childrenByParent.has(genreId)) { if (!state.childrenByParent.has(genreId)) {
const children = await loadChildren(genreId); const children = await loadChildren(genreId, true);
// Load grandchildren for each child loaded = true;
for (const child of children) { // Load grandchildren for each child in parallel (silent)
if (!state.childrenByParent.has(child.id)) { await Promise.all(
await loadChildren(child.id); children.map(child =>
} !state.childrenByParent.has(child.id)
} ? loadChildren(child.id, true)
: Promise.resolve([])
)
);
} else { } else {
// Children already loaded, check grandchildren // Children already loaded, check grandchildren
const children = state.childrenByParent.get(genreId) || []; const children = state.childrenByParent.get(genreId) || [];
for (const child of children) { const grandchildPromises = children
if (!state.childrenByParent.has(child.id)) { .filter(child => !state.childrenByParent.has(child.id))
await loadChildren(child.id); .map(child => loadChildren(child.id, true));
}
if (grandchildPromises.length > 0) {
await Promise.all(grandchildPromises);
loaded = true;
} }
} }
// Single notification after all loads complete
if (loaded) {
notifyAll();
}
} }
export function setGenresSelected(genreIds: number[], selected: boolean, context?: GenreFilterContext): void { export function setGenresSelected(genreIds: number[], selected: boolean, context?: GenreFilterContext): void {