diff --git a/frontend/app.js b/frontend/app.js index 6050393..0eaf60f 100644 --- a/frontend/app.js +++ b/frontend/app.js @@ -1942,15 +1942,15 @@ /** * Refreshes the sidebar tree while preserving the expanded state of vaults and folders. + * Optimized to avoid a full sidebar wipe and minimize visible loading states. */ async function refreshSidebarTreePreservingState() { - // 1. Capture expanded vaults + // 1. Capture expanded states const expandedVaults = Array.from(document.querySelectorAll(".vault-item")).filter(v => { const children = document.getElementById(`vault-children-${v.dataset.vault}`); return children && !children.classList.contains("collapsed"); }).map(v => v.dataset.vault); - // 2. Capture expanded directories const expandedDirs = Array.from(document.querySelectorAll(".tree-item[data-path]")).filter(item => { const vault = item.dataset.vault; const path = item.dataset.path; @@ -1958,39 +1958,53 @@ return children && !children.classList.contains("collapsed"); }).map(item => ({ vault: item.dataset.vault, path: item.dataset.path })); - // 3. Capture selected path const selectedItem = document.querySelector(".tree-item.path-selected"); const selectedState = selectedItem ? { vault: selectedItem.dataset.vault, path: selectedItem.dataset.path } : null; - // 4. Reload vaults (rebuilds root list) - await loadVaults(); + // 2. Soft update: load vaults to update names/counts without wiping the tree + try { + const vaults = await api("/api/vaults"); + allVaults = vaults; + vaults.forEach(v => { + const vItem = document.querySelector(`.vault-item[data-vault="${CSS.escape(v.name)}"]`); + if (vItem) { + const badge = vItem.querySelector(".badge-small"); + if (badge) badge.textContent = `(${v.file_count})`; + } + }); + } catch (e) { + console.warn("Soft vault refresh failed, falling back to full reload", e); + await loadVaults(); + } - // 5. Re-expand vaults + // 3. Refresh expanded vaults + // If we didn't wipe the tree, we only need to call loadDirectory to update the children for (const vName of expandedVaults) { - const vItem = document.querySelector(`.vault-item[data-vault="${CSS.escape(vName)}"]`); - if (vItem) { - await toggleVault(vItem, vName, true); + const container = document.getElementById(`vault-children-${vName}`); + if (container) { + await loadDirectory(vName, "", container); } } - // 6. Re-expand directories (parents first) + // 4. Re-expand directories (parents first) expandedDirs.sort((a, b) => a.path.split("/").length - b.path.split("/").length); for (const dir of expandedDirs) { const dItem = document.querySelector(`.tree-item[data-vault="${CSS.escape(dir.vault)}"][data-path="${CSS.escape(dir.path)}"]`); const container = document.getElementById(`dir-${dir.vault}-${dir.path}`); - if (dItem && container && container.classList.contains("collapsed")) { + if (dItem && container) { + // If it was already expanded but currently has its old content, loadDirectory will update it try { await loadDirectory(dir.vault, dir.path, container); container.classList.remove("collapsed"); const chev = dItem.querySelector("[data-lucide]"); if (chev) chev.setAttribute("data-lucide", "chevron-down"); } catch (e) { - console.error(`Failed to re-expand ${dir.vault}/${dir.path}`, e); + console.error(`Failed to refresh directory ${dir.vault}/${dir.path}`, e); } } } - // 7. Restore selection + // 5. Restore selection if (selectedState) { await focusPathInSidebar(selectedState.vault, selectedState.path, { alignToTop: false }); } @@ -2091,8 +2105,11 @@ } async function loadDirectory(vaultName, dirPath, container) { - // Show inline loading indicator while fetching directory contents - container.innerHTML = '
'; + // Only show the loading spinner if the container is currently empty + const isEmpty = container.children.length === 0; + if (isEmpty) { + container.innerHTML = '
'; + } var data; try { @@ -4289,6 +4306,7 @@ function smallBadge(count) { const s = document.createElement("span"); + s.className = "badge-small"; s.style.cssText = "font-size:0.68rem;color:var(--text-muted);margin-left:4px"; s.textContent = `(${count})`; return s;