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

commitaeb2ac7ddf8faeca54df02da99613b7d5af4da23
parent8f8f1ac77f
authorLucas Galante <[email protected]>
date2026-07-05 19:09
Refactor: remove unsafe transmutes and implement in-place page widget updates on refresh

 src/input_handler.rs   |  6 +-----
 src/pages/audio.rs     |  4 +++-
 src/pages/fonts.rs     | 11 ++++++++++-
 src/pages/network.rs   | 19 ++++++++++++-------
 src/pages/packages.rs  | 34 +++++++++-------------------------
 src/pages/processes.rs |  3 ---
 6 files changed, 35 insertions(+), 42 deletions(-)

diff --git a/src/input_handler.rs b/src/input_handler.rs
index 8ea64b8..ba91bc2 100644
--- a/src/input_handler.rs
+++ b/src/input_handler.rs
@@ -312,11 +312,7 @@ impl SystemInterface {
 
     pub(crate) fn get_page_root_widget(&mut self) -> Option<*mut (dyn cce_ui::widget::Element + 'static)> {
         let page_idx = Page::ALL.iter().position(|&p| p == self.app.current_page).unwrap_or(0);
-        let ptr = &mut self.pages[page_idx] as &mut dyn cce_ui::widget::Element as *mut dyn cce_ui::widget::Element;
-        let static_ptr = unsafe {
-            std::mem::transmute::<*mut dyn cce_ui::widget::Element, *mut (dyn cce_ui::widget::Element + 'static)>(ptr)
-        };
-        Some(static_ptr)
+        Some(self.pages[page_idx].as_ptr_mut())
     }
 
     pub(crate) fn handle_key_input_internal(&mut self, event: &cce_ui::widget::KeyEvent) -> bool {
diff --git a/src/pages/audio.rs b/src/pages/audio.rs
index 42077ad..1a0ef1d 100644
--- a/src/pages/audio.rs
+++ b/src/pages/audio.rs
@@ -363,7 +363,9 @@ pub fn view(state: &mut AudioState, cx: f32, cy: f32, cw: f32, ch: f32, sec_focu
 pub fn update(state: &mut AudioState, msg: AudioMessage) {
     match msg {
         AudioMessage::Refreshed(new) => {
-            *state = new;
+            state.loaded = new.loaded;
+            state.sinks = new.sinks;
+            state.sources = new.sources;
             state.sink_spinboxes.resize_with(state.sinks.len(), || Box::new(Spinbox::new(50, 0, 100, 1)));
             state.source_spinboxes.resize_with(state.sources.len(), || Box::new(Spinbox::new(50, 0, 100, 1)));
             state.sink_sliders.resize_with(state.sinks.len(), || Box::new(Slider::new().with_range(0.0, 1.0).with_scroll(true)));
diff --git a/src/pages/fonts.rs b/src/pages/fonts.rs
index 2d14246..1d3c590 100644
--- a/src/pages/fonts.rs
+++ b/src/pages/fonts.rs
@@ -569,7 +569,16 @@ pub fn read_typeface_config() -> FontsState {
 pub fn update(state: &mut FontsState, msg: FontsMessage) {
     match msg {
         FontsMessage::TypefaceRefreshed(refreshed) | FontsMessage::Refreshed(refreshed) => {
-            *state = refreshed;
+            state.typeface_loaded = refreshed.typeface_loaded;
+            state.sans_serif = refreshed.sans_serif;
+            state.serif = refreshed.serif;
+            state.monospace = refreshed.monospace;
+            state.window_borders = refreshed.window_borders;
+            state.status_interface = refreshed.status_interface;
+            state.fuzzel = refreshed.fuzzel;
+            state.terminal = refreshed.terminal;
+            state.all_fonts = refreshed.all_fonts;
+            state.mono_fonts = refreshed.mono_fonts;
         }
         FontsMessage::SetSans(font) => {
             state.sans_serif = font;
diff --git a/src/pages/network.rs b/src/pages/network.rs
index 3ee1147..57e10f5 100644
--- a/src/pages/network.rs
+++ b/src/pages/network.rs
@@ -476,13 +476,18 @@ pub fn view(state: &mut NetworkState, cx: f32, cy: f32, cw: f32, ch: f32, root_f
 pub fn update(state: &mut NetworkState, msg: NetworkMessage) {
     match msg {
         NetworkMessage::Refreshed(new) => {
-            let old_scroll = state.wifi_list_box.scroll_y();
-            let was_wifi_hovered = state.wifi_toggle.hovered();
-            let was_bt_hovered = state.bt_toggle.hovered();
-            *state = new;
-            state.wifi_list_box.set_scroll_y(old_scroll);
-            state.wifi_toggle.set_hovered(was_wifi_hovered);
-            state.bt_toggle.set_hovered(was_bt_hovered);
+            state.loaded = new.loaded;
+            state.wifi_enabled = new.wifi_enabled;
+            state.connected_ssid = new.connected_ssid;
+            state.signal_strength = new.signal_strength;
+            state.ip_address = new.ip_address;
+            state.device = new.device;
+            state.available = new.available;
+            state.bt_installed = new.bt_installed;
+            state.bt_service_active = new.bt_service_active;
+            state.bt_enabled = new.bt_enabled;
+            state.bt_devices = new.bt_devices;
+            state.bt_scanning = new.bt_scanning;
         }
         NetworkMessage::ToggleWifi => {
             state.wifi_enabled = !state.wifi_enabled;
diff --git a/src/pages/packages.rs b/src/pages/packages.rs
index 57a9ac1..a497042 100644
--- a/src/pages/packages.rs
+++ b/src/pages/packages.rs
@@ -619,31 +619,15 @@ pub fn view(
 pub fn update(state: &mut PackagesState, msg: PackagesMessage) {
     match msg {
         PackagesMessage::Refreshed(new) => {
-            let active = state.active_tab;
-            let query = state.search_box.text.clone();
-            let is_editing = state.search_box.editing;
-            let edit_buf = state.search_box.edit_buffer.clone();
-            
-            let selected_package = state.selected_package.clone();
-            let selected_package_info = state.selected_package_info.clone();
-            let loading_info = state.loading_info;
-
-            let installed_scroll = state.installed_list_box.scroll_y();
-            let updates_scroll = state.updates_list_box.scroll_y();
-            
-            *state = new;
-            
-            state.active_tab = active;
-            state.search_box.text = query;
-            state.search_box.editing = is_editing;
-            state.search_box.edit_buffer = edit_buf;
-            
-            state.selected_package = selected_package;
-            state.selected_package_info = selected_package_info;
-            state.loading_info = loading_info;
-
-            state.installed_list_box.set_scroll_y(installed_scroll);
-            state.updates_list_box.set_scroll_y(updates_scroll);
+            state.loaded = new.loaded;
+            state.installed = new.installed;
+            state.updates = new.updates;
+            state.updating = new.updating;
+            state.last_update_res = new.last_update_res;
+            state.selected_package = new.selected_package;
+            state.selected_package_info = new.selected_package_info;
+            state.loading_info = new.loading_info;
+            state.uninstalling = new.uninstalling;
         }
         PackagesMessage::SetTab(tab) => {
             state.active_tab = tab;
diff --git a/src/pages/processes.rs b/src/pages/processes.rs
index 75c75c5..8533316 100644
--- a/src/pages/processes.rs
+++ b/src/pages/processes.rs
@@ -374,9 +374,6 @@ pub fn update(state: &mut ProcessesState, msg: ProcessesMessage) {
         ProcessesMessage::Refreshed(new) => {
             state.loaded = new.loaded;
             state.processes = new.processes;
-            let old_scroll = state.cpu_list_box.scroll_y();
-            state.cpu_list_box = new.cpu_list_box;
-            state.cpu_list_box.set_scroll_y(old_scroll);
         }
         ProcessesMessage::ServicesRefreshed(new_services) => {
             state.services_loaded = true;