use serde::{Deserialize, Serialize}; use anyhow::Result; use std::fs; use std::path::PathBuf; #[derive(Debug, Deserialize, Serialize, Clone)] pub struct Config { pub server_url: String, pub timeout_sec: u64, #[serde(default = "default_theme")] pub theme: Theme, #[serde(default)] pub update_api: Option, } #[derive(Debug, Deserialize, Serialize, Clone)] pub struct Theme { #[serde(default = "default_selected_bg")] pub selected_bg: String, } fn default_selected_bg() -> String { "blue".to_string() } fn default_theme() -> Theme { Theme { selected_bg: default_selected_bg(), } } impl Config { pub fn load() -> Result { // Respect XDG_CONFIG_HOME; fall back to ~/.config on all platforms. let config_base = std::env::var("XDG_CONFIG_HOME") .map(PathBuf::from) .unwrap_or_else(|_| { dirs::home_dir() .unwrap_or_else(|| PathBuf::from(".")) .join(".config") }); let config_path = config_base .join(env!("CARGO_PKG_NAME")) .join("config.toml"); if !config_path.exists() { let default = Config { server_url: "http://localhost:8080/api/menu".to_string(), timeout_sec: 10, theme: default_theme(), update_api: None, }; fs::create_dir_all(config_path.parent().unwrap())?; fs::write(config_path, toml::to_string_pretty(&default)?)?; return Ok(default); } let content = fs::read_to_string(config_path)?; Ok(toml::from_str(&content)?) } }