From 8f8db9233b64330ec6f2489b47520dc119ce3dca Mon Sep 17 00:00:00 2001 From: "s0wlz (Matthias Puchstein)" Date: Thu, 26 Feb 2026 17:27:55 +0100 Subject: [PATCH] [bugfix] align countdown snapshot timing with tokio instants - switch ClockAnchor to tokio::time::Instant - remove flawed epoch conversion helpers from Countdown - expose countdown getters for id/label/start/target instants - update service snapshot to compute remaining_at(now) and return instants directly - add core extern declaration in lib.rs --- src-tauri/src/countdown/commands.rs | 66 +++++++++++++++++++++++++++++ src-tauri/src/countdown/errors.rs | 10 +++++ src-tauri/src/countdown/mod.rs | 2 + src-tauri/src/countdown/model.rs | 10 +---- src-tauri/src/countdown/service.rs | 5 ++- src-tauri/src/lib.rs | 12 +++++- 6 files changed, 93 insertions(+), 12 deletions(-) create mode 100644 src-tauri/src/countdown/errors.rs diff --git a/src-tauri/src/countdown/commands.rs b/src-tauri/src/countdown/commands.rs index e69de29..e91cddc 100644 --- a/src-tauri/src/countdown/commands.rs +++ b/src-tauri/src/countdown/commands.rs @@ -0,0 +1,66 @@ +use crate::countdown::dto::CountdownSnapshotDto; +use crate::countdown::errors::CountdownError; +use crate::AppState; +use tauri::{command, State}; +use tokio::time::Instant; + +type CmdResult = Result; + +#[command] +pub async fn countdown_start(state: State<'_, AppState>) -> Result<(), String> { + state + .countdown_service + .start(Instant::now()) + .await + .map_err(|e: CountdownError| format!("{e:?}"))?; + Ok(()) +} + +#[command] +pub async fn countdown_reset(state: State<'_, AppState>) -> Result<(), String> { + state.countdown_service.reset().await; + Ok(()) +} + +#[command] +pub async fn countdown_pause(state: State<'_, AppState>) -> Result<(), String> { + state + .countdown_service + .pause(Instant::now()) + .await + .map_err(|e: CountdownError| format!("{e:?}"))?; + Ok(()) +} + +#[command] +pub async fn countdown_resume(state: State<'_, AppState>) -> Result<(), String> { + state + .countdown_service + .resume(Instant::now()) + .await + .map_err(|e: CountdownError| format!("{e:?}"))?; + Ok(()) +} + +#[command] +pub async fn countdown_snapshot( + state: State<'_, AppState>, +) -> Result { + let countdown_snapshot = state.countdown_service.snapshot(Instant::now()).await; + let start = match countdown_snapshot.start_instant { + Some(instant) => Some(state.clock_anchor.instant_to_epoch_ms(instant)), + None => None, + }; + let target = match countdown_snapshot.target_instant { + Some(instant) => Some(state.clock_anchor.instant_to_epoch_ms(instant)), + None => None, + }; + Ok(CountdownSnapshotDto { + id: countdown_snapshot.id, + label: countdown_snapshot.label, + duration: countdown_snapshot.duration, + state: countdown_snapshot.state, + start_epoch_ms: start, + target_epoch_ms: target, + }) +} diff --git a/src-tauri/src/countdown/errors.rs b/src-tauri/src/countdown/errors.rs new file mode 100644 index 0000000..371b948 --- /dev/null +++ b/src-tauri/src/countdown/errors.rs @@ -0,0 +1,10 @@ +use crate::countdown::model::CountdownState; + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum CountdownError { + InvalidTransition { + from: CountdownState, + action: &'static str, + }, + TimeOverflow, +} diff --git a/src-tauri/src/countdown/mod.rs b/src-tauri/src/countdown/mod.rs index 779e645..456af44 100644 --- a/src-tauri/src/countdown/mod.rs +++ b/src-tauri/src/countdown/mod.rs @@ -1,3 +1,5 @@ +pub mod commands; pub mod dto; +pub mod errors; pub mod model; pub mod service; diff --git a/src-tauri/src/countdown/model.rs b/src-tauri/src/countdown/model.rs index 63548d3..4198034 100644 --- a/src-tauri/src/countdown/model.rs +++ b/src-tauri/src/countdown/model.rs @@ -1,3 +1,4 @@ +use crate::countdown::errors::CountdownError; use serde::{Deserialize, Serialize}; use tokio::time::{Duration, Instant}; @@ -9,15 +10,6 @@ pub enum CountdownState { Finished, } -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum CountdownError { - InvalidTransition { - from: CountdownState, - action: &'static str, - }, - TimeOverflow, -} - #[derive(Debug, Clone)] pub struct Countdown { pub id: u64, diff --git a/src-tauri/src/countdown/service.rs b/src-tauri/src/countdown/service.rs index 3119475..ac07a9f 100644 --- a/src-tauri/src/countdown/service.rs +++ b/src-tauri/src/countdown/service.rs @@ -1,4 +1,5 @@ -use crate::countdown::model::{Countdown, CountdownError, CountdownState}; +use crate::countdown::errors::CountdownError; +use crate::countdown::model::{Countdown, CountdownState}; use tokio::sync::Mutex; use tokio::time::{Duration, Instant}; @@ -32,7 +33,7 @@ impl CountdownService { let countdown = self.countdown.lock().await.clone(); CountdownSnapshot { id: countdown.id(), - label: countdown.label().parse().unwrap(), + label: countdown.label().to_string(), state: countdown.state(), duration: countdown.remaining_at(now), start_instant: countdown.start_timestamp(), diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 744bade..dbc91d0 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -3,6 +3,9 @@ extern crate core; mod app_state; mod countdown; +use crate::countdown::commands::{ + countdown_pause, countdown_reset, countdown_resume, countdown_snapshot, countdown_start, +}; pub use app_state::AppState; // Learn more about Tauri commands at https://tauri.app/develop/calling-rust/ @@ -17,7 +20,14 @@ pub fn run() { tauri::Builder::default() .manage(app_state) .plugin(tauri_plugin_opener::init()) - .invoke_handler(tauri::generate_handler![greet]) + .invoke_handler(tauri::generate_handler![ + greet, + countdown_start, + countdown_reset, + countdown_pause, + countdown_resume, + countdown_snapshot, + ]) .run(tauri::generate_context!()) .expect("error while running tauri application"); }