From e40b953e5a64b90d57bbd549958bebe4b14e9c9d Mon Sep 17 00:00:00 2001 From: oo8dev Date: Sat, 25 Jul 2026 18:40:07 +0200 Subject: [PATCH] Dynamic color palettes without restart (#594) * dash-frontend: dynamic color palette switching * wayvr: add support for color dynamic color palette refresh --- .../assets/gui/view/popup_window.xml | 2 +- dash-frontend/assets/lang/de.json | 3 +- dash-frontend/assets/lang/en.json | 1 - dash-frontend/assets/lang/es.json | 3 +- dash-frontend/assets/lang/it.json | 3 +- dash-frontend/assets/lang/ja.json | 3 +- dash-frontend/assets/lang/pl.json | 3 +- dash-frontend/assets/lang/zh_CN.json | 3 +- .../src/tab/settings/tab_look_and_feel.rs | 5 +- dash-frontend/src/views/color_palettes.rs | 97 ++++--------------- wayvr/src/backend/task.rs | 1 + wayvr/src/gui/panel/mod.rs | 5 +- wayvr/src/overlays/dashboard.rs | 8 +- wayvr/src/state.rs | 4 +- wayvr/src/windowing/backend.rs | 1 + wayvr/src/windowing/manager.rs | 14 +++ wgui/src/layout.rs | 28 ++++++ wgui/src/palette.rs | 2 +- wgui/src/widget/label.rs | 9 +- wgui/src/widget/mod.rs | 2 + wlx-common/src/dash_interface.rs | 2 +- 21 files changed, 95 insertions(+), 104 deletions(-) diff --git a/dash-frontend/assets/gui/view/popup_window.xml b/dash-frontend/assets/gui/view/popup_window.xml index 88245458..fca9b563 100644 --- a/dash-frontend/assets/gui/view/popup_window.xml +++ b/dash-frontend/assets/gui/view/popup_window.xml @@ -23,7 +23,7 @@
diff --git a/dash-frontend/assets/lang/de.json b/dash-frontend/assets/lang/de.json index 4692b502..f671d5ad 100644 --- a/dash-frontend/assets/lang/de.json +++ b/dash-frontend/assets/lang/de.json @@ -191,7 +191,6 @@ "COLOR_PALETTES": "Farbpaletten", "COLOR_PALETTE_CURRENT": "Derzeit aktives Thema.", "COLOR_PALETTE_ACTIVATE": "Klicken Sie hier, um dieses Thema zu verwenden.", - "APPLY_CHANGES_RESTART": "WayVR neu starten, um die Änderungen zu übernehmen?", "COLOR_PALETTE_HELP": "Klicken, um Farbpaletten zu durchsuchen.\nUm eigene zu erstellen, besuche die Webseite!", "COLOR_PALETTE_CUSTOM_URL": "Füge dein eigenes benutzerdefiniertes Thema hinzu!", "COLOR_PALETTE_CUSTOM_URL2": "Klicken Sie hier, um das Web-Handbuch zu öffnen.", @@ -329,4 +328,4 @@ "REMOVE_FROM_FAVOURITES": "Aus Favoriten entfernen", "EMPTY": "Leer", "PINNED_APPS": "Angepinnte Anwendungen" -} \ No newline at end of file +} diff --git a/dash-frontend/assets/lang/en.json b/dash-frontend/assets/lang/en.json index 3fc32f94..53a831ca 100644 --- a/dash-frontend/assets/lang/en.json +++ b/dash-frontend/assets/lang/en.json @@ -103,7 +103,6 @@ "COLOR_PALETTE_CUSTOM_URL": "Add your own custom theme!", "COLOR_PALETTE_CUSTOM_URL2": "Click to open web manual.", "COLOR_PALETTE_ACTIVATE": "Click to use this theme.", - "APPLY_CHANGES_RESTART": "Restart WayVR to apply changes?", "CLEAR_PIPEWIRE_TOKENS": "Clear PipeWire tokens", "CLEAR_PIPEWIRE_TOKENS_HELP": "Prompt for screen selection on next start", "CLEAR_SAVED_STATE": "Clear saved state", diff --git a/dash-frontend/assets/lang/es.json b/dash-frontend/assets/lang/es.json index 3e95ba63..883a4602 100644 --- a/dash-frontend/assets/lang/es.json +++ b/dash-frontend/assets/lang/es.json @@ -191,7 +191,6 @@ "COLOR_PALETTES": "Paletas de colores", "COLOR_PALETTE_CURRENT": "Tema actualmente activo.", "COLOR_PALETTE_ACTIVATE": "Haz clic para usar este tema.", - "APPLY_CHANGES_RESTART": "¿Reiniciar WayVR para aplicar los cambios?", "COLOR_PALETTE_HELP": "Haz clic para explorar paletas de colores.\nPara crear paletas personalizadas, ¡visita el sitio web!", "COLOR_PALETTE_CUSTOM_URL": "¡Añade tu propio tema personalizado!", "COLOR_PALETTE_CUSTOM_URL2": "Haz clic para abrir el manual web.", @@ -329,4 +328,4 @@ "REMOVE_FROM_FAVOURITES": "Eliminar de favoritos", "EMPTY": "Vacío", "PINNED_APPS": "Aplicaciones ancladas" -} \ No newline at end of file +} diff --git a/dash-frontend/assets/lang/it.json b/dash-frontend/assets/lang/it.json index 37e0bdc6..1eb9b658 100644 --- a/dash-frontend/assets/lang/it.json +++ b/dash-frontend/assets/lang/it.json @@ -212,7 +212,6 @@ "COLOR_PALETTES": "Tavolozze colori", "COLOR_PALETTE_CURRENT": "Tema attualmente attivo.", "COLOR_PALETTE_ACTIVATE": "Clicca per usare questo tema.", - "APPLY_CHANGES_RESTART": "Riavviare WayVR per applicare le modifiche?", "COLOR_PALETTE_HELP": "Clicca per sfogliare le palette di colori.\nPer crearne di personalizzate, visita il sito web!", "COLOR_PALETTE_CUSTOM_URL": "Aggiungi il tuo tema personalizzato!", "COLOR_PALETTE_CUSTOM_URL2": "Clicca per aprire il manuale web.", @@ -329,4 +328,4 @@ "REMOVE_FROM_FAVOURITES": "Rimuovi dai preferiti", "EMPTY": "Vuoto", "PINNED_APPS": "Applicazioni fissate" -} \ No newline at end of file +} diff --git a/dash-frontend/assets/lang/ja.json b/dash-frontend/assets/lang/ja.json index 04618528..6dbb6ca4 100644 --- a/dash-frontend/assets/lang/ja.json +++ b/dash-frontend/assets/lang/ja.json @@ -191,7 +191,6 @@ "COLOR_PALETTES": "カラーパレット", "COLOR_PALETTE_CURRENT": "現在有効なテーマ。", "COLOR_PALETTE_ACTIVATE": "クリックしてこのテーマを適用します。", - "APPLY_CHANGES_RESTART": "変更を適用するためにWayVRを再起動しますか?", "COLOR_PALETTE_HELP": "クリックしてカラーパレットを選択してください。\nカスタムパレットの作成については、ウェブサイトを参照してください!", "COLOR_PALETTE_CUSTOM_URL": "カスタムテーマを追加しましょう!", "COLOR_PALETTE_CUSTOM_URL2": "クリックしてウェブマニュアルを開く。", @@ -329,4 +328,4 @@ "REMOVE_FROM_FAVOURITES": "お気に入りから削除", "EMPTY": "空", "PINNED_APPS": "ピン留めされたアプリケーション" -} \ No newline at end of file +} diff --git a/dash-frontend/assets/lang/pl.json b/dash-frontend/assets/lang/pl.json index 585ffdbb..aa372bd0 100644 --- a/dash-frontend/assets/lang/pl.json +++ b/dash-frontend/assets/lang/pl.json @@ -186,7 +186,6 @@ "COLOR_PALETTES": "Palety kolorów", "COLOR_PALETTE_CURRENT": "Obecnie aktywny motyw.", "COLOR_PALETTE_ACTIVATE": "Kliknij, aby użyć tego motywu.", - "APPLY_CHANGES_RESTART": "Zrestartować WayVR, aby zastosować zmiany?", "COLOR_PALETTE_HELP": "Kliknij, aby przeglądać palety kolorów.\nAby stworzyć własne, odwiedź stronę internetową!", "COLOR_PALETTE_CUSTOM_URL": "Dodaj własny motyw!", "COLOR_PALETTE_CUSTOM_URL2": "Kliknij, aby otworzyć instrukcję internetową.", @@ -329,4 +328,4 @@ "REMOVE_FROM_FAVOURITES": "Usuń z ulubionych", "EMPTY": "Puste", "PINNED_APPS": "Przypięte aplikacje" -} \ No newline at end of file +} diff --git a/dash-frontend/assets/lang/zh_CN.json b/dash-frontend/assets/lang/zh_CN.json index 08107d48..a9437312 100644 --- a/dash-frontend/assets/lang/zh_CN.json +++ b/dash-frontend/assets/lang/zh_CN.json @@ -212,7 +212,6 @@ "COLOR_PALETTES": "配色方案", "COLOR_PALETTE_CURRENT": "当前激活的主题。", "COLOR_PALETTE_ACTIVATE": "点击以使用此主题。", - "APPLY_CHANGES_RESTART": "重启 WayVR 以应用更改吗?", "COLOR_PALETTE_HELP": "点击浏览配色方案。\n如需创建自定义配色,请参阅网站!", "COLOR_PALETTE_CUSTOM_URL": "添加自定义主题!", "COLOR_PALETTE_CUSTOM_URL2": "点击打开网页版手册。", @@ -329,4 +328,4 @@ "REMOVE_FROM_FAVOURITES": "从收藏中移除", "EMPTY": "空", "PINNED_APPS": "已固定应用程序" -} \ No newline at end of file +} diff --git a/dash-frontend/src/tab/settings/tab_look_and_feel.rs b/dash-frontend/src/tab/settings/tab_look_and_feel.rs index a8245f24..bc264bb0 100644 --- a/dash-frontend/src/tab/settings/tab_look_and_feel.rs +++ b/dash-frontend/src/tab/settings/tab_look_and_feel.rs @@ -11,7 +11,7 @@ use wgui::{ use crate::{ frontend::FrontendTasks, tab::settings::{ - SettingType, SettingsMountParams, SettingsTab, Task as SettingsTask, horiz_cell, + SettingType, SettingsMountParams, SettingsTab, horiz_cell, macros::{options_category, options_checkbox, options_dropdown, options_slider_f32}, mount_requires_restart, }, @@ -29,7 +29,6 @@ pub struct State { frontend_tasks: FrontendTasks, globals: WguiGlobals, tasks: Tasks, - settings_tasks: Tasks, } impl SettingsTab for State { @@ -43,7 +42,6 @@ impl SettingsTab for State { self.frontend_tasks.clone(), self.globals.clone(), self.popup_color_palettes.clone(), - self.settings_tasks.clone(), par.general_config.color_palette.clone(), ); } @@ -81,7 +79,6 @@ impl State { frontend_tasks: par.frontend_tasks.clone(), globals: par.mp.doc_params.globals.clone(), tasks, - settings_tasks: par.mp.tasks.clone(), }) } } diff --git a/dash-frontend/src/views/color_palettes.rs b/dash-frontend/src/views/color_palettes.rs index 9bfd222e..26e368d6 100644 --- a/dash-frontend/src/views/color_palettes.rs +++ b/dash-frontend/src/views/color_palettes.rs @@ -1,11 +1,16 @@ +use crate::{ + frontend::{FrontendTask, FrontendTasks}, + util::popup_manager::{MountPopupOnceParams, PopupHolder}, + views::{ViewTrait, ViewUpdateParams}, +}; use std::{rc::Rc, sync::Arc}; +use wgui::color::WguiColorName; use wgui::{ assets::AssetPath, - color::WguiColorName, components::button::ComponentButton, globals::WguiGlobals, i18n::Translation, - layout::{Layout, WidgetID}, + layout::{Layout, LayoutTask, WidgetID}, log::LogErr, palette::PALETTES, parser::{Fetchable, ParseDocumentParams, TemplateParams}, @@ -16,19 +21,10 @@ use wlx_common::{ palette::{list_palette_files, load_custom_palette}, }; -use crate::{ - frontend::{FrontendTask, FrontendTasks}, - tab::settings::Task as SettingsTask, - util::popup_manager::{MountPopupOnceParams, PopupHolder}, - views::{self, ViewTrait, ViewUpdateParams}, -}; - #[derive(Clone)] enum Task { SelectPalette(String), CustomPaletteUrl, - Restart, - Cancel, } pub struct Params<'a> { @@ -36,40 +32,30 @@ pub struct Params<'a> { pub layout: &'a mut Layout, pub parent_id: WidgetID, pub frontend_tasks: &'a FrontendTasks, - pub settings_tasks: Tasks, + pub on_close_request: Box, pub current_palette: Arc, } pub struct View { tasks: Tasks, frontend_tasks: FrontendTasks, - globals: WguiGlobals, - popup_dialog: PopupHolder, - settings_tasks: Tasks, - chosen_palette: Option>, + on_close_request: Option>, } impl ViewTrait for View { fn update(&mut self, par: &mut ViewUpdateParams) -> anyhow::Result<()> { - self.popup_dialog.update(par)?; - for task in self.tasks.drain() { match task { Task::SelectPalette(profile) => { - self.chosen_palette = Some(profile.into()); - self.show_restart_dialog_box()?; - } - Task::Cancel => { - let close_dialog = self.popup_dialog.get_close_callback(par.layout); - close_dialog(); - } - Task::Restart => { - if let Some(palette) = self.chosen_palette.take() { - par.general_config.color_palette = palette; - par.config_change_kind.replace(ConfigChangeKind::WguiThemeChange); + let mut globals = par.layout.state.globals.get(); + let new_palette = wlx_common::palette::load_palette(&profile); + globals.palette = new_palette; + par.general_config.color_palette = profile.into(); + par.layout.tasks.push(LayoutTask::RefreshPalette); + par.config_change_kind.replace(ConfigChangeKind::WguiColorPaletteChange); + if let Some(c) = self.on_close_request.take() { + c(); } - - self.settings_tasks.push(SettingsTask::RestartSoftware); } Task::CustomPaletteUrl => { self.frontend_tasks.push(FrontendTask::OpenURL( @@ -113,7 +99,6 @@ impl View { let list_parent = parser_state.fetch_widget(¶ms.layout.state, "list_parent")?.id; let tasks = Tasks::new(); - let popup_dialog = PopupHolder::::default(); for (idx, name) in list_palette_files().into_iter().enumerate() { let Ok(palette) = load_custom_palette(&name).log_warn("Could not load custom color palette") else { @@ -246,58 +231,15 @@ impl View { Ok(Self { tasks, frontend_tasks: params.frontend_tasks.clone(), - globals: params.globals.clone(), - popup_dialog, - settings_tasks: params.settings_tasks, - chosen_palette: None, + on_close_request: Some(params.on_close_request), }) } - - fn show_restart_dialog_box(&mut self) -> anyhow::Result<()> { - const ACTION_RESTART: &str = "restart"; - const ACTION_CANCEL: &str = "cancel"; - - let tasks = self.tasks.clone(); - - views::dialog_box::mount_popup( - self.popup_dialog.clone(), - self.frontend_tasks.clone(), - views::dialog_box::Params { - globals: self.globals.clone(), - message: Translation::from_translation_key("APP_SETTINGS.APPLY_CHANGES_RESTART"), - entries: vec![ - views::dialog_box::ButtonEntry { - content: Translation::from_translation_key("APP_SETTINGS.CANCEL"), - icon: "dashboard/close.svg", - action: ACTION_CANCEL, - }, - views::dialog_box::ButtonEntry { - content: Translation::from_translation_key("APP_SETTINGS.RESTART_SOFTWARE"), - icon: "dashboard/refresh.svg", - action: ACTION_RESTART, - }, - ], - on_action_click: Box::new(move |action| match action { - ACTION_RESTART => { - tasks.push(Task::Restart); - } - ACTION_CANCEL => { - tasks.push(Task::Cancel); - } - _ => unreachable!(), - }), - }, - ); - - Ok(()) - } } pub fn mount_popup( frontend_tasks: FrontendTasks, globals: WguiGlobals, popup: PopupHolder, - settings_tasks: Tasks, current_palette: Arc, ) { frontend_tasks @@ -305,13 +247,14 @@ pub fn mount_popup( .push(FrontendTask::MountPopupOnce(MountPopupOnceParams::new( Translation::from_translation_key("APP_SETTINGS.COLOR_PALETTES"), Box::new(move |data| { + let on_close_request = popup.get_close_callback(data.layout); let view = View::new(Params { globals: globals.clone(), layout: data.layout, parent_id: data.id_content, frontend_tasks: &frontend_tasks, - settings_tasks, current_palette, + on_close_request, })?; popup.set_view(data.handle, view, None); diff --git a/wayvr/src/backend/task.rs b/wayvr/src/backend/task.rs index 7a145fa4..c2885ed7 100644 --- a/wayvr/src/backend/task.rs +++ b/wayvr/src/backend/task.rs @@ -107,6 +107,7 @@ pub enum SpawnPos { pub enum GlobalChange { Settings, Keyboard, + ColorPalette, } pub type ModifyOverlayTask = dyn FnOnce(&mut AppState, &mut OverlayWindowConfig) + Send; diff --git a/wayvr/src/gui/panel/mod.rs b/wayvr/src/gui/panel/mod.rs index 88296dc6..bcd8ffff 100644 --- a/wayvr/src/gui/panel/mod.rs +++ b/wayvr/src/gui/panel/mod.rs @@ -29,7 +29,7 @@ use wgui::{ }, gfx::cmd::WGfxClearMode, i18n::Translation, - layout::{Layout, LayoutParams, LayoutUpdateParams, WidgetID}, + layout::{Layout, LayoutParams, LayoutTask, LayoutUpdateParams, WidgetID}, parser::{self, CustomAttribsInfoOwned, Fetchable, ParseDocumentExtra, ParserState}, renderer_vk::{context::Context as WguiContext, text::custom_glyph::CustomGlyphData}, widget::{ @@ -360,6 +360,9 @@ impl OverlayBackend for GuiPanel { } fn notify(&mut self, app: &mut AppState, data: OverlayEventData) -> anyhow::Result<()> { + if let OverlayEventData::ColorPaletteRefresh = data { + self.layout.tasks.push(LayoutTask::RefreshPalette); + } let Some(on_notify) = self.on_notify.take() else { return Ok(()); }; diff --git a/wayvr/src/overlays/dashboard.rs b/wayvr/src/overlays/dashboard.rs index b8301793..e3824542 100644 --- a/wayvr/src/overlays/dashboard.rs +++ b/wayvr/src/overlays/dashboard.rs @@ -538,11 +538,17 @@ impl DashInterface for DashInterfaceLive { data.session.config_dirty = true; match kind { + ConfigChangeKind::WguiColorPaletteChange => { + data.tasks + .enqueue(TaskType::Overlay(OverlayTask::GlobalChange( + GlobalChange::ColorPalette, + ))); + } ConfigChangeKind::OverlayConfig => { data.tasks .enqueue(TaskType::Overlay(OverlayTask::GlobalChange( GlobalChange::Settings, - ))) + ))); } ConfigChangeKind::EnvironmentBlend => { #[cfg(feature = "openxr")] diff --git a/wayvr/src/state.rs b/wayvr/src/state.rs index c95f40f1..3b802e68 100644 --- a/wayvr/src/state.rs +++ b/wayvr/src/state.rs @@ -189,8 +189,6 @@ impl AppState { ) .ok(); - let palette = load_palette(&*session.config.color_palette); - let mut app_state = Self { tasks, gfx, @@ -208,7 +206,7 @@ impl AppState { &lang_provider, &WguiFontConfig::default(), get_config_file_path(&theme_path), - palette, + load_palette(&*session.config.color_palette), )?, wgui_theme: Rc::new(theme), dbus, diff --git a/wayvr/src/windowing/backend.rs b/wayvr/src/windowing/backend.rs index f9bf7651..0ca522ba 100644 --- a/wayvr/src/windowing/backend.rs +++ b/wayvr/src/windowing/backend.rs @@ -130,6 +130,7 @@ pub enum OverlayEventData { }, WvrCommand(WvrCommand), ResizeRequest([u32; 2]), + ColorPaletteRefresh, } pub trait OverlayBackend: Any { diff --git a/wayvr/src/windowing/manager.rs b/wayvr/src/windowing/manager.rs index 02278935..596409bb 100644 --- a/wayvr/src/windowing/manager.rs +++ b/wayvr/src/windowing/manager.rs @@ -333,6 +333,20 @@ where self.overlays_changed(app)?; self.sets_changed(app); } + OverlayTask::GlobalChange(GlobalChange::ColorPalette) => { + { + let mut globals = app.wgui_globals.get(); + globals.palette = + wlx_common::palette::load_palette(&app.session.config.color_palette); + } + + for o in self.overlays.values_mut() { + let _ = o + .config + .backend + .notify(app, OverlayEventData::ColorPaletteRefresh); + } + } OverlayTask::CleanupMirrors => { let mut ids_to_remove = vec![]; for (oid, o) in &self.overlays { diff --git a/wgui/src/layout.rs b/wgui/src/layout.rs index 8984261c..b57cea30 100644 --- a/wgui/src/layout.rs +++ b/wgui/src/layout.rs @@ -155,6 +155,7 @@ pub enum LayoutTask { PlaySound(WguiSoundType), Dispatch(LayoutDispatchFunc), SetFocus(ComponentWeak), + RefreshPalette, Unfocus, } @@ -748,6 +749,10 @@ impl Layout { let mut tasks = self.tasks.drain(); while let Some(task) = tasks.pop_front() { match task { + LayoutTask::RefreshPalette => { + let root = self.tree_root_widget; + LayoutState::refresh_palette_recur(&mut self.common(), root); + } LayoutTask::RemoveWidget(widget_id) => { self.remove_widget(widget_id); } @@ -1028,4 +1033,27 @@ impl LayoutState { // safety: we just checked the type unsafe { Ok(Rc::from_raw(Rc::into_raw(component.0).cast())) } } + + fn refresh_palette_recur(common: &mut CallbackDataCommon, widget_id: WidgetID) { + if let Some(widget) = common.state.widgets.get(widget_id) { + widget.state().obj.palette_updated(common); + } else { + debug_assert!(false); + return; + } + + let Some(node_id) = common.state.nodes.get(widget_id) else { + /* node/widget desync, this shouldn't happen */ + debug_assert!(false); + return; + }; + + for child_node_id in common.state.tree.child_ids(*node_id) { + let Some(widget_id) = common.state.tree.get_node_context(child_node_id) else { + debug_assert!(false); + continue; + }; + LayoutState::refresh_palette_recur(common, *widget_id); + } + } } diff --git a/wgui/src/palette.rs b/wgui/src/palette.rs index ddd8b339..8490e5e3 100644 --- a/wgui/src/palette.rs +++ b/wgui/src/palette.rs @@ -22,7 +22,7 @@ impl WguiColorPalette { } log::warn!("No color palette with name '{palette_name}', using default colors."); - return DEFAULT.clone(); + DEFAULT.clone() } pub const fn from_inner(colors: [drawing::Color; WguiColorName::COUNT]) -> Self { diff --git a/wgui/src/widget/label.rs b/wgui/src/widget/label.rs index 834c6f9e..43474aca 100644 --- a/wgui/src/widget/label.rs +++ b/wgui/src/widget/label.rs @@ -129,11 +129,11 @@ impl WidgetLabel { } } - pub fn get_color(&self) -> WguiColor { + pub const fn get_color(&self) -> WguiColor { self.params.style.color.unwrap() // create_ex populates this } - pub fn parent_color(&self) -> ParentColor { + pub const fn parent_color(&self) -> ParentColor { self.params.parent_color } } @@ -188,6 +188,11 @@ impl WidgetObj for WidgetLabel { }) } + fn palette_updated(&mut self, common: &mut CallbackDataCommon) { + let cur_color = self.get_color(); + self.set_color(common, cur_color, true); + } + fn get_id(&self) -> WidgetID { self.id } diff --git a/wgui/src/widget/mod.rs b/wgui/src/widget/mod.rs index 3236cff6..d00e172d 100644 --- a/wgui/src/widget/mod.rs +++ b/wgui/src/widget/mod.rs @@ -191,6 +191,8 @@ pub trait WidgetObj: AnyTrait { fn draw(&mut self, state: &mut DrawState, params: &DrawParams); + fn palette_updated(&mut self, _common: &mut CallbackDataCommon) {} + fn measure( &mut self, _globals: &Globals, diff --git a/wlx-common/src/dash_interface.rs b/wlx-common/src/dash_interface.rs index 8c63345b..420931a4 100644 --- a/wlx-common/src/dash_interface.rs +++ b/wlx-common/src/dash_interface.rs @@ -84,7 +84,7 @@ pub trait DashInterface { pub enum ConfigChangeKind { OverlayConfig, EnvironmentBlend, - WguiThemeChange, // TODO: does not do anything right now + WguiColorPaletteChange, WvrServerConfig, /// Marks the config for saving but doesn't notify any components #[default]