time: Calculate period to wait on each iteration (#237)
Computing the delay only once won't work; it has to be be done each time to stay properly in sync. The time widget should now reliably update at the minute. Co-authored-by: Michael Murphy <michael@mmurphy.dev>
This commit is contained in:
parent
43de23e94a
commit
fee7eefe5b
3 changed files with 22 additions and 22 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
|
@ -1035,6 +1035,7 @@ dependencies = [
|
||||||
"nix 0.26.4",
|
"nix 0.26.4",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"rust-embed 6.8.1",
|
"rust-embed 6.8.1",
|
||||||
|
"tokio",
|
||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,9 @@ license = "GPL-3.0-or-later"
|
||||||
icon-loader = { version = "0.3.6", features = ["gtk"] }
|
icon-loader = { version = "0.3.6", features = ["gtk"] }
|
||||||
libcosmic.workspace = true
|
libcosmic.workspace = true
|
||||||
nix = "0.26.2"
|
nix = "0.26.2"
|
||||||
chrono = { version = "0.4.23", features = ["clock"] }
|
chrono = { version = "0.4.34", features = ["clock"] }
|
||||||
once_cell = "1"
|
once_cell = "1"
|
||||||
|
tokio = { version = "1.36.0", features = ["time"] }
|
||||||
tracing.workspace = true
|
tracing.workspace = true
|
||||||
|
|
||||||
# Application i18n
|
# Application i18n
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ use cosmic::applet::{menu_button, padded_control};
|
||||||
use cosmic::cctk::sctk::reexports::calloop;
|
use cosmic::cctk::sctk::reexports::calloop;
|
||||||
use cosmic::iced::wayland::popup::{destroy_popup, get_popup};
|
use cosmic::iced::wayland::popup::{destroy_popup, get_popup};
|
||||||
use cosmic::iced::{
|
use cosmic::iced::{
|
||||||
time,
|
subscription,
|
||||||
widget::{column, row, text, vertical_space},
|
widget::{column, row, text, vertical_space},
|
||||||
window, Alignment, Length, Rectangle, Subscription,
|
window, Alignment, Length, Rectangle, Subscription,
|
||||||
};
|
};
|
||||||
|
|
@ -15,7 +15,7 @@ use cosmic::{
|
||||||
Element, Theme,
|
Element, Theme,
|
||||||
};
|
};
|
||||||
|
|
||||||
use chrono::{DateTime, Datelike, Local, Months, NaiveDate, Timelike, Weekday};
|
use chrono::{DateTime, Datelike, DurationRound, Local, Months, NaiveDate, Timelike, Weekday};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use crate::fl;
|
use crate::fl;
|
||||||
|
|
@ -24,8 +24,8 @@ use cosmic::applet::token::subscription::{
|
||||||
activation_token_subscription, TokenRequest, TokenUpdate,
|
activation_token_subscription, TokenRequest, TokenUpdate,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
enum Every {
|
enum Every {
|
||||||
Minute,
|
Minute,
|
||||||
Second,
|
Second,
|
||||||
|
|
@ -94,26 +94,9 @@ impl cosmic::Application for Window {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn subscription(&self) -> Subscription<Message> {
|
fn subscription(&self) -> Subscription<Message> {
|
||||||
const FALLBACK_DELAY: u64 = 500;
|
|
||||||
let update_delay = match self.update_at {
|
|
||||||
Every::Minute => chrono::Duration::minutes(1),
|
|
||||||
Every::Second => chrono::Duration::seconds(1),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Calculate the time until next second/minute so we can sleep the thread until then.
|
|
||||||
let now = Local::now().time();
|
|
||||||
let next = (now + update_delay)
|
|
||||||
.with_second(0)
|
|
||||||
.expect("Setting seconds to 0 should always be possible")
|
|
||||||
.with_nanosecond(0)
|
|
||||||
.expect("Setting nanoseconds to 0 should always be possible.");
|
|
||||||
let wait = 1.max((next - now).num_milliseconds());
|
|
||||||
Subscription::batch(vec![
|
Subscription::batch(vec![
|
||||||
rectangle_tracker_subscription(0).map(|e| Message::Rectangle(e.1)),
|
rectangle_tracker_subscription(0).map(|e| Message::Rectangle(e.1)),
|
||||||
time::every(Duration::from_millis(
|
time_subscription(self.update_at).map(|_| Message::Tick),
|
||||||
wait.try_into().unwrap_or(FALLBACK_DELAY),
|
|
||||||
))
|
|
||||||
.map(|_| Message::Tick),
|
|
||||||
activation_token_subscription(0).map(Message::Token),
|
activation_token_subscription(0).map(Message::Token),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
@ -367,3 +350,18 @@ fn date_button(
|
||||||
button
|
button
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn time_subscription(update_at: Every) -> Subscription<()> {
|
||||||
|
subscription::unfold("time-sub", (), move |()| async move {
|
||||||
|
let now = Local::now();
|
||||||
|
let update_delay = match update_at {
|
||||||
|
Every::Minute => chrono::TimeDelta::minutes(1),
|
||||||
|
Every::Second => chrono::TimeDelta::seconds(1),
|
||||||
|
};
|
||||||
|
let duration = ((now + update_delay).duration_trunc(update_delay).unwrap() - now)
|
||||||
|
.to_std()
|
||||||
|
.unwrap();
|
||||||
|
tokio::time::sleep(duration).await;
|
||||||
|
((), ())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue