[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
This commit is contained in:
@@ -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<T> = Result<T, String>;
|
||||
|
||||
#[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<CountdownSnapshotDto, String> {
|
||||
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,
|
||||
})
|
||||
}
|
||||
|
||||
10
src-tauri/src/countdown/errors.rs
Normal file
10
src-tauri/src/countdown/errors.rs
Normal file
@@ -0,0 +1,10 @@
|
||||
use crate::countdown::model::CountdownState;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum CountdownError {
|
||||
InvalidTransition {
|
||||
from: CountdownState,
|
||||
action: &'static str,
|
||||
},
|
||||
TimeOverflow,
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
pub mod commands;
|
||||
pub mod dto;
|
||||
pub mod errors;
|
||||
pub mod model;
|
||||
pub mod service;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user