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 { 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); }