diff --git a/src-tauri/src/auto_updater.rs b/src-tauri/src/auto_updater.rs index 60a35ac..4924a84 100644 --- a/src-tauri/src/auto_updater.rs +++ b/src-tauri/src/auto_updater.rs @@ -458,6 +458,39 @@ impl AutoUpdater { Ok(()) } + + /// Get pending update versions for a specific browser + /// Returns a set of (browser, version) pairs that have pending updates + pub fn get_pending_update_versions( + &self, + ) -> Result, Box> + { + let state = self.load_auto_update_state()?; + let mut pending_versions = std::collections::HashSet::new(); + + for update in &state.pending_updates { + pending_versions.insert((update.browser.clone(), update.new_version.clone())); + } + + Ok(pending_versions) + } + + /// Get pending update for a specific browser version if it exists + pub fn get_pending_update( + &self, + browser: &str, + current_version: &str, + ) -> Result, Box> { + let state = self.load_auto_update_state()?; + + for update in &state.pending_updates { + if update.browser == browser && update.current_version == current_version { + return Ok(Some(update.clone())); + } + } + + Ok(None) + } } // Tauri commands diff --git a/src-tauri/src/browser_runner.rs b/src-tauri/src/browser_runner.rs index 9cd3de7..5e80397 100644 --- a/src-tauri/src/browser_runner.rs +++ b/src-tauri/src/browser_runner.rs @@ -1007,6 +1007,19 @@ impl BrowserRunner { }) } + /// Update a profile's browser version + pub fn update_profile_version( + &self, + app_handle: &tauri::AppHandle, + profile_id: &str, + version: &str, + ) -> Result> { + let profile_manager = ProfileManager::instance(); + profile_manager + .update_profile_version(app_handle, profile_id, version) + .map_err(|e| format!("Failed to update profile version: {e}").into()) + } + pub fn delete_profile( &self, app_handle: tauri::AppHandle, @@ -1110,6 +1123,45 @@ impl BrowserRunner { // Clear the process ID from the profile let mut updated_profile = profile.clone(); updated_profile.process_id = None; + + // Check for pending updates and apply them for Camoufox profiles too + let auto_updater = crate::auto_updater::AutoUpdater::instance(); + if let Ok(Some(pending_update)) = + auto_updater.get_pending_update(&profile.browser, &profile.version) + { + println!( + "Found pending update for Camoufox profile {}: {} -> {}", + profile.name, profile.version, pending_update.new_version + ); + + // Update the profile to the new version + match self.update_profile_version( + &app_handle, + &profile.id.to_string(), + &pending_update.new_version, + ) { + Ok(updated_profile_after_update) => { + println!( + "Successfully updated Camoufox profile {} from version {} to {}", + profile.name, profile.version, pending_update.new_version + ); + updated_profile = updated_profile_after_update; + + // Remove the pending update from the auto updater state + if let Err(e) = auto_updater.dismiss_update_notification(&pending_update.id) { + eprintln!("Warning: Failed to dismiss pending update notification: {e}"); + } + } + Err(e) => { + eprintln!( + "Failed to apply pending update for Camoufox profile {}: {}", + profile.name, e + ); + // Continue with the original profile update (just clearing process_id) + } + } + } + self .save_process_info(&updated_profile) .map_err(|e| format!("Failed to update profile: {e}"))?; @@ -1288,6 +1340,45 @@ impl BrowserRunner { // Clear the process ID from the profile let mut updated_profile = profile.clone(); updated_profile.process_id = None; + + // Check for pending updates and apply them + let auto_updater = crate::auto_updater::AutoUpdater::instance(); + if let Ok(Some(pending_update)) = + auto_updater.get_pending_update(&profile.browser, &profile.version) + { + println!( + "Found pending update for profile {}: {} -> {}", + profile.name, profile.version, pending_update.new_version + ); + + // Update the profile to the new version + match self.update_profile_version( + &app_handle, + &profile.id.to_string(), + &pending_update.new_version, + ) { + Ok(updated_profile_after_update) => { + println!( + "Successfully updated profile {} from version {} to {}", + profile.name, profile.version, pending_update.new_version + ); + updated_profile = updated_profile_after_update; + + // Remove the pending update from the auto updater state + if let Err(e) = auto_updater.dismiss_update_notification(&pending_update.id) { + eprintln!("Warning: Failed to dismiss pending update notification: {e}"); + } + } + Err(e) => { + eprintln!( + "Failed to apply pending update for profile {}: {}", + profile.name, e + ); + // Continue with the original profile update (just clearing process_id) + } + } + } + self .save_process_info(&updated_profile) .map_err(|e| format!("Failed to update profile: {e}"))?; diff --git a/src-tauri/src/downloaded_browsers.rs b/src-tauri/src/downloaded_browsers.rs index 1a84d3d..74ed6f3 100644 --- a/src-tauri/src/downloaded_browsers.rs +++ b/src-tauri/src/downloaded_browsers.rs @@ -202,6 +202,16 @@ impl DownloadedBrowsersRegistry { running_profiles.iter().cloned().collect(); let mut cleaned_up = Vec::new(); + // Get pending update versions from auto updater + let pending_updates = + match crate::auto_updater::AutoUpdater::instance().get_pending_update_versions() { + Ok(updates) => updates, + Err(e) => { + eprintln!("Warning: Failed to get pending updates for cleanup: {e}"); + std::collections::HashSet::new() + } + }; + // Collect all downloaded browsers that are not in active profiles let mut to_remove = Vec::new(); { @@ -222,6 +232,18 @@ impl DownloadedBrowsersRegistry { continue; } + // Don't remove if this version has a pending update for a running profile + // This handles the case where a running profile has an update downloaded but not yet applied + if pending_updates.contains(&browser_version) { + // Check if there are any running profiles for this browser that could be updated + let has_running_profile_for_browser = + running_profiles.iter().any(|(b, _)| b == browser); + if has_running_profile_for_browser { + println!("Keeping: {browser} {version} (pending update for running profile)"); + continue; + } + } + // Mark for removal to_remove.push(browser_version); println!("Marking for removal: {browser} {version} (not used by any profile)");