- Show real time, not dummy text - Update time every minute - Use slint's Timer
67 lines
1.8 KiB
Rust
67 lines
1.8 KiB
Rust
use crate::TopBar;
|
|
use chrono::{Local, Timelike};
|
|
use slint::{ComponentHandle, SharedString, Timer, TimerMode};
|
|
use std::process::{Child, Command};
|
|
use std::time::Duration;
|
|
|
|
fn run_cmd(cmd: &str) -> Option<Child> {
|
|
Command::new(cmd).spawn().ok()
|
|
}
|
|
|
|
fn format_time() -> String {
|
|
Local::now().format("%I:%M %p").to_string()
|
|
}
|
|
|
|
fn time_until_next_minute() -> Duration {
|
|
let now = Local::now();
|
|
let secs = now.second();
|
|
let nanos = now.nanosecond();
|
|
|
|
Duration::from_secs(60 - u64::from(secs)) - Duration::from_nanos(u64::from(nanos))
|
|
}
|
|
|
|
fn start_clock_updater(ui: &TopBar) {
|
|
let weak = ui.as_weak();
|
|
|
|
// One-shot timer for the first update
|
|
let initial_timer = Box::leak(Box::new(Timer::default()));
|
|
|
|
// Repeating timer (every 60 seconds)
|
|
let repeating_timer = Box::leak(Box::new(Timer::default()));
|
|
|
|
// 1. Initial immediate update
|
|
if let Some(ui) = weak.upgrade() {
|
|
ui.set_time_text(SharedString::from(format_time()));
|
|
}
|
|
|
|
// 2. Schedule first update exactly at next minute boundary
|
|
initial_timer.start(TimerMode::SingleShot, time_until_next_minute(), move || {
|
|
// Update at the boundary
|
|
if let Some(ui) = weak.upgrade() {
|
|
ui.set_time_text(SharedString::from(format_time()));
|
|
}
|
|
|
|
// 3. Start repeating 60-sec timer
|
|
let weak_clone = weak.clone();
|
|
repeating_timer.start(TimerMode::Repeated, Duration::from_secs(60), move || {
|
|
if let Some(ui) = weak_clone.upgrade() {
|
|
ui.set_time_text(SharedString::from(format_time()));
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
pub fn install_callbacks(ui: &TopBar) {
|
|
let weak = ui.as_weak();
|
|
|
|
// Click handler
|
|
ui.on_show_clock(move || {
|
|
if weak.upgrade().is_some() {
|
|
run_cmd("xclock");
|
|
}
|
|
});
|
|
|
|
// Start the time-updating timer
|
|
start_clock_updater(ui);
|
|
}
|