1use serde::{Deserialize, Serialize};
8
9use blockworx_paint::{FontChoice, Mode, Palette, Scheme};
10
11#[derive(Clone, PartialEq, Eq, Debug, Default, Serialize, Deserialize)]
17#[serde(default)]
18pub struct Preferences {
19 #[serde(alias = "scheme")]
20 pub theme: Scheme,
21 pub mode: Mode,
22 pub font: FontChoice,
23 pub author_name: Option<String>,
28}
29
30impl Preferences {
31 pub fn palette(&self, system_dark: Option<bool>) -> Palette {
34 self.theme.palette(self.mode.is_dark(system_dark).into())
35 }
36
37 pub fn identity(&self) -> blockworx_store::record::Identity {
40 match self.author_name.as_deref().map(str::trim) {
41 Some(name) if !name.is_empty() => blockworx_store::record::Identity::new(name),
42 _ => blockworx_store::record::Identity::from_environment(),
43 }
44 }
45}
46
47#[cfg(test)]
48mod tests {
49 use super::*;
50
51 #[test]
52 fn palette_picks_variant_from_mode_and_os() {
53 let prefs = Preferences {
54 theme: Scheme::Ayu,
55 mode: Mode::System,
56 ..Default::default()
57 };
58 assert!(!prefs.palette(Some(false)).is_dark());
59 assert!(prefs.palette(Some(true)).is_dark());
60 }
61
62 #[test]
63 fn preferences_round_trip_through_json() {
64 let prefs = Preferences {
65 theme: Scheme::RosePine,
66 mode: Mode::Light,
67 font: FontChoice::Monospace,
68 author_name: Some("Ada Lovelace".to_owned()),
69 };
70 let json = serde_json::to_string(&prefs).unwrap();
71 assert_eq!(serde_json::from_str::<Preferences>(&json).unwrap(), prefs);
72 }
73
74 #[test]
78 fn the_stored_profile_name_overrides_the_environment() {
79 let named = Preferences {
80 author_name: Some("Ada Lovelace".to_owned()),
81 ..Default::default()
82 };
83 assert_eq!(named.identity().name, "Ada Lovelace");
84
85 let blank = Preferences {
86 author_name: Some(" ".to_owned()),
87 ..Default::default()
88 };
89 assert_eq!(
90 blank.identity(),
91 Preferences::default().identity(),
92 "a blank profile name falls back to the environment",
93 );
94 }
95
96 #[test]
97 fn partial_stored_blob_fills_missing_fields_from_default() {
98 let prefs: Preferences = serde_json::from_str(r#"{"scheme":"TokyoNight"}"#).unwrap();
101 assert_eq!(prefs.theme, Scheme::TokyoNight);
102 assert_eq!(prefs.mode, Mode::default());
103 assert_eq!(prefs.font, FontChoice::default());
104 }
105
106 #[test]
109 fn a_stored_widget_size_is_dropped_and_the_rest_of_the_blob_still_loads() {
110 let prefs: Preferences =
111 serde_json::from_str(r#"{"scheme":"Ayu","widget_size":"Large","font":"Formal"}"#)
112 .expect("a blob carrying the retired zoom must still load");
113 assert_eq!(prefs.theme, Scheme::Ayu);
114 assert_eq!(prefs.font, FontChoice::Formal);
115 assert!(
116 !serde_json::to_string(&prefs)
117 .unwrap()
118 .contains("widget_size"),
119 "the retired zoom was written back out",
120 );
121 }
122}