aaai_core/profile/
prefs.rs1use serde::{Deserialize, Serialize};
8use std::path::PathBuf;
9
10#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
12#[serde(rename_all = "lowercase")]
13pub enum Theme {
14 #[default]
16 Light,
17 Dark,
19 System,
21}
22
23impl std::fmt::Display for Theme {
24 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
25 match self {
26 Theme::Light => write!(f, "Light"),
27 Theme::Dark => write!(f, "Dark"),
28 Theme::System => write!(f, "System"),
29 }
30 }
31}
32
33#[derive(Debug, Clone, Default, Serialize, Deserialize)]
35pub struct UserPrefs {
36 #[serde(default)]
38 pub theme: Theme,
39}
40
41impl UserPrefs {
42 fn path() -> anyhow::Result<PathBuf> {
43 let base = dirs::home_dir()
44 .ok_or_else(|| anyhow::anyhow!("Cannot determine home directory"))?
45 .join(".aaai");
46 std::fs::create_dir_all(&base)?;
47 Ok(base.join("prefs.yaml"))
48 }
49
50 pub fn load() -> Self {
52 match Self::path().and_then(|p| {
53 if !p.exists() { return Ok(Self::default()); }
54 let text = std::fs::read_to_string(&p)?;
55 serde_yaml::from_str(&text).map_err(|e| anyhow::anyhow!(e))
56 }) {
57 Ok(prefs) => prefs,
58 Err(e) => {
59 log::warn!("Could not load prefs: {e}");
60 Self::default()
61 }
62 }
63 }
64
65 pub fn save(&self) {
67 if let Err(e) = Self::path().and_then(|p| {
68 let yaml = serde_yaml::to_string(self).map_err(|e| anyhow::anyhow!(e))?;
69 std::fs::write(&p, yaml)?;
70 Ok(())
71 }) {
72 log::warn!("Could not save prefs: {e}");
73 }
74 }
75}
76
77#[cfg(test)]
78mod tests {
79 use super::*;
80
81 #[test]
82 fn round_trip_yaml() {
83 let prefs = UserPrefs { theme: Theme::Dark };
84 let yaml = serde_yaml::to_string(&prefs).unwrap();
85 let restored: UserPrefs = serde_yaml::from_str(&yaml).unwrap();
86 assert_eq!(restored.theme, Theme::Dark);
87 }
88
89 #[test]
90 fn default_is_light() {
91 assert_eq!(UserPrefs::default().theme, Theme::Light);
92 }
93
94 #[test]
95 fn display_names() {
96 assert_eq!(Theme::Light.to_string(), "Light");
97 assert_eq!(Theme::Dark.to_string(), "Dark");
98 }
99}