Preserve tree scroll position

This commit is contained in:
Mikei386
2026-06-22 06:45:45 +02:00
parent d4f47c5bda
commit 91089328ce
7 changed files with 44 additions and 18 deletions
+28 -10
View File
@@ -375,6 +375,28 @@
}
}
function captureScrollState(root=document) {
const trees=[...root.querySelectorAll('.bu-tree')].map((tree,index)=>({index,top:tree.scrollTop,left:tree.scrollLeft}));
return {windowX:window.scrollX,windowY:window.scrollY,trees};
}
function restoreScrollState(snapshot, root=document) {
if(!snapshot) return;
const apply=()=>{
const trees=[...root.querySelectorAll('.bu-tree')];
snapshot.trees.forEach(item=>{
const tree=trees[item.index];
if(tree) {
tree.scrollTop=item.top;
tree.scrollLeft=item.left;
}
});
window.scrollTo(snapshot.windowX, snapshot.windowY);
};
apply();
requestAnimationFrame(()=>{ apply(); setTimeout(apply, 0); });
}
function renderDashboard() {
const active = state.runs.filter(r => ['queued','running','paused'].includes(r.status)).length;
const orderedRuns = newestRuns(state.runs);
@@ -517,15 +539,13 @@
function renderSourceBrowser() {
const host=document.getElementById('bu-source-browser');
if(!host) return;
const windowX=window.scrollX, windowY=window.scrollY;
const previousScroll=host.querySelector('.bu-tree')?.scrollTop || 0;
const scrollSnapshot=captureScrollState(host);
const chosen=state.backupSelections.length?state.backupSelections.map(path=>`<span class="bu-selection">${esc(path)}</span>`).join(''):'<span class="bu-muted">Keine Ordner ausgewählt.</span>';
const tree=state.sourceTreeRoots.map(item=>sourceTreeNode(item,0)).join('');
host.innerHTML=`<section class="bu-browser-card"><div class="bu-toolbar"><div><h3>Backup-Quellen auswählen</h3><span class="bu-muted">Ordner mit dem Dreieck aufklappen. Unterordner werden erst bei Bedarf geladen.</span></div><span class="bu-count">Ausgewählt: ${state.backupSelections.length}</span></div><div class="bu-selection-list">${chosen}</div><div class="bu-tree" role="tree">${tree||'<div class="bu-empty">Keine Ordner verfügbar.</div>'}</div></section>`;
const treeElement=host.querySelector('.bu-tree'); if(treeElement) treeElement.scrollTop=previousScroll;
host.querySelectorAll('.bu-source-select[data-partial="true"]').forEach(box=>{box.indeterminate=true;box.setAttribute('aria-checked','mixed');});
enhanceTooltips(host);
window.scrollTo(windowX, windowY);
restoreScrollState(scrollSnapshot, host);
}
async function toggleSourceTree(path, forceOpen=false) {
@@ -569,13 +589,11 @@
function renderDirectoryTree(key) {
const tree=state.directoryTrees[key]; const host=document.getElementById(`bu-dir-tree-${key}`);
if(!tree||!host) return;
const windowX=window.scrollX, windowY=window.scrollY;
const previousScroll=host.querySelector('.bu-tree')?.scrollTop || 0;
const scrollSnapshot=captureScrollState(host);
const html=tree.roots.map(item=>directoryTreeNode(key,item,0)).join('');
host.innerHTML=`<section class="bu-browser-card"><div class="bu-toolbar"><div><h3>${esc(tree.title)}</h3><span class="bu-muted">Ordner mit dem Dreieck aufklappen und den gewünschten Zielordner auswählen.</span></div></div><div class="bu-tree" role="tree">${html||'<div class="bu-empty">Keine Ordner verfügbar.</div>'}</div></section>`;
const treeElement=host.querySelector('.bu-tree'); if(treeElement) treeElement.scrollTop=previousScroll;
enhanceTooltips(host);
window.scrollTo(windowX, windowY);
restoreScrollState(scrollSnapshot, host);
}
async function toggleDirectoryTree(key, path, forceOpen=false) {
@@ -755,9 +773,9 @@
return state.config;
}
function renderPreservingScroll() {
const windowX=window.scrollX, windowY=window.scrollY;
const scrollSnapshot=captureScrollState(content);
render();
window.scrollTo(windowX, windowY);
restoreScrollState(scrollSnapshot, content);
}
const lines = (value) => value.split('\n').map(v=>v.trim()).filter(Boolean);
const runTime = run => new Date(run.createdAt || run.startedAt || run.finishedAt || 0).getTime() || 0;