// filepath: src-tauri/src/storage.rs use serde::{Deserialize, Serialize}; use std::fs; use std::path::PathBuf; use tauri::{AppHandle, Manager}; use anyhow::Result; use chrono::{DateTime, Utc}; #[derive(Serialize, Deserialize, Debug, Clone)] pub struct Settings { pub download_path: String, pub cookies_path: Option, pub theme: String, // 'light', 'dark', 'system' pub last_updated: Option>, } impl Default for Settings { fn default() -> Self { // We'll resolve the actual download path at runtime if empty, // but for default struct we can keep it empty or a placeholder. Self { download_path: "".to_string(), cookies_path: None, theme: "system".to_string(), last_updated: None, } } } #[derive(Serialize, Deserialize, Debug, Clone)] pub struct HistoryItem { pub id: String, pub title: String, pub thumbnail: String, pub url: String, pub output_path: String, pub timestamp: DateTime, pub status: String, // "success", "failed" pub format: String, } pub fn get_app_data_dir(app: &AppHandle) -> Result { // In Tauri v2, we use app.path().app_data_dir() let path = app.path().app_data_dir()?; if !path.exists() { fs::create_dir_all(&path)?; } Ok(path) } pub fn get_settings_path(app: &AppHandle) -> Result { Ok(get_app_data_dir(app)?.join("settings.json")) } pub fn get_history_path(app: &AppHandle) -> Result { Ok(get_app_data_dir(app)?.join("history.json")) } pub fn load_settings(app: &AppHandle) -> Result { let path = get_settings_path(app)?; if path.exists() { let content = fs::read_to_string(&path)?; let settings: Settings = serde_json::from_str(&content)?; return Ok(settings); } // If not exists, return default. // Note: We might want to set a default download path here if possible. let mut settings = Settings::default(); if let Ok(download_dir) = app.path().download_dir() { settings.download_path = download_dir.to_string_lossy().to_string(); } Ok(settings) } pub fn save_settings(app: &AppHandle, settings: &Settings) -> Result<()> { let path = get_settings_path(app)?; let content = serde_json::to_string_pretty(settings)?; fs::write(path, content)?; Ok(()) } pub fn load_history(app: &AppHandle) -> Result> { let path = get_history_path(app)?; if path.exists() { let content = fs::read_to_string(&path)?; let history: Vec = serde_json::from_str(&content)?; Ok(history) } else { Ok(Vec::new()) } } pub fn save_history(app: &AppHandle, history: &[HistoryItem]) -> Result<()> { let path = get_history_path(app)?; let content = serde_json::to_string_pretty(history)?; fs::write(path, content)?; Ok(()) } pub fn add_history_item(app: &AppHandle, item: HistoryItem) -> Result<()> { let mut history = load_history(app)?; // Prepend history.insert(0, item); save_history(app, &history)?; Ok(()) } pub fn clear_history(app: &AppHandle) -> Result<()> { save_history(app, &[]) } pub fn delete_history_item(app: &AppHandle, id: &str) -> Result<()> { let mut history = load_history(app)?; history.retain(|item| item.id != id); save_history(app, &history)?; Ok(()) }