diff --git a/desktop/angular/src/app/layout/navigation/navigation.html b/desktop/angular/src/app/layout/navigation/navigation.html index ae961f6c..8d9989dd 100644 --- a/desktop/angular/src/app/layout/navigation/navigation.html +++ b/desktop/angular/src/app/layout/navigation/navigation.html @@ -222,8 +222,8 @@ {{ pauseInfo }} - - Auto-resume at {{ pauseInfoTillTime }} + + {{ pauseInfoTillTime }}
diff --git a/desktop/angular/src/app/layout/navigation/navigation.ts b/desktop/angular/src/app/layout/navigation/navigation.ts index 46980ed4..ee99e324 100644 --- a/desktop/angular/src/app/layout/navigation/navigation.ts +++ b/desktop/angular/src/app/layout/navigation/navigation.ts @@ -50,8 +50,12 @@ export class NavigationComponent implements OnInit { return ''; } get pauseInfoTillTime(): string { - if (this.isPaused && this.pauseState?.TillTime) - return new Date(this.pauseState.TillTime).toLocaleTimeString(undefined, { hour12: false }); + if (this.isPaused && this.pauseState?.TillTime) { + const date = new Date(this.pauseState.TillTime); + if (isNaN(date.getTime()) || date.getTime() < Date.now()) + return ''; + return `Auto-resume at ${date.toLocaleTimeString(undefined, { hour12: false })}`; + } return ''; } diff --git a/desktop/tauri/src-tauri/src/traymenu.rs b/desktop/tauri/src-tauri/src/traymenu.rs index 490b55aa..53c06e13 100644 --- a/desktop/tauri/src-tauri/src/traymenu.rs +++ b/desktop/tauri/src-tauri/src/traymenu.rs @@ -2,7 +2,7 @@ use std::ops::Deref; use std::sync::atomic::AtomicBool; use std::sync::RwLock; use std::{sync::atomic::Ordering}; -use chrono::{DateTime}; +use chrono::{DateTime, Local}; use log::{debug, error}; use tauri::{ @@ -163,14 +163,22 @@ fn build_tray_menu( (false, true) => "SPN is paused", _ => unreachable!(), // We already checked at least one is true }; - let status_item = MenuItemBuilder::with_id(PAUSE_INFO_KEY, status_text).enabled(false).build(app)?; + let status_item = MenuItemBuilder::with_id(PAUSE_INFO_KEY, status_text).enabled(false).build(app).ok(); - let formatted_time = DateTime::parse_from_rfc3339(&pause_info.till_time) - .map(|dt| dt.with_timezone(&chrono::Local).format("%H:%M:%S").to_string()) - .unwrap_or_else(|_| pause_info.till_time.clone()); - let time_item = MenuItemBuilder::with_id(PAUSE_INFO_TIME_KEY, format!("Auto-resume at {}", formatted_time)).enabled(false).build(app)?; - let resume_item = MenuItemBuilder::with_id(RESUME_KEY, "Resume now").build(app)?; - (Some(status_item), Some(time_item), Some(resume_item)) + let time_item = if let Ok(resume_time) = DateTime::parse_from_rfc3339(&pause_info.till_time) { + let resume_time_local = resume_time.with_timezone(&Local); + if resume_time_local > Local::now() { + let formatted_time = resume_time_local.format("%H:%M:%S").to_string(); + MenuItemBuilder::with_id(PAUSE_INFO_TIME_KEY, format!("Auto-resume at {}", formatted_time)).enabled(false).build(app).ok() + } else { + None + } + } else { + None + }; + + let resume_item = MenuItemBuilder::with_id(RESUME_KEY, "Resume now").build(app).ok(); + (status_item, time_item, resume_item) } else { (None, None, None) }; diff --git a/service/control/pause.go b/service/control/pause.go index 7b07e1fc..3d319f98 100644 --- a/service/control/pause.go +++ b/service/control/pause.go @@ -89,11 +89,11 @@ func (c *Control) resume() (retErr error) { defer c.locker.Unlock() defer func() { - // update states after resume attempt - c.updateStatesAndNotify() - // log error if resume failed if retErr != nil { - c.mgr.Error("Failed to resume: " + retErr.Error()) + c.updateStatesAndNotifyError("Resume operation failed", retErr) + c.mgr.Error("Error occurred while resuming: " + retErr.Error()) + } else { + c.updateStatesAndNotify() } }() @@ -228,3 +228,26 @@ func (c *Control) updateStatesAndNotify() { notifications.Notify(c.pauseNotification) c.pauseNotification.SyncWithState(c.states) } + +// updateStatesAndNotifyError updates the paused states and sends an error notification. +// No thread safety, caller must hold c.locker. +func (c *Control) updateStatesAndNotifyError(errDescription string, err error) { + if err == nil { + return + } + + if errDescription == "" { + errDescription = "Error" + } + + // Error notification + c.pauseNotification = ¬ifications.Notification{ + EventID: "control:error", + Type: notifications.Error, + Title: errDescription, + Message: err.Error(), + EventData: &c.pauseInfo, + } + notifications.Notify(c.pauseNotification) + c.pauseNotification.SyncWithState(c.states) +}