use std::fs; use std::path::PathBuf; use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Settings { pub work_duration_secs: u64, pub short_break_secs: u64, pub long_break_secs: u64, pub sessions_before_long_break: u32, } impl Default for Settings { fn default() -> Self { Self { work_duration_secs: 25 * 60, short_break_secs: 5 * 60, long_break_secs: 15 * 60, sessions_before_long_break: 4, } } } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Task { pub id: String, pub name: String, pub total_sessions: u32, pub remaining_sessions: u32, pub completed: bool, pub created_at: String, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct AppData { pub settings: Settings, pub tasks: Vec, pub current_task_id: Option, } impl Default for AppData { fn default() -> Self { Self { settings: Settings::default(), tasks: Vec::new(), current_task_id: None, } } } pub fn data_path(app_data_dir: &PathBuf) -> PathBuf { app_data_dir.join("data.json") } pub fn load(app_data_dir: &PathBuf) -> AppData { let path = data_path(app_data_dir); if !path.exists() { return AppData::default(); } let mut data = match fs::read_to_string(&path) { Ok(contents) => serde_json::from_str(&contents).unwrap_or_default(), Err(_) => AppData::default(), }; // Guard against a corrupt/zero value that would cause division by zero if data.settings.sessions_before_long_break == 0 { data.settings.sessions_before_long_break = Settings::default().sessions_before_long_break; } data } pub fn save(app_data_dir: &PathBuf, data: &AppData) -> Result<(), String> { fs::create_dir_all(app_data_dir) .map_err(|e| format!("Failed to create data directory: {}", e))?; let path = data_path(app_data_dir); let contents = serde_json::to_string_pretty(data) .map_err(|e| format!("Failed to serialize data: {}", e))?; let tmp_path = app_data_dir.join("data.json.tmp"); fs::write(&tmp_path, contents) .map_err(|e| format!("Failed to write temp data file: {}", e))?; fs::rename(&tmp_path, &path) .map_err(|e| format!("Failed to finalize data file: {}", e))?; Ok(()) }