From 37211078c2bf08592cbe075f0e1b1e32adb1eb11 Mon Sep 17 00:00:00 2001 From: dotCooCoo Date: Sat, 31 Oct 2026 00:32:58 -0700 Subject: [PATCH] Fix #4837: the saved color scheme, accent and canvas color show at launch The first UI pass installed the default theme over the one the saved preferences had applied earlier in the same frame, and later frames saw the preferences as already applied. Classic, a non-default accent and a Canvas Color showed as the defaults until a preference changed, and again after the app took a new graphics context. The first pass now applies the saved preferences. --- crates/ui-egui/src/app.rs | 3 ++- crates/ui-egui/src/prefs_dialog.rs | 14 +++++++++++++- crates/ui-egui/src/prefs_dialog/tests.rs | 19 +++++++++++++++++++ 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/crates/ui-egui/src/app.rs b/crates/ui-egui/src/app.rs index 923459f89..13d5a00d8 100644 --- a/crates/ui-egui/src/app.rs +++ b/crates/ui-egui/src/app.rs @@ -400,7 +400,8 @@ impl VectorcraftApp { crate::ime::install_hooks(ctx); self.adopt_context(ctx); if !self.styled { - theme::apply(ctx, self.ui.brightness); + // The saved accent, color scheme and canvas color, not the defaults (#4837). + prefs_dialog::reapply(self, ctx); egui_extras::install_image_loaders(ctx); self.styled = true; } diff --git a/crates/ui-egui/src/prefs_dialog.rs b/crates/ui-egui/src/prefs_dialog.rs index d638e0b26..b91c149f4 100644 --- a/crates/ui-egui/src/prefs_dialog.rs +++ b/crates/ui-egui/src/prefs_dialog.rs @@ -125,7 +125,7 @@ pub fn apply_runtime(app: &mut VectorcraftApp, ctx: &egui::Context) { scrub: p.scrub_numeric_fields, bare_points: p.numbers_without_units_are_points, }; - let id = egui::Id::unique("dc-applied-prefs"); + let id = applied_id(); let prev: Option = ctx.data(|d| d.get_temp::>(id)).flatten(); if prev != Some(want) { theme::apply_with(ctx, want.brightness, want.accent, want.scheme); @@ -160,6 +160,18 @@ pub fn apply_runtime(app: &mut VectorcraftApp, ctx: &egui::Context) { } } +/// Where [`apply_runtime`] keeps the preferences it last pushed into `ctx`. +fn applied_id() -> egui::Id { + egui::Id::unique("dc-applied-prefs") +} + +/// [`apply_runtime`] with nothing recorded as applied, so the theme (brightness, accent, color +/// scheme and canvas color) and the other UI-side preferences are pushed into `ctx` again. +pub(crate) fn reapply(app: &mut VectorcraftApp, ctx: &egui::Context) { + ctx.data_mut(|d| d.remove::>(applied_id())); + apply_runtime(app, ctx); +} + pub fn show(app: &mut VectorcraftApp, ctx: &egui::Context) { let Some(mut d) = app.ui.dialog.clone() else { return }; let t = Tokens::get(ctx); diff --git a/crates/ui-egui/src/prefs_dialog/tests.rs b/crates/ui-egui/src/prefs_dialog/tests.rs index c433fbc02..80fb23a17 100644 --- a/crates/ui-egui/src/prefs_dialog/tests.rs +++ b/crates/ui-egui/src/prefs_dialog/tests.rs @@ -60,6 +60,25 @@ fn canvas_color_choices_paint_the_pasteboard() { assert!(app.run("prefs.set", serde_json::json!({"key": "canvasColor", "value": "pink"})).is_err()); } +/// #4837: the saved Color Scheme, Accent and Canvas Color are the ones the first frame shows, not +/// the defaults the first UI pass installs. +#[test] +fn saved_scheme_accent_and_canvas_color_show_from_the_first_frame() { + let mut app = app(); + for (key, value) in [("uiColorScheme", "classic"), ("uiAccent", "pink"), ("canvasColor", "white")] { + app.run("prefs.set", json!({"key": key, "value": value})).unwrap(); + } + let ctx = egui::Context::default(); + for _ in 0..2 { + let mut out = ctx.run_ui(egui::RawInput::default(), |ui| app.logic(ui.ctx())); + out.textures_delta.clear(); + let (t, classic) = (Tokens::get(&ctx), Tokens::for_scheme(Scheme::Classic, app.ui.brightness, Accent::Pink)); + assert_eq!((t.accent, t.app_bar, t.panel), (classic.accent, classic.app_bar, classic.panel)); + assert_eq!(t.pasteboard, egui::Color32::WHITE); + assert_eq!(ctx.global_style().visuals.hyperlink_color, classic.accent); + } +} + fn app() -> VectorcraftApp { VectorcraftApp::new(Session::new(), Services::default()) }