diff --git a/src-tauri/src/downloaded_browsers_registry.rs b/src-tauri/src/downloaded_browsers_registry.rs index 6791b70..d3b96b1 100644 --- a/src-tauri/src/downloaded_browsers_registry.rs +++ b/src-tauri/src/downloaded_browsers_registry.rs @@ -290,24 +290,45 @@ impl DownloadedBrowsersRegistry { } } - // Filter out versions that would leave a browser with zero versions in the registry + // For each browser where every registered version would be removed (no + // profile uses any), keep the newest one by semver. Without this, the + // version preserved depends on HashMap iteration order, so a freshly + // downloaded version can be deleted in favor of an older orphan — leaving + // the UI stuck on "needs to be downloaded". { let data = self.data.lock().unwrap(); - let mut removal_counts: std::collections::HashMap = + let mut removal_versions_by_browser: std::collections::HashMap> = std::collections::HashMap::new(); - for (browser, _) in &to_remove { - *removal_counts.entry(browser.clone()).or_insert(0) += 1; + for (browser, version) in &to_remove { + removal_versions_by_browser + .entry(browser.clone()) + .or_default() + .push(version.clone()); } - to_remove.retain(|(browser, version)| { + let mut keep_per_browser: std::collections::HashMap = + std::collections::HashMap::new(); + for (browser, versions) in &removal_versions_by_browser { let total = data .browsers .get(browser.as_str()) .map(|v| v.len()) .unwrap_or(0); - let removing = *removal_counts.get(browser.as_str()).unwrap_or(&0); - if removing >= total { - log::info!("Keeping last available version: {browser} {version}"); - *removal_counts.get_mut(browser.as_str()).unwrap() -= 1; + if versions.len() >= total { + if let Some(latest) = versions + .iter() + .max_by(|a, b| crate::api_client::compare_versions(a, b)) + { + keep_per_browser.insert(browser.clone(), latest.clone()); + } + } + } + drop(data); + to_remove.retain(|(browser, version)| { + if keep_per_browser + .get(browser) + .is_some_and(|keep| keep == version) + { + log::info!("Keeping latest available version: {browser} {version}"); return false; } true diff --git a/src-tauri/src/profile/manager.rs b/src-tauri/src/profile/manager.rs index dfc75a1..d29f5a8 100644 --- a/src-tauri/src/profile/manager.rs +++ b/src-tauri/src/profile/manager.rs @@ -1509,6 +1509,7 @@ impl ProfileManager { }; let mut merged = latest_profile.clone(); + let mut detected_stop = false; if let Some(pid) = found_pid { if merged.process_id != Some(pid) { @@ -1523,6 +1524,15 @@ impl ProfileManager { if let Err(e) = self.save_profile(&merged) { log::warn!("Warning: Failed to clear profile PID: {e}"); } + detected_stop = true; + } + + if detected_stop { + if let Some(updated) = crate::auto_updater::AutoUpdater::instance() + .update_profile_to_latest_installed(&app_handle, &merged) + { + merged = updated; + } } // Emit profile update event to frontend @@ -1537,7 +1547,7 @@ impl ProfileManager { // Check Camoufox status using CamoufoxManager async fn check_camoufox_status( &self, - _app_handle: &tauri::AppHandle, + app_handle: &tauri::AppHandle, profile: &BrowserProfile, ) -> Result> { let launcher = self.camoufox_manager; @@ -1611,6 +1621,12 @@ impl ProfileManager { log::warn!("Warning: Failed to clear Camoufox profile process info: {e}"); } + if let Some(updated) = crate::auto_updater::AutoUpdater::instance() + .update_profile_to_latest_installed(app_handle, &latest) + { + latest = updated; + } + if let Err(e) = events::emit("profile-updated", &latest) { log::warn!("Warning: Failed to emit profile update event: {e}"); } @@ -1647,6 +1663,12 @@ impl ProfileManager { ); } + if let Some(updated) = crate::auto_updater::AutoUpdater::instance() + .update_profile_to_latest_installed(app_handle, &latest) + { + latest = updated; + } + // Emit profile update event to frontend if let Err(e3) = events::emit("profile-updated", &latest) { log::warn!("Warning: Failed to emit profile update event: {e3}"); @@ -1661,7 +1683,7 @@ impl ProfileManager { // Check Wayfern status using WayfernManager async fn check_wayfern_status( &self, - _app_handle: &tauri::AppHandle, + app_handle: &tauri::AppHandle, profile: &BrowserProfile, ) -> Result> { let manager = self.wayfern_manager; @@ -1735,6 +1757,12 @@ impl ProfileManager { log::warn!("Warning: Failed to clear Wayfern profile process info: {e}"); } + if let Some(updated) = crate::auto_updater::AutoUpdater::instance() + .update_profile_to_latest_installed(app_handle, &latest) + { + latest = updated; + } + if let Err(e) = events::emit("profile-updated", &latest) { log::warn!("Warning: Failed to emit profile update event: {e}"); }