diff --git a/src-tauri/src/browser_runner.rs b/src-tauri/src/browser_runner.rs index aab5ab3..4d92cfc 100644 --- a/src-tauri/src/browser_runner.rs +++ b/src-tauri/src/browser_runner.rs @@ -1,8 +1,10 @@ use crate::proxy_manager::PROXY_MANAGER; use directories::BaseDirs; use serde::{Deserialize, Serialize}; +use std::collections::HashSet; use std::fs::{self, create_dir_all}; use std::path::{Path, PathBuf}; +use std::sync::{Arc, Mutex}; use std::time::{SystemTime, UNIX_EPOCH}; use sysinfo::{Pid, System}; use tauri::Emitter; @@ -35,6 +37,11 @@ fn default_release_type() -> String { "stable".to_string() } +// Global state to track currently downloading browsers +lazy_static::lazy_static! { + static ref DOWNLOADING_BROWSERS: Arc>> = Arc::new(Mutex::new(HashSet::new())); +} + // Platform-specific modules #[cfg(target_os = "macos")] mod macos { @@ -2345,6 +2352,18 @@ impl BrowserRunner { browser_str: String, version: String, ) -> Result> { + // Check if this browser type is already being downloaded + { + let mut downloading = DOWNLOADING_BROWSERS.lock().unwrap(); + if downloading.contains(&browser_str) { + return Err(format!( + "Browser '{browser_str}' is already being downloaded. Please wait for the current download to complete." + ).into()); + } + // Mark this browser as being downloaded + downloading.insert(browser_str.clone()); + } + let browser_type = BrowserType::from_str(&browser_str).map_err(|e| format!("Invalid browser type: {e}"))?; let browser = create_browser(browser_type.clone()); @@ -2428,6 +2447,11 @@ impl BrowserRunner { // Clean up failed download let _ = registry.cleanup_failed_download(&browser_str, &version); let _ = registry.save(); + // Remove browser from downloading set on error + { + let mut downloading = DOWNLOADING_BROWSERS.lock().unwrap(); + downloading.remove(&browser_str); + } return Err(format!("Failed to download browser: {e}").into()); } }; @@ -2455,6 +2479,11 @@ impl BrowserRunner { // Clean up failed download let _ = registry.cleanup_failed_download(&browser_str, &version); let _ = registry.save(); + // Remove browser from downloading set on error + { + let mut downloading = DOWNLOADING_BROWSERS.lock().unwrap(); + downloading.remove(&browser_str); + } return Err(format!("Failed to extract browser: {e}").into()); } } @@ -2484,6 +2513,11 @@ impl BrowserRunner { if !browser.is_version_downloaded(&version, &binaries_dir) { let _ = registry.cleanup_failed_download(&browser_str, &version); let _ = registry.save(); + // Remove browser from downloading set on verification failure + { + let mut downloading = DOWNLOADING_BROWSERS.lock().unwrap(); + downloading.remove(&browser_str); + } return Err("Browser download completed but verification failed".into()); } @@ -2514,6 +2548,12 @@ impl BrowserRunner { }; let _ = app_handle.emit("download-progress", &progress); + // Remove browser from downloading set + { + let mut downloading = DOWNLOADING_BROWSERS.lock().unwrap(); + downloading.remove(&browser_str); + } + Ok(version) } diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 929b09d..93e20cc 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -27,9 +27,9 @@ export default function RootLayout({ className={`${geistSans.variable} ${geistMono.variable} antialiased`} > - {children} + diff --git a/src/app/page.tsx b/src/app/page.tsx index ef4d7d9..2bd1d5e 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -79,17 +79,27 @@ export default function Home() { if (missingBinaries.length > 0) { console.log("Found missing binaries:", missingBinaries); + // Group missing binaries by browser type to avoid concurrent downloads + const browserMap = new Map(); + for (const [profileName, browser, version] of missingBinaries) { + if (!browserMap.has(browser)) { + browserMap.set(browser, []); + } + const versions = browserMap.get(browser); + if (versions) { + versions.push(`${version} (for ${profileName})`); + } + } + // Show a toast notification about missing binaries and auto-download them - const missingList = missingBinaries - .map( - ([profileName, browser, version]) => - `${browser} ${version} (for ${profileName})`, - ) + const missingList = Array.from(browserMap.entries()) + .map(([browser, versions]) => `${browser}: ${versions.join(", ")}`) .join(", "); console.log(`Downloading missing binaries: ${missingList}`); try { + // Download missing binaries sequentially by browser type to prevent conflicts const downloaded = await invoke( "ensure_all_binaries_exist", ); diff --git a/src/components/window-drag-area.tsx b/src/components/window-drag-area.tsx index c6e8c9c..0eee23e 100644 --- a/src/components/window-drag-area.tsx +++ b/src/components/window-drag-area.tsx @@ -41,7 +41,7 @@ export function WindowDragArea() { return (