fucking something i forgot
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
//! Clock service: emits a `ServiceEvent` whenever a clock kind's displayed
|
||||
//! value changes (minute or second rollover).
|
||||
//!
|
||||
//! The ticker knows nothing about the app's `Message` type; it produces
|
||||
//! protocol events from `common` that core routes to subscribed modules.
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
|
||||
use iced::{futures::SinkExt, Subscription};
|
||||
|
||||
use common::{Service, ServiceEvent};
|
||||
|
||||
/// Route-key namespace owned by this service; keys are `"clock.<kind>"`.
|
||||
pub const NAMESPACE: &str = "clock.";
|
||||
|
||||
/// What a clock subscription wants: the tick interval and payload selector.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
||||
pub enum ClockKind {
|
||||
Mins,
|
||||
Seconds,
|
||||
}
|
||||
|
||||
impl ClockKind {
|
||||
/// Route key a module subscribes under to receive this kind's ticks.
|
||||
pub fn key(self) -> Service {
|
||||
Service(match self {
|
||||
Self::Mins => "clock.mins",
|
||||
Self::Seconds => "clock.seconds",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Clock tick payload: the value plus the kind that produced it.
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
pub struct ClockPayload {
|
||||
pub kind: ClockKind,
|
||||
pub value: String,
|
||||
}
|
||||
|
||||
/// Emits a payload only when a kind's displayed value changes (minute or
|
||||
/// second rollover). Drive `tick` once per second.
|
||||
#[derive(Default)]
|
||||
pub struct ClockTicker {
|
||||
last: HashMap<ClockKind, String>,
|
||||
}
|
||||
|
||||
impl ClockTicker {
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
/// Subscription that emits a `ServiceEvent` on every change.
|
||||
pub fn run() -> Subscription<ServiceEvent> {
|
||||
Subscription::run_with((), |_| {
|
||||
iced::stream::channel(
|
||||
0,
|
||||
|mut sender: iced::futures::channel::mpsc::Sender<ServiceEvent>| async move {
|
||||
let mut clock = ClockTicker::new();
|
||||
let mut interval = tokio::time::interval(std::time::Duration::from_secs(1));
|
||||
loop {
|
||||
interval.tick().await;
|
||||
for payload in clock.tick() {
|
||||
let event = ServiceEvent {
|
||||
key: payload.kind.key(),
|
||||
payload: Arc::new(payload),
|
||||
};
|
||||
if sender.send(event).await.is_err() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns a payload per kind whose value changed since the last tick.
|
||||
/// The second that rolls into a new minute yields `[Seconds, Mins]`.
|
||||
pub fn tick(&mut self) -> Vec<ClockPayload> {
|
||||
let now = chrono::Local::now();
|
||||
[ClockKind::Seconds, ClockKind::Mins]
|
||||
.into_iter()
|
||||
.filter_map(|kind| {
|
||||
let value = now
|
||||
.format(match kind {
|
||||
ClockKind::Mins => "%H:%M",
|
||||
ClockKind::Seconds => "%H:%M:%S",
|
||||
})
|
||||
.to_string();
|
||||
match self.last.get(&kind) {
|
||||
Some(prev) if *prev == value => None,
|
||||
_ => {
|
||||
self.last.insert(kind, value.clone());
|
||||
Some(ClockPayload { kind, value })
|
||||
}
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user