Improve pause info display and error handling

This commit is contained in:
Alexandr Stelnykovych
2025-11-26 13:01:24 +02:00
parent 4913147dd5
commit d635db77c2
4 changed files with 51 additions and 16 deletions

View File

@@ -222,8 +222,8 @@
<span class="text-secondary"> <span class="text-secondary">
<span class="text-secondary">{{ pauseInfo }} </span> <span class="text-secondary">{{ pauseInfo }} </span>
</span> </span>
<span class="text-secondary"> <span class="text-secondary" *ngIf="pauseInfoTillTime">
Auto-resume at <span class="text-secondary">{{ pauseInfoTillTime }} </span> {{ pauseInfoTillTime }}
</span> </span>
</div> </div>
<hr/> <hr/>

View File

@@ -50,8 +50,12 @@ export class NavigationComponent implements OnInit {
return ''; return '';
} }
get pauseInfoTillTime(): string { get pauseInfoTillTime(): string {
if (this.isPaused && this.pauseState?.TillTime) if (this.isPaused && this.pauseState?.TillTime) {
return new Date(this.pauseState.TillTime).toLocaleTimeString(undefined, { hour12: false }); 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 ''; return '';
} }

View File

@@ -2,7 +2,7 @@ use std::ops::Deref;
use std::sync::atomic::AtomicBool; use std::sync::atomic::AtomicBool;
use std::sync::RwLock; use std::sync::RwLock;
use std::{sync::atomic::Ordering}; use std::{sync::atomic::Ordering};
use chrono::{DateTime}; use chrono::{DateTime, Local};
use log::{debug, error}; use log::{debug, error};
use tauri::{ use tauri::{
@@ -163,14 +163,22 @@ fn build_tray_menu(
(false, true) => "SPN is paused", (false, true) => "SPN is paused",
_ => unreachable!(), // We already checked at least one is true _ => 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) let time_item = if let Ok(resume_time) = DateTime::parse_from_rfc3339(&pause_info.till_time) {
.map(|dt| dt.with_timezone(&chrono::Local).format("%H:%M:%S").to_string()) let resume_time_local = resume_time.with_timezone(&Local);
.unwrap_or_else(|_| pause_info.till_time.clone()); if resume_time_local > Local::now() {
let time_item = MenuItemBuilder::with_id(PAUSE_INFO_TIME_KEY, format!("Auto-resume at {}", formatted_time)).enabled(false).build(app)?; let formatted_time = resume_time_local.format("%H:%M:%S").to_string();
let resume_item = MenuItemBuilder::with_id(RESUME_KEY, "Resume now").build(app)?; MenuItemBuilder::with_id(PAUSE_INFO_TIME_KEY, format!("Auto-resume at {}", formatted_time)).enabled(false).build(app).ok()
(Some(status_item), Some(time_item), Some(resume_item)) } else {
None
}
} else {
None
};
let resume_item = MenuItemBuilder::with_id(RESUME_KEY, "Resume now").build(app).ok();
(status_item, time_item, resume_item)
} else { } else {
(None, None, None) (None, None, None)
}; };

View File

@@ -89,11 +89,11 @@ func (c *Control) resume() (retErr error) {
defer c.locker.Unlock() defer c.locker.Unlock()
defer func() { defer func() {
// update states after resume attempt
c.updateStatesAndNotify()
// log error if resume failed
if retErr != nil { 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) notifications.Notify(c.pauseNotification)
c.pauseNotification.SyncWithState(c.states) 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 = &notifications.Notification{
EventID: "control:error",
Type: notifications.Error,
Title: errDescription,
Message: err.Error(),
EventData: &c.pauseInfo,
}
notifications.Notify(c.pauseNotification)
c.pauseNotification.SyncWithState(c.states)
}