diff --git a/src/cortex-tui/src/runner/app_runner/runner.rs b/src/cortex-tui/src/runner/app_runner/runner.rs index e79ac3746..7a36e9276 100644 --- a/src/cortex-tui/src/runner/app_runner/runner.rs +++ b/src/cortex-tui/src/runner/app_runner/runner.rs @@ -557,7 +557,7 @@ impl AppRunner { // 2. Background update check task - check for new versions without blocking startup let update_check_task = tokio::spawn(async move { match UpdateManager::new() { - Ok(manager) => match manager.check_update().await { + Ok(mut manager) => match manager.check_update_for_notification().await { Ok(info) => info, Err(e) => { tracing::debug!("Update check failed: {}", e); diff --git a/src/cortex-update/src/config.rs b/src/cortex-update/src/config.rs index b352ae68a..91f006841 100644 --- a/src/cortex-update/src/config.rs +++ b/src/cortex-update/src/config.rs @@ -145,4 +145,31 @@ impl UpdateConfig { pub fn is_version_skipped(&self, version: &str) -> bool { self.skip_version.as_deref() == Some(version) } + + /// Check if the user has already been notified about a version. + pub fn is_version_notified(&self, version: &str) -> bool { + self.last_notified_version.as_deref() == Some(version) + } + + /// Remember that the user has been notified about a version. + pub fn mark_version_notified(&mut self, version: &str) { + self.last_notified_version = Some(version.to_string()); + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn tracks_last_notified_version() { + let mut config = UpdateConfig::default(); + + assert!(!config.is_version_notified("1.2.3")); + + config.mark_version_notified("1.2.3"); + + assert!(config.is_version_notified("1.2.3")); + assert!(!config.is_version_notified("1.2.4")); + } } diff --git a/src/cortex-update/src/manager.rs b/src/cortex-update/src/manager.rs index 9b7f2a034..8832498ca 100644 --- a/src/cortex-update/src/manager.rs +++ b/src/cortex-update/src/manager.rs @@ -101,6 +101,29 @@ impl UpdateManager { self.check_update_forced().await } + /// Check for an update that should be shown as a user notification. + /// + /// This suppresses repeat notifications for the same latest version while + /// leaving the regular update check behavior unchanged for explicit update + /// commands and install flows. + pub async fn check_update_for_notification(&mut self) -> UpdateResult> { + let info = match self.check_update().await? { + Some(info) => info, + None => return Ok(None), + }; + + if self.config.is_version_notified(&info.latest_version) { + return Ok(None); + } + + self.config.mark_version_notified(&info.latest_version); + if let Err(e) = self.config.save() { + tracing::warn!("Failed to save update notification state: {}", e); + } + + Ok(Some(info)) + } + /// Force check for updates (bypass cache). pub async fn check_update_forced(&self) -> UpdateResult> { let latest = self.client.get_latest(self.config.channel).await?;