feat(timer): wire VisualTimer to tasks with notifications and persistence
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -26,6 +26,7 @@ tauri = { version = "2", features = ["tray-icon"] }
|
||||
tauri-plugin-opener = "2"
|
||||
tauri-plugin-dialog = "2"
|
||||
tauri-plugin-global-shortcut = "2"
|
||||
tauri-plugin-notification = "2"
|
||||
|
||||
# Serialisation
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
"opener:default",
|
||||
"dialog:default",
|
||||
"global-shortcut:allow-register",
|
||||
"global-shortcut:allow-unregister"
|
||||
"global-shortcut:allow-unregister",
|
||||
"notification:default"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -4,5 +4,6 @@ pub mod hardware;
|
||||
pub mod history;
|
||||
pub mod models;
|
||||
pub mod tasks;
|
||||
pub mod timer;
|
||||
pub mod transcription;
|
||||
pub mod windows;
|
||||
|
||||
56
src-tauri/src/commands/timer.rs
Normal file
56
src-tauri/src/commands/timer.rs
Normal file
@@ -0,0 +1,56 @@
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::AppState;
|
||||
use kon_storage::{clear_timer_state, get_timer_state, save_timer_state};
|
||||
|
||||
/// Serialisable timer state response.
|
||||
#[derive(Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct TimerStateResponse {
|
||||
pub task_id: String,
|
||||
pub total_seconds: i64,
|
||||
pub remaining_seconds: i64,
|
||||
pub started_at: String,
|
||||
pub paused: bool,
|
||||
}
|
||||
|
||||
/// Save or update the active timer state.
|
||||
#[tauri::command]
|
||||
pub async fn save_timer(
|
||||
state: tauri::State<'_, AppState>,
|
||||
task_id: String,
|
||||
total_seconds: i64,
|
||||
remaining_seconds: i64,
|
||||
paused: bool,
|
||||
) -> Result<(), String> {
|
||||
save_timer_state(&state.db, &task_id, total_seconds, remaining_seconds, paused)
|
||||
.await
|
||||
.map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
/// Retrieve the active timer state (for context restoration on app restart).
|
||||
#[tauri::command]
|
||||
pub async fn get_timer(
|
||||
state: tauri::State<'_, AppState>,
|
||||
) -> Result<Option<TimerStateResponse>, String> {
|
||||
let row = get_timer_state(&state.db)
|
||||
.await
|
||||
.map_err(|e| e.to_string())?;
|
||||
Ok(row.map(|r| TimerStateResponse {
|
||||
task_id: r.task_id,
|
||||
total_seconds: r.total_seconds,
|
||||
remaining_seconds: r.remaining_seconds,
|
||||
started_at: r.started_at,
|
||||
paused: r.paused,
|
||||
}))
|
||||
}
|
||||
|
||||
/// Clear the active timer (completed or cancelled).
|
||||
#[tauri::command]
|
||||
pub async fn clear_timer(
|
||||
state: tauri::State<'_, AppState>,
|
||||
) -> Result<(), String> {
|
||||
clear_timer_state(&state.db)
|
||||
.await
|
||||
.map_err(|e| e.to_string())
|
||||
}
|
||||
@@ -72,6 +72,7 @@ pub fn run() {
|
||||
.plugin(tauri_plugin_opener::init())
|
||||
.plugin(tauri_plugin_dialog::init())
|
||||
.plugin(tauri_plugin_global_shortcut::Builder::new().build())
|
||||
.plugin(tauri_plugin_notification::init())
|
||||
.setup(|app| {
|
||||
// Initialise database (blocking in setup — runs once at startup)
|
||||
let db_path = database_path();
|
||||
@@ -154,6 +155,10 @@ pub fn run() {
|
||||
commands::tasks::reorder_tasks_cmd,
|
||||
commands::tasks::complete_task_cmd,
|
||||
commands::tasks::uncomplete_task_cmd,
|
||||
// Timer
|
||||
commands::timer::save_timer,
|
||||
commands::timer::get_timer,
|
||||
commands::timer::clear_timer,
|
||||
// Transcription
|
||||
commands::transcription::transcribe_pcm,
|
||||
commands::transcription::transcribe_file,
|
||||
|
||||
Reference in New Issue
Block a user