diff --git a/src-tauri/src/browser_runner.rs b/src-tauri/src/browser_runner.rs index 42ba6a7..f2bc706 100644 --- a/src-tauri/src/browser_runner.rs +++ b/src-tauri/src/browser_runner.rs @@ -1380,9 +1380,10 @@ impl BrowserRunner { return Err(error_details.into()); } - registry - .mark_download_completed(&browser_str, &version) - .map_err(|e| format!("Failed to mark download as completed: {e}"))?; + // Mark completion in registry. If it fails (e.g., rare race during cleanup), log but continue. + if let Err(e) = registry.mark_download_completed(&browser_str, &version) { + eprintln!("Warning: Could not mark {browser_str} {version} as completed in registry: {e}"); + } registry .save() .map_err(|e| format!("Failed to save registry: {e}"))?; diff --git a/src-tauri/src/download.rs b/src-tauri/src/download.rs index bca3e08..8c4ec9e 100644 --- a/src-tauri/src/download.rs +++ b/src-tauri/src/download.rs @@ -402,23 +402,44 @@ impl Downloader { existing_size = meta.len(); } - // Build request, add Range only if we have bytes - let mut request = self - .client - .get(&download_url) - .header( - "User-Agent", - "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36", - ); + // Build request, add Range only if we have bytes. If the server responds with 416 (Range Not + // Satisfiable), delete the partial file and retry once without the Range header. + let response = { + let mut request = self + .client + .get(&download_url) + .header( + "User-Agent", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36", + ); - if existing_size > 0 { - request = request.header("Range", format!("bytes={existing_size}-")); - } + if existing_size > 0 { + request = request.header("Range", format!("bytes={existing_size}-")); + } - // Start download (or resume) - let response = request.send().await?; + let first = request.send().await?; - // Check if the response is successful + if first.status().as_u16() == 416 && existing_size > 0 { + // Partial file on disk is not acceptable to the server — remove it and retry from scratch + let _ = std::fs::remove_file(&file_path); + existing_size = 0; + + let retry = self + .client + .get(&download_url) + .header( + "User-Agent", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36", + ) + .send() + .await?; + retry + } else { + first + } + }; + + // Check if the response is successful (200 OK or 206 Partial Content) if !(response.status().is_success() || response.status().as_u16() == 206) { return Err(format!("Download failed with status: {}", response.status()).into()); } diff --git a/src-tauri/src/platform_browser.rs b/src-tauri/src/platform_browser.rs index b42a74c..f72d019 100644 --- a/src-tauri/src/platform_browser.rs +++ b/src-tauri/src/platform_browser.rs @@ -727,41 +727,10 @@ pub mod windows { cmd.current_dir(parent_dir); } - let output = cmd.output()?; - - if !output.status.success() { - // Try fallback without --new-window - let mut fallback_cmd = Command::new(&executable_path); - fallback_cmd.args([ - &format!( - "--user-data-dir={}", - profile - .get_profile_data_path(profiles_dir) - .to_string_lossy() - ), - url, - ]); - - if let Some(parent_dir) = browser_dir - .parent() - .or_else(|| browser_dir.ancestors().nth(1)) - { - fallback_cmd.current_dir(parent_dir); - } - - let fallback_output = fallback_cmd.output()?; - - if !fallback_output.status.success() { - return Err( - format!( - "Failed to open URL in existing Chromium-based browser: {}", - String::from_utf8_lossy(&fallback_output.stderr) - ) - .into(), - ); - } - } - + // Do not call output() to avoid blocking the UI thread while the browser processes the request. + // Spawn the helper process and return immediately. This applies to Chromium-based browsers + // including Brave to prevent UI freezes observed in production. + let _child = cmd.spawn()?; Ok(()) }