git.lucas.co / cce-system-interface
system settings
git clone https://git.lucas.co/cce-system-interface.git

commitc3549339c91dc1b11ccbe2380000a76cd8519edd
parentf3c5c6464d
authorLucas Galante <[email protected]>
date2026-06-26 14:50
system-interface: resolve status interface compilation and routing errors

 src/input_handler.rs   |  54 ++++----
 src/pages/interface.rs | 355 ++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 379 insertions(+), 30 deletions(-)

diff --git a/src/input_handler.rs b/src/input_handler.rs
index 2a3b2ad..2fe5f6d 100644
--- a/src/input_handler.rs
+++ b/src/input_handler.rs
@@ -87,20 +87,20 @@ impl SystemInterface {
                 }
             }
         }
-        if self.app.current_page == Page::System {
+        if self.app.current_page == Page::Interface {
             if self.status_box_opacity_dragging {
                 drag_handled = true;
-                if self.app.system_info.status_box_opacity_slider.drag_update(lx, ly) {
+                if self.app.interface.status_box_opacity_slider.drag_update(lx, ly) {
                     changed = true;
-                    let val = self.app.system_info.status_box_opacity_slider.value();
-                    self.handle_action(&AppAction::SystemInfo(pages::system_info::SystemMessage::StatusSetBoxOpacity(val)));
+                    let val = self.app.interface.status_box_opacity_slider.value();
+                    self.handle_action(&AppAction::Interface(pages::interface::InterfaceMessage::StatusSetBoxOpacity(val)));
                 }
             } else if self.status_box_blur_dragging {
                 drag_handled = true;
-                if self.app.system_info.status_box_blur_slider.drag_update(lx, ly) {
+                if self.app.interface.status_box_blur_slider.drag_update(lx, ly) {
                     changed = true;
-                    let val = self.app.system_info.status_box_blur_slider.value();
-                    self.handle_action(&AppAction::SystemInfo(pages::system_info::SystemMessage::StatusSetBoxBlur(val)));
+                    let val = self.app.interface.status_box_blur_slider.value();
+                    self.handle_action(&AppAction::Interface(pages::interface::InterfaceMessage::StatusSetBoxBlur(val)));
                 }
             }
         }
@@ -235,14 +235,14 @@ impl SystemInterface {
                     self.needs_rebuild = true;
                 }
             }
-            if self.app.current_page == Page::System {
+            if self.app.current_page == Page::Interface {
                 if self.status_box_opacity_dragging {
-                    self.app.system_info.status_box_opacity_slider.drag_end();
+                    self.app.interface.status_box_opacity_slider.drag_end();
                     self.status_box_opacity_dragging = false;
                     self.needs_rebuild = true;
                 }
                 if self.status_box_blur_dragging {
-                    self.app.system_info.status_box_blur_slider.drag_end();
+                    self.app.interface.status_box_blur_slider.drag_end();
                     self.status_box_blur_dragging = false;
                     self.needs_rebuild = true;
                 }
@@ -276,11 +276,11 @@ impl SystemInterface {
                     }
                 }
             }
-            if self.app.current_page == Page::System {
-                if self.app.system_info.status_box_opacity_slider.is_dragging() {
+            if self.app.current_page == Page::Interface {
+                if self.app.interface.status_box_opacity_slider.is_dragging() {
                     self.status_box_opacity_dragging = true;
                 }
-                if self.app.system_info.status_box_blur_slider.is_dragging() {
+                if self.app.interface.status_box_blur_slider.is_dragging() {
                     self.status_box_blur_dragging = true;
                 }
             }
@@ -356,6 +356,18 @@ impl SystemInterface {
                 if self.app.interface.status_module_spacing_spinbox.take_change() {
                     actions.push(AppAction::Interface(pages::interface::InterfaceMessage::SetStatusModuleSpacing(self.app.interface.status_module_spacing_spinbox.value as u16)));
                 }
+                if self.app.interface.status_separators_toggle.take_change() {
+                    actions.push(AppAction::Interface(pages::interface::InterfaceMessage::StatusToggleSeparators));
+                }
+                if self.app.interface.status_underline_toggle.take_change() {
+                    actions.push(AppAction::Interface(pages::interface::InterfaceMessage::StatusToggleUnderline));
+                }
+                if self.app.interface.status_box_opacity_slider.take_change() {
+                    actions.push(AppAction::Interface(pages::interface::InterfaceMessage::StatusSetBoxOpacity(self.app.interface.status_box_opacity_slider.value())));
+                }
+                if self.app.interface.status_box_blur_slider.take_change() {
+                    actions.push(AppAction::Interface(pages::interface::InterfaceMessage::StatusSetBoxBlur(self.app.interface.status_box_blur_slider.value())));
+                }
 
                 if self.app.interface.button_padding_spinbox.take_change() {
                     actions.push(AppAction::Interface(pages::interface::InterfaceMessage::SetButtonPadding(self.app.interface.button_padding_spinbox.value as u16)));
@@ -679,21 +691,7 @@ impl SystemInterface {
                 if self.app.system_info.notifications_duration_spinbox.take_change() {
                     actions.push(AppAction::SystemInfo(pages::system_info::SystemMessage::SetNotificationsDuration(self.app.system_info.notifications_duration_spinbox.value)));
                 }
-                if self.app.system_info.status_separators_toggle.take_change() {
-                    actions.push(AppAction::SystemInfo(pages::system_info::SystemMessage::StatusToggleSeparators));
-                }
-                if self.app.system_info.status_underline_toggle.take_change() {
-                    actions.push(AppAction::SystemInfo(pages::system_info::SystemMessage::StatusToggleUnderline));
-                }
-                if self.app.system_info.status_padding_spinbox.take_change() {
-                    actions.push(AppAction::SystemInfo(pages::system_info::SystemMessage::StatusSetPadding(self.app.system_info.status_padding_spinbox.value as u16)));
-                }
-                if self.app.system_info.status_box_opacity_slider.take_change() {
-                    actions.push(AppAction::SystemInfo(pages::system_info::SystemMessage::StatusSetBoxOpacity(self.app.system_info.status_box_opacity_slider.value())));
-                }
-                if self.app.system_info.status_box_blur_slider.take_change() {
-                    actions.push(AppAction::SystemInfo(pages::system_info::SystemMessage::StatusSetBoxBlur(self.app.system_info.status_box_blur_slider.value())));
-                }
+
             }
             Page::Accounts => {
                 if self.app.accounts.adding_new && self.app.accounts.email_box.take_change() {
diff --git a/src/pages/interface.rs b/src/pages/interface.rs
index 0fdcac1..97bf528 100644
--- a/src/pages/interface.rs
+++ b/src/pages/interface.rs
@@ -1,15 +1,47 @@
 use std::fs;
 use std::io::Write;
-use crate::app::PageContent;
+use crate::app::{PageContent, SectionContextExt};
 use cce_ui::layout::{render_widget, PageLayoutBuilder, LayoutStrategy};
 use cce_ui::widget::{
     ColorSelector, Spinbox, Element, Dropdown, TextBox, FontSelector, Toggle, MultiControl,
-    LayoutPreview, PreviewLayoutMode
+    LayoutPreview, PreviewLayoutMode, Label, Slider
 };
 
 const CONFIG_PATH: &str = "/home/lsgalante/.config/cce/config.json";
 const LINKS_PATH: &str = "/home/lsgalante/.config/cce/cce-system-interface/links.json";
 
+#[derive(Debug, Clone)]
+pub struct StatusData {
+    pub font_size: u16,
+    pub padding: u16,
+    pub separators: bool,
+    pub underline: bool,
+    pub running: bool,
+    pub bg_opacity: f32,
+    pub bg_blur: f32,
+}
+
+thread_local! {
+    static TEST_CONFIG_PATH: std::cell::RefCell<Option<String>> = std::cell::RefCell::new(None);
+}
+
+fn get_config_path() -> String {
+    #[cfg(test)]
+    {
+        TEST_CONFIG_PATH.with(|p| {
+            if let Some(path) = p.borrow().as_ref() {
+                return path.clone();
+            }
+            CONFIG_PATH.to_string()
+        })
+    }
+    #[cfg(not(test))]
+    {
+        CONFIG_PATH.to_string()
+    }
+}
+
+
 fn get_socket_path() -> String {
     match std::env::var("WAYLAND_DISPLAY") {
         Ok(display) => format!("/tmp/cce-{}.sock", display),
@@ -328,6 +360,18 @@ pub struct InterfaceState {
     pub status_padding_spinbox: Spinbox,
     pub status_module_spacing: u16,
     pub status_module_spacing_spinbox: Spinbox,
+    pub status_loaded: bool,
+    pub status_font_size: u16,
+    pub status_separators: bool,
+    pub status_underline: bool,
+    pub status_running: bool,
+    pub status_label: Label,
+    pub status_separators_toggle: Toggle,
+    pub status_underline_toggle: Toggle,
+    pub status_box_opacity: f32,
+    pub status_box_blur: f32,
+    pub status_box_opacity_slider: Slider,
+    pub status_box_blur_slider: Slider,
     pub nested_section_label_alignment: u8,
     pub label_alignment_menu: Dropdown,
     pub nested_section_label_offset: i16,
@@ -570,6 +614,18 @@ impl Default for InterfaceState {
             status_padding_spinbox: Spinbox::new(8, 0, 32, 1).with_label("Padding").with_unit("px").with_config(CONFIG_PATH, "status_padding"),
             status_module_spacing: 8,
             status_module_spacing_spinbox: Spinbox::new(8, 0, 100, 1).with_label("Spacing").with_unit("px").with_config(CONFIG_PATH, "status_module_spacing"),
+            status_loaded: false,
+            status_font_size: 11,
+            status_separators: true,
+            status_underline: true,
+            status_running: false,
+            status_label: Label::new("Status Interface: Stopped").with_font_size(14.0).with_color([170, 51, 51]),
+            status_separators_toggle: Toggle::new().with_label("Show Separators").with_config(CONFIG_PATH, "status_separators"),
+            status_underline_toggle: Toggle::new().with_label("Show Underline").with_config(CONFIG_PATH, "status_underline"),
+            status_box_opacity: 1.0,
+            status_box_blur: 0.0,
+            status_box_opacity_slider: Slider::new().with_range(0.0, 100.0).with_scroll(true).with_value(1.0).with_label("Background Opacity").with_config(CONFIG_PATH, "status_box_opacity"),
+            status_box_blur_slider: Slider::new().with_range(0.0, 100.0).with_scroll(true).with_value(0.0).with_label("Background Blur").with_config(CONFIG_PATH, "status_box_blur"),
             custom_multicontrol: MultiControl::new("custom_parameters".to_string()).with_label("custom_parameters"),
             layout_status: None,
         }
@@ -678,6 +734,13 @@ pub enum InterfaceMessage {
     Refreshed(InterfaceState),
     TypefaceRefreshed(InterfaceState),
     LayoutStatusRefreshed(LayoutStatusInfo),
+    StatusRefreshed(StatusData),
+    StatusToggleSeparators,
+    StatusToggleUnderline,
+    StatusReload,
+    StatusSetPadding(u16),
+    StatusSetBoxOpacity(f32),
+    StatusSetBoxBlur(f32),
     SetSans(String),
     SetSerif(String),
     SetMono(String),
@@ -915,6 +978,18 @@ pub fn read_interface_config() -> InterfaceState {
         status_padding_spinbox: Spinbox::new(status_padding as i32, 0, 32, 1).with_label("Padding").with_unit("px").with_config(CONFIG_PATH, "status_padding"),
         status_module_spacing,
         status_module_spacing_spinbox: Spinbox::new(status_module_spacing as i32, 0, 100, 1).with_label("Spacing").with_unit("px").with_config(CONFIG_PATH, "status_module_spacing"),
+        status_loaded: false,
+        status_font_size: 11,
+        status_separators: true,
+        status_underline: true,
+        status_running: false,
+        status_label: Label::new("Status Interface: Stopped").with_font_size(14.0).with_color([170, 51, 51]),
+        status_separators_toggle: Toggle::new().with_label("Show Separators").with_config(CONFIG_PATH, "status_separators"),
+        status_underline_toggle: Toggle::new().with_label("Show Underline").with_config(CONFIG_PATH, "status_underline"),
+        status_box_opacity: 1.0,
+        status_box_blur: 0.0,
+        status_box_opacity_slider: Slider::new().with_range(0.0, 100.0).with_scroll(true).with_value(1.0).with_label("Background Opacity").with_config(CONFIG_PATH, "status_box_opacity"),
+        status_box_blur_slider: Slider::new().with_range(0.0, 100.0).with_scroll(true).with_value(0.0).with_label("Background Blur").with_config(CONFIG_PATH, "status_box_blur"),
         nested_section_label_alignment,
         label_alignment_menu: Dropdown::new(
             vec!["Left".to_string(), "Center".to_string(), "Right".to_string()],
@@ -1847,6 +1922,85 @@ pub fn status_interface_reload() {
     });
 }
 
+fn write_status_value(key: &str, value: &str) {
+    write_config_value_path(&get_config_path(), key, value);
+}
+
+fn read_status_font_size() -> Option<u16> {
+    let content = std::fs::read_to_string(&get_config_path()).ok()?;
+    Some(parse_u16_from(&content, "status_font_size", 11))
+}
+
+fn read_status_padding() -> Option<u16> {
+    let content = std::fs::read_to_string(&get_config_path()).ok()?;
+    Some(parse_u16_from(&content, "status_padding", 8))
+}
+
+fn write_status_padding(padding: u16) {
+    write_status_value("status_padding", &padding.to_string());
+}
+
+fn read_status_separators() -> Option<bool> {
+    let content = std::fs::read_to_string(&get_config_path()).ok()?;
+    Some(parse_bool_from(&content, "status_separators", true))
+}
+
+fn write_status_separators(val: bool) {
+    write_status_value("status_separators", &val.to_string());
+}
+
+fn read_status_underline() -> Option<bool> {
+    let content = std::fs::read_to_string(&get_config_path()).ok()?;
+    Some(parse_bool_from(&content, "status_underline", true))
+}
+
+fn write_status_underline(val: bool) {
+    write_status_value("status_underline", &val.to_string());
+}
+
+fn read_status_box_opacity() -> Option<f32> {
+    let content = std::fs::read_to_string(&get_config_path()).ok()?;
+    Some(parse_f32_from(&content, "status_box_opacity", 1.0))
+}
+
+fn write_status_box_opacity(val: f32) {
+    write_status_value("status_box_opacity", &val.to_string());
+}
+
+fn read_status_box_blur() -> Option<f32> {
+    let content = std::fs::read_to_string(&get_config_path()).ok()?;
+    Some(parse_f32_from(&content, "status_box_blur", 0.0))
+}
+
+fn write_status_box_blur(val: f32) {
+    write_status_value("status_box_blur", &val.to_string());
+}
+
+pub async fn fetch_status_state() -> StatusData {
+    let running = tokio::process::Command::new("pgrep")
+        .args(["-f", "cce-status-interface"]).output().await.ok()
+        .map(|o| !o.stdout.is_empty())
+        .unwrap_or(false);
+
+    let font_size = read_status_font_size().unwrap_or(11);
+    let padding = read_status_padding().unwrap_or(8);
+    let separators = read_status_separators().unwrap_or(true);
+    let underline = read_status_underline().unwrap_or(true);
+    let bg_opacity = read_status_box_opacity().unwrap_or(1.0);
+    let bg_blur = read_status_box_blur().unwrap_or(0.0);
+
+    StatusData {
+        font_size,
+        padding,
+        separators,
+        underline,
+        running,
+        bg_opacity,
+        bg_blur,
+    }
+}
+
+
 fn apply_visual_guides_color(rgb: [u8; 3]) {
     let hex = format!("\"#{:02x}{:02x}{:02x}\"", rgb[0], rgb[1], rgb[2]);
     write_config_value("visual_guides_color", &hex);
@@ -2628,6 +2782,7 @@ pub fn view(state: &mut InterfaceState, cx: f32, cy: f32, cw: f32, ch: f32, sec_
 
     // 3. Status Section
     builder.add_section_with_width(&mut final_pc, cw, "Status", false, |sec| {
+        const TEXT_DIM: [f32; 4] = [0.53, 0.53, 0.60, 1.0];
         sec.spacing(8.0);
         state.color_selectors[7].color = state.normal_color;
         sec.widget_full(&mut state.color_selectors[7], 40.0, ctx);
@@ -2647,6 +2802,62 @@ pub fn view(state: &mut InterfaceState, cx: f32, cy: f32, cw: f32, ch: f32, sec_
         state.status_module_spacing_spinbox.value = state.status_module_spacing as i32;
         sec.widget_full(&mut state.status_module_spacing_spinbox, 44.0, ctx);
         sec.spacing(8.0);
+
+        if !state.status_loaded {
+            sec.text("Loading Status Interface status...", 12.0, 0.0, 12.0, TEXT_DIM);
+            sec.spacing(8.0);
+        } else {
+            // Status
+            let status_text = if state.status_running { "Status Interface: Running" } else { "Status Interface: Stopped" };
+            let status_color = if state.status_running { [92, 143, 97] } else { [170, 51, 51] };
+            state.status_label.set_text(status_text);
+            state.status_label.set_color(status_color);
+            sec.widget_full(&mut state.status_label, 20.0, ctx);
+            sec.spacing(8.0);
+
+            // Separators toggle
+            state.status_separators_toggle.set_toggled(state.status_separators);
+            sec.widget_full(&mut state.status_separators_toggle, cce_ui::layout::toggle_height(), ctx);
+            sec.spacing(8.0);
+
+            // Underline toggle
+            state.status_underline_toggle.set_toggled(state.status_underline);
+            sec.widget_full(&mut state.status_underline_toggle, cce_ui::layout::toggle_height(), ctx);
+            sec.spacing(8.0);
+
+            // Opacity slider
+            state.status_box_opacity_slider.set_label(&format!("Background Opacity: {}%", (state.status_box_opacity * 100.0).round() as i32));
+            state.status_box_opacity_slider.set_value(state.status_box_opacity);
+            let label_h_op = cce_ui::widget::label_offset(&state.status_box_opacity_slider);
+            let slider_h_op = cce_ui::layout::slider_height() + label_h_op;
+            sec.widget_full(&mut state.status_box_opacity_slider, slider_h_op, ctx);
+            sec.spacing(8.0);
+
+            // Blur slider
+            state.status_box_blur_slider.set_label(&format!("Background Blur: {}%", (state.status_box_blur * 100.0).round() as i32));
+            state.status_box_blur_slider.set_value(state.status_box_blur);
+            let label_h_bl = cce_ui::widget::label_offset(&state.status_box_blur_slider);
+            let slider_h_bl = cce_ui::layout::slider_height() + label_h_bl;
+            sec.widget_full(&mut state.status_box_blur_slider, slider_h_bl, ctx);
+            sec.spacing(8.0);
+
+            // Reload button
+            let yt_reload = sec.ay();
+            let btn_w = cw - 24.0;
+            let button_x = sec.left + 12.0;
+            sec.button(
+                "Reload Status Interface",
+                button_x,
+                yt_reload,
+                btn_w,
+                32.0,
+                [0.13, 0.18, 0.14, 1.0],
+                [0.25, 0.30, 0.26, 1.0],
+                [1.0, 1.0, 1.0, 1.0],
+                crate::app::AppAction::Interface(InterfaceMessage::StatusReload),
+            );
+            sec.spacing(12.0);
+        }
     });
 
     // 4. Controls Section
@@ -3386,6 +3597,56 @@ pub fn update(state: &mut InterfaceState, msg: InterfaceMessage) {
             state.status_padding_spinbox.value = padding as i32;
             apply_status_padding(padding);
         }
+        InterfaceMessage::StatusRefreshed(new) => {
+            let was_status_hovered = state.status_label.hovered();
+            let was_separators_hovered = state.status_separators_toggle.hovered();
+            let was_underline_hovered = state.status_underline_toggle.hovered();
+            let was_opacity_hovered = state.status_box_opacity_slider.hovered();
+            let was_blur_hovered = state.status_box_blur_slider.hovered();
+
+            state.status_loaded = true;
+            state.status_font_size = new.font_size;
+            state.status_padding = new.padding;
+            state.status_separators = new.separators;
+            state.status_underline = new.underline;
+            state.status_running = new.running;
+            state.status_box_opacity = new.bg_opacity;
+            state.status_box_blur = new.bg_blur;
+
+            state.status_label.set_hovered(was_status_hovered);
+            state.status_separators_toggle.set_hovered(was_separators_hovered);
+            state.status_underline_toggle.set_hovered(was_underline_hovered);
+            state.status_box_opacity_slider.set_hovered(was_opacity_hovered);
+            state.status_box_blur_slider.set_hovered(was_blur_hovered);
+        }
+        InterfaceMessage::StatusToggleSeparators => {
+            state.status_separators = !state.status_separators;
+            write_status_separators(state.status_separators);
+            status_interface_reload();
+        }
+        InterfaceMessage::StatusToggleUnderline => {
+            state.status_underline = !state.status_underline;
+            write_status_underline(state.status_underline);
+            status_interface_reload();
+        }
+        InterfaceMessage::StatusSetPadding(val) => {
+            state.status_padding = val;
+            write_status_padding(val);
+            status_interface_reload();
+        }
+        InterfaceMessage::StatusSetBoxOpacity(val) => {
+            state.status_box_opacity = val;
+            write_status_box_opacity(val);
+            status_interface_reload();
+        }
+        InterfaceMessage::StatusSetBoxBlur(val) => {
+            state.status_box_blur = val;
+            write_status_box_blur(val);
+            status_interface_reload();
+        }
+        InterfaceMessage::StatusReload => {
+            status_interface_reload();
+        }
         InterfaceMessage::SetStatusModuleSpacing(spacing) => {
             state.status_module_spacing = spacing;
             state.status_module_spacing_spinbox.value = spacing as i32;
@@ -5751,6 +6012,96 @@ mod tests {
         // Assert that the context menu is hidden (cleared)
         assert!(!cce_ui::widget::context_menu::is_visible());
     }
+
+    #[test]
+    fn test_read_write_separators() {
+        let dir = std::env::temp_dir();
+        let path = dir.join("test_status_separators.json");
+        let path_str = path.to_str().unwrap().to_string();
+
+        let _ = fs::write(&path_str, "{\"layout\": {\"status_separators\": true, \"status_padding\": 8}}");
+        TEST_CONFIG_PATH.with(|p| *p.borrow_mut() = Some(path_str));
+
+        let original = read_status_separators().unwrap_or(true);
+        write_status_separators(!original);
+        assert_eq!(read_status_separators(), Some(!original));
+        write_status_separators(original);
+        assert_eq!(read_status_separators(), Some(original));
+
+        let _ = fs::remove_file(path);
+    }
+
+    #[test]
+    fn test_read_write_padding() {
+        let dir = std::env::temp_dir();
+        let path = dir.join("test_status_padding.json");
+        let path_str = path.to_str().unwrap().to_string();
+
+        let _ = fs::write(&path_str, "{\"layout\": {\"status_separators\": true, \"status_padding\": 8}}");
+        TEST_CONFIG_PATH.with(|p| *p.borrow_mut() = Some(path_str));
+
+        let original = read_status_padding().unwrap_or(8);
+        write_status_padding(12);
+        assert_eq!(read_status_padding(), Some(12));
+        write_status_padding(original);
+        assert_eq!(read_status_padding(), Some(original));
+
+        let _ = fs::remove_file(path);
+    }
+
+    #[test]
+    fn test_read_write_underline() {
+        let dir = std::env::temp_dir();
+        let path = dir.join("test_status_underline.json");
+        let path_str = path.to_str().unwrap().to_string();
+
+        let _ = fs::write(&path_str, "{\"layout\": {\"status_underline\": true, \"status_padding\": 8}}");
+        TEST_CONFIG_PATH.with(|p| *p.borrow_mut() = Some(path_str));
+
+        let original = read_status_underline().unwrap_or(true);
+        write_status_underline(!original);
+        assert_eq!(read_status_underline(), Some(!original));
+        write_status_underline(original);
+        assert_eq!(read_status_underline(), Some(original));
+
+        let _ = fs::remove_file(path);
+    }
+
+    #[test]
+    fn test_read_write_status_box_opacity() {
+        let dir = std::env::temp_dir();
+        let path = dir.join("test_status_box_opacity.json");
+        let path_str = path.to_str().unwrap().to_string();
+
+        let _ = fs::write(&path_str, "{\"layout\": {\"status_box_opacity\": 1.0}}");
+        TEST_CONFIG_PATH.with(|p| *p.borrow_mut() = Some(path_str));
+
+        let original = read_status_box_opacity().unwrap_or(1.0);
+        write_status_box_opacity(0.75);
+        assert_eq!(read_status_box_opacity(), Some(0.75));
+        write_status_box_opacity(original);
+        assert_eq!(read_status_box_opacity(), Some(original));
+
+        let _ = fs::remove_file(path);
+    }
+
+    #[test]
+    fn test_read_write_status_box_blur() {
+        let dir = std::env::temp_dir();
+        let path = dir.join("test_status_box_blur.json");
+        let path_str = path.to_str().unwrap().to_string();
+
+        let _ = fs::write(&path_str, "{\"layout\": {\"status_box_blur\": 0.0}}");
+        TEST_CONFIG_PATH.with(|p| *p.borrow_mut() = Some(path_str));
+
+        let original = read_status_box_blur().unwrap_or(0.0);
+        write_status_box_blur(0.5);
+        assert_eq!(read_status_box_blur(), Some(0.5));
+        write_status_box_blur(original);
+        assert_eq!(read_status_box_blur(), Some(original));
+
+        let _ = fs::remove_file(path);
+    }
 }