gardesk/garnotify / 6b55ac2

Browse files

feat(config): use gartk Color type for theme consistency

Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
6b55ac2ae639e1c03e2532bbb763adef9eb3023f
Parents
b7e80b7
Tree
11a5d32

3 changed files

StatusFile+-
M garnotify/src/config/lua.rs 25 19
M garnotify/src/config/mod.rs 42 21
M garnotify/src/ui/popup.rs 4 25
garnotify/src/config/lua.rsmodified
@@ -3,14 +3,17 @@
33
 //! Reads `gar.notification` table from `~/.config/gar/init.lua`
44
 
55
 use anyhow::{anyhow, Result};
6
+use gartk_core::Color;
67
 use mlua::{Lua, Table, Value};
78
 use std::path::Path;
89
 use tracing::{debug, info, warn};
910
 
10
-use super::{
11
-    AnimationConfig, AppearanceConfig, ColorConfig, Config, GeneralConfig,
12
-    GeometryConfig, HistoryConfig, TimeoutConfig,
13
-};
11
+use super::{ColorConfig, Config};
12
+
13
+/// Parse a color string from Lua, returning default on failure
14
+fn parse_color(s: &str, default: Color) -> Color {
15
+    Color::parse(s).unwrap_or(default)
16
+}
1417
 
1518
 /// Convert mlua Error to anyhow Error
1619
 fn lua_err(e: mlua::Error) -> anyhow::Error {
@@ -224,16 +227,19 @@ fn parse_notification_config(table: &Table) -> Result<Config> {
224227
 
225228
     // Colors - can be flat or nested
226229
     if let Ok(background) = table.get::<String>("background") {
227
-        config.appearance.colors.background = background.clone();
228
-        config.appearance.colors.low_background = background.clone();
230
+        let color = parse_color(&background, config.appearance.colors.background);
231
+        config.appearance.colors.background = color;
232
+        config.appearance.colors.low_background = color;
229233
     }
230234
     if let Ok(foreground) = table.get::<String>("foreground") {
231
-        config.appearance.colors.foreground = foreground.clone();
232
-        config.appearance.colors.low_foreground = foreground.clone();
235
+        let color = parse_color(&foreground, config.appearance.colors.foreground);
236
+        config.appearance.colors.foreground = color;
237
+        config.appearance.colors.low_foreground = color;
233238
     }
234239
     if let Ok(border) = table.get::<String>("border") {
235
-        config.appearance.colors.border = border.clone();
236
-        config.appearance.colors.low_border = border.clone();
240
+        let color = parse_color(&border, config.appearance.colors.border);
241
+        config.appearance.colors.border = color;
242
+        config.appearance.colors.low_border = color;
237243
     }
238244
 
239245
     // Nested colors table
@@ -280,35 +286,35 @@ fn parse_notification_config(table: &Table) -> Result<Config> {
280286
 /// Parse colors table
281287
 fn parse_colors(table: &Table, colors: &mut ColorConfig) {
282288
     if let Ok(bg) = table.get::<String>("background") {
283
-        colors.background = bg;
289
+        colors.background = parse_color(&bg, colors.background);
284290
     }
285291
     if let Ok(fg) = table.get::<String>("foreground") {
286
-        colors.foreground = fg;
292
+        colors.foreground = parse_color(&fg, colors.foreground);
287293
     }
288294
     if let Ok(border) = table.get::<String>("border") {
289
-        colors.border = border;
295
+        colors.border = parse_color(&border, colors.border);
290296
     }
291297
 
292298
     // Low urgency
293299
     if let Ok(low_bg) = table.get::<String>("low_background") {
294
-        colors.low_background = low_bg;
300
+        colors.low_background = parse_color(&low_bg, colors.low_background);
295301
     }
296302
     if let Ok(low_fg) = table.get::<String>("low_foreground") {
297
-        colors.low_foreground = low_fg;
303
+        colors.low_foreground = parse_color(&low_fg, colors.low_foreground);
298304
     }
299305
     if let Ok(low_border) = table.get::<String>("low_border") {
300
-        colors.low_border = low_border;
306
+        colors.low_border = parse_color(&low_border, colors.low_border);
301307
     }
302308
 
303309
     // Critical urgency
304310
     if let Ok(crit_bg) = table.get::<String>("critical_background") {
305
-        colors.critical_background = crit_bg;
311
+        colors.critical_background = parse_color(&crit_bg, colors.critical_background);
306312
     }
307313
     if let Ok(crit_fg) = table.get::<String>("critical_foreground") {
308
-        colors.critical_foreground = crit_fg;
314
+        colors.critical_foreground = parse_color(&crit_fg, colors.critical_foreground);
309315
     }
310316
     if let Ok(crit_border) = table.get::<String>("critical_border") {
311
-        colors.critical_border = crit_border;
317
+        colors.critical_border = parse_color(&crit_border, colors.critical_border);
312318
     }
313319
 }
314320
 
garnotify/src/config/mod.rsmodified
@@ -3,12 +3,24 @@
33
 pub mod lua;
44
 
55
 use anyhow::{Context, Result};
6
-use serde::{Deserialize, Serialize};
6
+use gartk_core::Color;
7
+use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
78
 use std::path::PathBuf;
89
 use tracing::{debug, info, warn};
910
 
1011
 use crate::rules::Rule;
1112
 
13
+/// Serialize Color as hex string
14
+fn serialize_color<S: Serializer>(color: &Color, s: S) -> Result<S::Ok, S::Error> {
15
+    s.serialize_str(&color.to_hex())
16
+}
17
+
18
+/// Deserialize Color from any color string (hex, rgb, rgba, named)
19
+fn deserialize_color<'de, D: Deserializer<'de>>(d: D) -> Result<Color, D::Error> {
20
+    let s: String = Deserialize::deserialize(d)?;
21
+    Color::parse(&s).map_err(de::Error::custom)
22
+}
23
+
1224
 /// Get the default configuration file path
1325
 fn config_path() -> PathBuf {
1426
     dirs::config_dir()
@@ -161,47 +173,56 @@ impl Default for AppearanceConfig {
161173
     }
162174
 }
163175
 
164
-/// Color configuration
176
+/// Color configuration using gartk Color type
165177
 #[derive(Debug, Clone, Serialize, Deserialize)]
166178
 #[serde(default)]
167179
 pub struct ColorConfig {
168180
     /// Default background color
169
-    pub background: String,
181
+    #[serde(serialize_with = "serialize_color", deserialize_with = "deserialize_color")]
182
+    pub background: Color,
170183
     /// Default foreground (text) color
171
-    pub foreground: String,
184
+    #[serde(serialize_with = "serialize_color", deserialize_with = "deserialize_color")]
185
+    pub foreground: Color,
172186
     /// Default border color
173
-    pub border: String,
187
+    #[serde(serialize_with = "serialize_color", deserialize_with = "deserialize_color")]
188
+    pub border: Color,
174189
 
175190
     /// Low urgency background
176
-    pub low_background: String,
191
+    #[serde(serialize_with = "serialize_color", deserialize_with = "deserialize_color")]
192
+    pub low_background: Color,
177193
     /// Low urgency foreground
178
-    pub low_foreground: String,
194
+    #[serde(serialize_with = "serialize_color", deserialize_with = "deserialize_color")]
195
+    pub low_foreground: Color,
179196
     /// Low urgency border
180
-    pub low_border: String,
197
+    #[serde(serialize_with = "serialize_color", deserialize_with = "deserialize_color")]
198
+    pub low_border: Color,
181199
 
182200
     /// Critical urgency background
183
-    pub critical_background: String,
201
+    #[serde(serialize_with = "serialize_color", deserialize_with = "deserialize_color")]
202
+    pub critical_background: Color,
184203
     /// Critical urgency foreground
185
-    pub critical_foreground: String,
204
+    #[serde(serialize_with = "serialize_color", deserialize_with = "deserialize_color")]
205
+    pub critical_foreground: Color,
186206
     /// Critical urgency border
187
-    pub critical_border: String,
207
+    #[serde(serialize_with = "serialize_color", deserialize_with = "deserialize_color")]
208
+    pub critical_border: Color,
188209
 }
189210
 
190211
 impl Default for ColorConfig {
191212
     fn default() -> Self {
192
-        // Catppuccin-inspired colors
213
+        // Catppuccin-inspired colors (matching gartk Theme::dark())
193214
         Self {
194
-            background: "#1e1e2e".into(),
195
-            foreground: "#cdd6f4".into(),
196
-            border: "#45475a".into(),
215
+            background: Color::from_hex("#1e1e2e").unwrap(),
216
+            foreground: Color::from_hex("#cdd6f4").unwrap(),
217
+            border: Color::from_hex("#45475a").unwrap(),
197218
 
198
-            low_background: "#1e1e2e".into(),
199
-            low_foreground: "#6c7086".into(),
200
-            low_border: "#45475a".into(),
219
+            low_background: Color::from_hex("#1e1e2e").unwrap(),
220
+            low_foreground: Color::from_hex("#6c7086").unwrap(),
221
+            low_border: Color::from_hex("#45475a").unwrap(),
201222
 
202
-            critical_background: "#f38ba8".into(),
203
-            critical_foreground: "#1e1e2e".into(),
204
-            critical_border: "#f38ba8".into(),
223
+            critical_background: Color::from_hex("#f38ba8").unwrap(),
224
+            critical_foreground: Color::from_hex("#1e1e2e").unwrap(),
225
+            critical_border: Color::from_hex("#f38ba8").unwrap(),
205226
         }
206227
     }
207228
 }
garnotify/src/ui/popup.rsmodified
@@ -296,31 +296,10 @@ impl NotificationPopup {
296296
         let urgency = &self.notification.hints.urgency;
297297
         let colors = &self.appearance.colors;
298298
 
299
-        let bg = match urgency {
300
-            Urgency::Low => Color::from_hex(&colors.low_background)
301
-                .unwrap_or(Color::new(0.1, 0.1, 0.1, 0.9)),
302
-            Urgency::Normal => Color::from_hex(&colors.background)
303
-                .unwrap_or(Color::new(0.12, 0.12, 0.14, 0.95)),
304
-            Urgency::Critical => Color::from_hex(&colors.critical_background)
305
-                .unwrap_or(Color::new(0.3, 0.1, 0.1, 0.95)),
306
-        };
307
-
308
-        let fg = match urgency {
309
-            Urgency::Low => Color::from_hex(&colors.low_foreground)
310
-                .unwrap_or(Color::new(0.7, 0.7, 0.7, 1.0)),
311
-            Urgency::Normal => Color::from_hex(&colors.foreground)
312
-                .unwrap_or(Color::new(0.9, 0.9, 0.9, 1.0)),
313
-            Urgency::Critical => Color::from_hex(&colors.critical_foreground)
314
-                .unwrap_or(Color::new(1.0, 0.9, 0.9, 1.0)),
315
-        };
316
-
317
-        let border = match urgency {
318
-            Urgency::Low => Color::from_hex(&colors.low_border)
319
-                .unwrap_or(Color::new(0.3, 0.3, 0.3, 0.5)),
320
-            Urgency::Normal => Color::from_hex(&colors.border)
321
-                .unwrap_or(Color::new(0.4, 0.4, 0.4, 0.5)),
322
-            Urgency::Critical => Color::from_hex(&colors.critical_border)
323
-                .unwrap_or(Color::new(0.8, 0.2, 0.2, 0.8)),
299
+        let (bg, fg, border) = match urgency {
300
+            Urgency::Low => (colors.low_background, colors.low_foreground, colors.low_border),
301
+            Urgency::Normal => (colors.background, colors.foreground, colors.border),
302
+            Urgency::Critical => (colors.critical_background, colors.critical_foreground, colors.critical_border),
324303
         };
325304
 
326305
         (bg, fg, border)