use std::path::PathBuf; use std::sync::Mutex; use serde::{Deserialize, Serialize}; use crate::audio::{RecordingSession, RecordingStatus}; use crate::models::{model_statuses, ModelWithStatus}; use crate::settings::AppSettings; pub struct ManagedAppState { pub settings: Mutex, pub recording: Mutex, pub transcript: Mutex, pub model_dir: PathBuf, pub recordings_dir: PathBuf, } #[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq, Eq)] #[serde(rename_all = "camelCase")] pub struct TranscriptDraft { pub text: String, pub last_message: Option, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] #[serde(rename_all = "camelCase")] pub struct AppSnapshot { pub settings: AppSettings, pub recording_status: RecordingStatus, pub transcript: TranscriptDraft, pub models: Vec, } impl Default for ManagedAppState { fn default() -> Self { Self { settings: Mutex::new(AppSettings::default()), recording: Mutex::new(RecordingSession::default()), transcript: Mutex::new(TranscriptDraft::default()), model_dir: default_model_dir(), recordings_dir: default_recordings_dir(), } } } impl ManagedAppState { pub fn snapshot(&self) -> Result { let settings = self .settings .lock() .map_err(|_| "falha ao acessar configurações".to_string())? .clone(); let recording_status = self .recording .lock() .map_err(|_| "falha ao acessar estado de gravação".to_string())? .status .clone(); let transcript = self .transcript .lock() .map_err(|_| "falha ao acessar transcrição".to_string())? .clone(); Ok(AppSnapshot { settings, recording_status, transcript, models: model_statuses(&self.model_dir), }) } } fn default_model_dir() -> PathBuf { std::env::current_dir() .unwrap_or_else(|_| std::env::temp_dir()) .join("models") } fn default_recordings_dir() -> PathBuf { std::env::current_dir() .unwrap_or_else(|_| std::env::temp_dir()) .join("recordings") } #[cfg(test)] mod tests { use super::*; #[test] fn default_snapshot_starts_idle() { let state = ManagedAppState::default(); let snapshot = match state.snapshot() { Ok(snapshot) => snapshot, Err(error) => panic!("snapshot should work: {error}"), }; assert_eq!(snapshot.recording_status, RecordingStatus::Idle); assert!(snapshot.transcript.text.is_empty()); assert_eq!(snapshot.models.len(), 1); } }