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()) }