// Tauri commands for onboarding flow + opt-in activation log. // // These are thin adapters over the storage helpers — no business logic lives // here. Every sqlx::Error is mapped to a String so Tauri can serialise it // to the frontend as a rejected Promise. use std::time::{SystemTime, UNIX_EPOCH}; use lumotia_storage::{ clear_lumotia_events as db_clear_lumotia_events, has_completed_onboarding as db_has_completed_onboarding, insert_lumotia_event as db_insert_lumotia_event, insert_onboarding_event as db_insert_onboarding_event, list_lumotia_events as db_list_lumotia_events, list_onboarding_events as db_list_onboarding_events, LumotiaEventRow, OnboardingEventRow, }; use crate::AppState; /// Record a single onboarding step. /// /// `event` — short snake_case identifier, e.g. `"started"`, `"completed"`, `"skipped"`. /// `version` — app version string, e.g. `"0.1.0"`. /// `skipped` — `true` if the user bypassed this step. /// `notes` — optional freeform annotation. #[tauri::command] pub async fn record_onboarding_event( state: tauri::State<'_, AppState>, event: String, version: String, skipped: bool, notes: Option, ) -> Result<(), String> { let now = SystemTime::now() .duration_since(UNIX_EPOCH) .map(|d| d.as_secs() as i64) .unwrap_or(0); db_insert_onboarding_event(&state.db, &event, &version, skipped, notes.as_deref(), now) .await .map_err(|e| e.to_string()) } /// List all recorded onboarding events, oldest first. #[tauri::command] pub async fn list_onboarding_events( state: tauri::State<'_, AppState>, ) -> Result, String> { db_list_onboarding_events(&state.db) .await .map_err(|e| e.to_string()) } /// Returns `true` if the user has ever recorded a `completed` or `skipped` /// onboarding event — i.e. first-run onboarding should not be shown again. #[tauri::command] pub async fn has_completed_onboarding(state: tauri::State<'_, AppState>) -> Result { db_has_completed_onboarding(&state.db) .await .map_err(|e| e.to_string()) } /// Append a single entry to the opt-in local activation log. /// /// `kind` — event kind, e.g. `"app_launched"`, `"recording_started"`. /// `payload` — optional JSON blob with event-specific context. #[tauri::command] pub async fn record_lumotia_event( state: tauri::State<'_, AppState>, kind: String, payload: Option, ) -> Result<(), String> { let now = SystemTime::now() .duration_since(UNIX_EPOCH) .map(|d| d.as_secs() as i64) .unwrap_or(0); db_insert_lumotia_event(&state.db, &kind, payload.as_deref(), now) .await .map_err(|e| e.to_string()) } /// List all activation log events, oldest first. #[tauri::command] pub async fn list_lumotia_events( state: tauri::State<'_, AppState>, ) -> Result, String> { db_list_lumotia_events(&state.db) .await .map_err(|e| e.to_string()) } /// Delete all rows from the activation log. #[tauri::command] pub async fn clear_lumotia_events(state: tauri::State<'_, AppState>) -> Result<(), String> { db_clear_lumotia_events(&state.db) .await .map_err(|e| e.to_string()) }