From b0006d6af86ae9c6cd3c9ac616bc8c89e5df90d8 Mon Sep 17 00:00:00 2001 From: MarekSpodBiedry <73122968+MarekSpodBiedry@users.noreply.github.com> Date: Sat, 17 Oct 2026 07:46:18 +0200 Subject: [PATCH 1/2] About: Contributors and Models get their own fixed-size block below the tabs (#843) --- crates/ui-egui/src/dialogs.rs | 44 +++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/crates/ui-egui/src/dialogs.rs b/crates/ui-egui/src/dialogs.rs index 576a2297..c00a70ca 100644 --- a/crates/ui-egui/src/dialogs.rs +++ b/crates/ui-egui/src/dialogs.rs @@ -122,6 +122,21 @@ pub fn show(app: &mut SlideApp, ctx: &egui::Context) { } } +/// Room the About credits need for their table; the About tab keeps its compact size. +const CREDITS_SIZE: egui::Vec2 = vec2(640.0, 380.0); + +/// The Contributors / Models body in a block of its own fixed size, below the tab row. Sizing the +/// dialog's `ui` instead (`set_min_size` / `set_max_height`) squeezed the tab row and the first +/// credits row together, so the text was garbled and the tabs stopped answering (#843). +fn credits_block(ui: &mut Ui, models: bool) -> Rect { + ui.allocate_ui(CREDITS_SIZE, |ui| { + ui.set_min_size(CREDITS_SIZE); + if models { crate::credits::models_ui(ui) } else { crate::credits::contributors_ui(ui) } + }) + .response + .rect +} + fn buttons(ui: &mut Ui, ok_label: &str) -> (bool, bool) { let mut ok = false; let mut cancel = false; @@ -2078,10 +2093,7 @@ fn body(app: &mut SlideApp, ui: &mut Ui, d: &mut Dialog) -> bool { ui.separator(); match tab.as_str() { "contributors" | "models" => { - // The credits need room for the table; the About tab keeps its compact size. - ui.set_min_size(vec2(640.0, 380.0)); - ui.set_max_height(380.0); - if tab == "models" { crate::credits::models_ui(ui) } else { crate::credits::contributors_ui(ui) } + credits_block(ui, tab == "models"); } _ => about(app, ui), } @@ -3629,3 +3641,27 @@ mod spelling_tests; #[cfg(test)] #[path = "paragraph_dialog_tests.rs"] mod paragraph_dialog_tests; + +#[cfg(test)] +mod about_credits_tests { + use super::{CREDITS_SIZE, credits_block}; + + #[test] + fn credits_get_their_own_block_below_the_tab_row() { + for models in [false, true] { + let ctx = egui::Context::default(); + let mut tabs = egui::Rect::NOTHING; + let mut block = egui::Rect::NOTHING; + let mut whole = egui::Rect::NOTHING; + let _ = ctx.run_ui(egui::RawInput::default(), |ui| { + tabs = ui.label("About").rect; + block = credits_block(ui, models); + whole = ui.min_rect(); + }); + assert_eq!(block.size(), CREDITS_SIZE, "models={models}"); + assert!(block.min.y >= tabs.max.y, "the credits start below the tab row (models={models})"); + assert!(whole.max.y >= block.max.y, "the dialog grows to hold the block (models={models})"); + assert!(whole.height() > CREDITS_SIZE.y, "the tab row is not squeezed into the credits height (models={models})"); + } + } +} From 445e7c6b558a15a63a3d75de935a778215c0bc7f Mon Sep 17 00:00:00 2001 From: MarekSpodBiedry <73122968+MarekSpodBiedry@users.noreply.github.com> Date: Sun, 18 Oct 2026 18:39:06 +0200 Subject: [PATCH 2/2] About credits test: clear textures_delta, drive the real dialog tabs; ROADMAP progress-log row for #843 --- ROADMAP.md | 1 + crates/ui-egui/src/dialogs.rs | 36 +++++++++++++++++++++++++++++++++-- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/ROADMAP.md b/ROADMAP.md index 933bc7d1..def15e24 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -131,6 +131,7 @@ app's JSON control channel (`deckcraft --control PORT`). | Date | What landed | |---|---| +| 2026-10-18 | About: Contributors and Models get their own fixed-size block below the tab row, so the tab row is no longer squeezed into the credits and the tabs keep answering (#843) | | 2026-10-17 | Opening a file caps absurd effect sizes (glow, soft edges, shadows, reflections, on shapes, text and table text) at what Format Shape allows: a glow of 10^18 pt in a .pptx made rendering ask for 34 GB and abort | | 2026-10-17 | Opening a .deckcraft file whose shapes repeat an id gives the repeats fresh ids (groups, layouts and masters too), so the deck validates and edits by id find one shape | | 2026-10-17 | Edit Points: turning a shape into a freeform is one undo step, so Undo brings the original shape back (it used to stay a freeform) | diff --git a/crates/ui-egui/src/dialogs.rs b/crates/ui-egui/src/dialogs.rs index fa7d839f..42a194de 100644 --- a/crates/ui-egui/src/dialogs.rs +++ b/crates/ui-egui/src/dialogs.rs @@ -3699,7 +3699,38 @@ mod paragraph_dialog_tests; #[cfg(test)] mod about_credits_tests { - use super::{CREDITS_SIZE, credits_block}; + use egui_kittest::Harness; + use egui_kittest::kittest::Queryable; + + use super::{CREDITS_SIZE, Dialog, credits_block}; + use crate::{Services, SlideApp}; + + fn tab_of(h: &Harness<'_, SlideApp>) -> String { + let d = h.state().dialog.as_ref().expect("the About dialog is open"); + d.fields.get("tab").cloned().unwrap_or_else(|| "about".into()) + } + + /// The reported symptom (#843): in the real dialog the tabs stopped answering once Contributors + /// or Models was open. Click through Contributors, Models and back to About. + #[test] + fn about_dialog_tabs_keep_responding() { + let mut app = SlideApp::new(deckcraft_engine::Session::with_new(), Services::default()); + app.dialog = Some(Dialog::new("about")); + let mut h = Harness::builder().with_size(egui::vec2(1440.0, 900.0)).with_step_dt(1.0 / 60.0).build_ui_state( + |ui, app: &mut SlideApp| { + app.logic(ui.ctx()); + app.ui(ui); + }, + app, + ); + h.run_steps(4); + assert_eq!(tab_of(&h), "about"); + for label in ["Contributors", "Models", "About", "Models", "Contributors"] { + h.get_by_label(label).click(); + h.run_steps(3); + assert_eq!(tab_of(&h), label.to_lowercase(), "clicking {label} switches the tab"); + } + } #[test] fn credits_get_their_own_block_below_the_tab_row() { @@ -3708,11 +3739,12 @@ mod about_credits_tests { let mut tabs = egui::Rect::NOTHING; let mut block = egui::Rect::NOTHING; let mut whole = egui::Rect::NOTHING; - let _ = ctx.run_ui(egui::RawInput::default(), |ui| { + let mut out = ctx.run_ui(egui::RawInput::default(), |ui| { tabs = ui.label("About").rect; block = credits_block(ui, models); whole = ui.min_rect(); }); + out.textures_delta.clear(); assert_eq!(block.size(), CREDITS_SIZE, "models={models}"); assert!(block.min.y >= tabs.max.y, "the credits start below the tab row (models={models})"); assert!(whole.max.y >= block.max.y, "the dialog grows to hold the block (models={models})");