From c878c7f678b8a07ed8c6839b74a28387c9ea49b7 Mon Sep 17 00:00:00 2001 From: Candifloss Date: Thu, 20 Nov 2025 12:28:26 +0530 Subject: [PATCH] Make the time widget work - Show real time, not dummy text - Update time every minute - Use slint's Timer --- Cargo.toml | 2 ++ src/widgets.rs | 58 ++++++++++++++++++++++++++++++++++++++++++++----- ui/topbar.slint | 7 ++++-- 3 files changed, 59 insertions(+), 8 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 3d105a4..ce78686 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,10 +7,12 @@ authors = ["candifloss "] readme = "README.md" [dependencies] +chrono = "0.4.42" dirs = "6.0.0" i-slint-backend-winit = { version = "1.14.1", features = ["x11"] } serde = { version = "1.0.228", features = ["derive"] } slint = { version = "1.14.1", features = ["backend-winit"] } +tokio = { version = "1.48.0", features = ["macros", "rt-multi-thread", "time"] } toml = "0.9.8" [build-dependencies] diff --git a/src/widgets.rs b/src/widgets.rs index 6a69ede..155bd85 100644 --- a/src/widgets.rs +++ b/src/widgets.rs @@ -1,20 +1,66 @@ use crate::TopBar; -use slint::ComponentHandle; +use chrono::{Local, Timelike}; +use slint::{ComponentHandle, SharedString, Timer, TimerMode}; use std::process::{Child, Command}; +use std::time::Duration; -// Run a command fn run_cmd(cmd: &str) -> Option { Command::new(cmd).spawn().ok() } -/// Connect widget callbacks for the top bar. +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_none() { - return; + if weak.upgrade().is_some() { + run_cmd("xclock"); } - run_cmd("xclock"); }); + + // Start the time-updating timer + start_clock_updater(ui); } diff --git a/ui/topbar.slint b/ui/topbar.slint index f3acd3a..9847874 100644 --- a/ui/topbar.slint +++ b/ui/topbar.slint @@ -2,11 +2,14 @@ import { TimeWidget } from "time-widget.slint"; export component TopBar inherits Window { + // Common properties in property bar_width; in property bar_height; in property def_font_size; in property def_font_fam; + // Time widget + in-out property time_text; callback show_clock(); title: "chocobar"; @@ -51,10 +54,10 @@ export component TopBar inherits Window { width: parent.width/3; HorizontalLayout { - alignment: end; // RIght-align + alignment: end; // Right-align TimeWidget { - time_text: "11:43 AM"; // Fix this: Replace with time value + time_text: root.time_text; // Get from root show_clock => root.show_clock(); // Forward the widget's callback to the root's to access from Rust } }