feat(git): make fetch command asynchronous for improved performance #11

Merged
Christoph merged 1 commits from bug/blocking_ui into master 2026-07-03 15:15:51 +00:00
2 changed files with 30 additions and 26 deletions
+5 -1
View File
@@ -718,11 +718,12 @@ pub fn pull(
} }
#[tauri::command] #[tauri::command]
pub fn fetch( pub async fn fetch(
path: String, path: String,
username: Option<String>, username: Option<String>,
password: Option<String>, password: Option<String>,
) -> Result<GitStatus, String> { ) -> Result<GitStatus, String> {
tauri::async_runtime::spawn_blocking(move || -> Result<GitStatus, String> {
let repo = resolve_repo(&path)?; let repo = resolve_repo(&path)?;
let fetch_args = ["fetch"]; let fetch_args = ["fetch"];
let output = match (username.as_deref(), password.as_deref()) { let output = match (username.as_deref(), password.as_deref()) {
@@ -746,6 +747,9 @@ pub fn fetch(
return Err(format!("AUTH_FAILED:{details}")); return Err(format!("AUTH_FAILED:{details}"));
} }
Err(format!("Git command failed: {details}")) Err(format!("Git command failed: {details}"))
})
.await
.map_err(|err| format!("Could not fetch repository: {err}"))?
} }
#[tauri::command] #[tauri::command]
+4 -4
View File
@@ -189,8 +189,10 @@
const AUTO_REFRESH_INTERVAL = 4000; const AUTO_REFRESH_INTERVAL = 4000;
let autoRefreshTimer: ReturnType<typeof setInterval> | undefined; let autoRefreshTimer: ReturnType<typeof setInterval> | undefined;
const BACKGROUND_FETCH_INTERVAL = 180_000; const BACKGROUND_FETCH_INTERVAL = 180_000;
const BACKGROUND_FETCH_AFTER_SWITCH_GRACE_MS = 30_000;
let backgroundFetchTimer: ReturnType<typeof setInterval> | undefined; let backgroundFetchTimer: ReturnType<typeof setInterval> | undefined;
let backgroundFetchInFlight = false; let backgroundFetchInFlight = false;
let lastRepoSwitchAt = 0;
let updateToastOpen = false; let updateToastOpen = false;
let updateToastState: UpdateToastState = "available"; let updateToastState: UpdateToastState = "available";
let pendingUpdate: Update | null = null; let pendingUpdate: Update | null = null;
@@ -264,6 +266,7 @@
// Push buttons instead, not as a background popup. // Push buttons instead, not as a background popup.
async function backgroundFetchTick() { async function backgroundFetchTick() {
if (!autoRefreshEnabled || activeView !== "repository" || !activeRepoPath || isBusy || backgroundFetchInFlight) return; if (!autoRefreshEnabled || activeView !== "repository" || !activeRepoPath || isBusy || backgroundFetchInFlight) return;
if (Date.now() - lastRepoSwitchAt < BACKGROUND_FETCH_AFTER_SWITCH_GRACE_MS) return;
backgroundFetchInFlight = true; backgroundFetchInFlight = true;
try { try {
await fetchRemote(activeRepoPath); await fetchRemote(activeRepoPath);
@@ -869,11 +872,8 @@
await refreshBranchList(activeRepoPath, bundle.branches); await refreshBranchList(activeRepoPath, bundle.branches);
await refreshCommitHistory(activeRepoPath, bundle.commits); await refreshCommitHistory(activeRepoPath, bundle.commits);
await refreshExplorerFiles(activeRepoPath, bundle.files); await refreshExplorerFiles(activeRepoPath, bundle.files);
lastRepoSwitchAt = Date.now();
}); });
// Silent background fetch on open, same as the periodic tick — no "Fetching" indicator,
// just brings ahead/behind (and the taskbar badge) up to date without blocking the
// repo-open flow.
void backgroundFetchTick();
} }
async function chooseRepositoryFolder() { async function chooseRepositoryFolder() {