From 44a5b776d7ae6fbba3bc823cd1a5d92c108596e7 Mon Sep 17 00:00:00 2001 From: Christoph Brandau Date: Fri, 10 Jul 2026 11:15:47 +0200 Subject: [PATCH] fix(refresh): improve auto-refresh robustness against repo switches The automatic data refreshing mechanism has been updated to handle asynchronous state changes more reliably. It now incorporates checks to determine if the active repository path has changed during background operations. This prevents stale or incorrect data from being displayed if a user navigates away from or switches repositories while a refresh cycle is in progress. - Added path validation checks after status fetching and bundle opening - Ensured all subsequent refresh calls use the validated current repository path --- src/App.svelte | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/App.svelte b/src/App.svelte index 743b082..123f22f 100644 --- a/src/App.svelte +++ b/src/App.svelte @@ -631,26 +631,32 @@ async function autoRefreshTick() { if (!autoRefreshEnabled || activeView !== "repository" || !activeRepoPath || isBusy || autoRefreshInFlight || resolveDialogOpen || compareDialogOpen || compareSelectOpen || newBranchCommit || globalSearchOpen) return; + const path = activeRepoPath; autoRefreshInFlight = true; try { // Cheap fast path: only fetch status; skip the heavy reload if nothing changed. - const nextStatus = await getStatus(activeRepoPath); + const nextStatus = await getStatus(path); + // The user may have switched repos (or closed this one) while the status + // call was in flight — applying a stale result would flash/overwrite the + // now-active repo's name and data with this one's. + if (!sameRepoPath(path, activeRepoPath)) return; if (statusFingerprint(nextStatus) === lastStatusFingerprint) return; applyStatus(nextStatus); // Something changed — reload branches, commits and files in one bundled call. - const bundle = await openRepositoryBundle(activeRepoPath, 100); + const bundle = await openRepositoryBundle(path, 100); + if (!sameRepoPath(path, activeRepoPath)) return; const previousHeadHash = lastFileHistoryHeadHash; - await refreshBranchList(activeRepoPath, bundle.branches); - await refreshTags(activeRepoPath, bundle.tags); - await refreshStashes(activeRepoPath, bundle.stashes); - await refreshCommitHistory(activeRepoPath, bundle.commits); - await refreshExplorerFiles(activeRepoPath, bundle.files); + await refreshBranchList(path, bundle.branches); + await refreshTags(path, bundle.tags); + await refreshStashes(path, bundle.stashes); + await refreshCommitHistory(path, bundle.commits); + await refreshExplorerFiles(path, bundle.files); // File history reflects `git log`, which only changes when HEAD actually moves // (new commit, checkout, merge, ...) — skip the reload otherwise so a plain // working-tree/status change (staging, edits) doesn't keep re-fetching and // flickering the currently viewed file's history. - if (lastFileHistoryHeadHash !== previousHeadHash) { - await refreshFileHistory(activeRepoPath); + if (lastFileHistoryHeadHash !== previousHeadHash && sameRepoPath(path, activeRepoPath)) { + await refreshFileHistory(path); } } catch { /* ignore transient errors */ } finally { autoRefreshInFlight = false;