Improve pause info display and error handling
This commit is contained in:
@@ -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/>
|
||||||
|
|||||||
@@ -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 '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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 = ¬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)
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user