From e49bdc94dc989344f1d90845f349d66a8cc0b5d4 Mon Sep 17 00:00:00 2001 From: Osman Said <57035358+Umid0vic@users.noreply.github.com> Date: Mon, 12 Oct 2026 07:53:50 +0200 Subject: [PATCH] Fix header label overlap in narrow windows (#130) --- crates/ui-egui/src/views.rs | 19 ++++++++--- crates/ui-egui/tests/german.rs | 13 ++++++++ crates/ui-egui/tests/ui.rs | 60 ++++++++++++++++++++++++++++++++-- 3 files changed, 85 insertions(+), 7 deletions(-) diff --git a/crates/ui-egui/src/views.rs b/crates/ui-egui/src/views.rs index df665a1..17c6618 100644 --- a/crates/ui-egui/src/views.rs +++ b/crates/ui-egui/src/views.rs @@ -80,11 +80,6 @@ impl LauncherUi { let logo = vec2(14.0 * crate::icons::ARTCRAFT_LOGO_ASPECT, 14.0); let (cell, _) = ui.allocate_exact_size(vec2(logo.x + 40.0, h), Sense::hover()); egui::Image::new(crate::icons::artcraft_logo(t.dark)).alt_text(tl!("ArtCraft")).paint_at(ui, Rect::from_center_size(cell.center(), logo)); - widgets::rule(ui, h); - ui.add_space(16.0); - widgets::tag(ui, tl!("Launcher"), t.invert_bg, t.invert_fg); - ui.add_space(12.0); - widgets::hud(ui, tl!("Craft App Suite"), t.muted); ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| { if bar == TitleBar::Custom { widgets::window_buttons(ui, h); @@ -112,6 +107,20 @@ impl LauncherUi { } ui.add_space(6.0); widgets::rule(ui, h); + // The controls reserve their actual widths before the secondary text gets space. + ui.with_layout(egui::Layout::left_to_right(egui::Align::Center), |ui| { + let tag_width = + widgets::caps(ui, tl!("Launcher"), theme::HUD_SIZE, theme::mono_bold(), theme::HUD_SPACING, t.ink).size().x + 16.0; + if ui.available_width() >= 17.0 + tag_width { + widgets::rule(ui, h); + ui.add_space(16.0); + widgets::tag(ui, tl!("Launcher"), t.invert_bg, t.invert_fg); + } + if ui.available_width() >= 12.0 + widgets::hud_galley(ui, tl!("Craft App Suite"), t.muted).size().x { + ui.add_space(12.0); + widgets::hud(ui, tl!("Craft App Suite"), t.muted); + } + }); }); }); } diff --git a/crates/ui-egui/tests/german.rs b/crates/ui-egui/tests/german.rs index 3360498..eb80c39 100644 --- a/crates/ui-egui/tests/german.rs +++ b/crates/ui-egui/tests/german.rs @@ -184,4 +184,17 @@ fn german_switches_persists_and_keeps_install_actions() { let (mut web, _) = harness_language(ViewMode::Grid, egui::Theme::Dark, false, &restored.language); web.run_steps(6); assert!(web.query_all_by_label("Für macOS herunterladen").count() >= 3); + for width in [720.0, 800.0, 1180.0] { + web.set_size(egui::vec2(width, 900.0)); + web.run_steps(6); + for label in ["Grid", "Table", "Settings", "Check for updates"] { + let rect = web.get_by_label(artcraft_launcher_ui_egui::i18n::t(label)).rect(); + assert!(rect.left() >= 0.0 && rect.right() <= width, "{width}: {label} {rect:?}"); + for label in ["Launcher", "Craft App Suite"] { + if let Some(text) = web.query_by_label(label) { + assert!(!rect.intersects(text.rect()), "{width}: {label} overlaps {rect:?}"); + } + } + } + } } diff --git a/crates/ui-egui/tests/ui.rs b/crates/ui-egui/tests/ui.rs index f9a0ff4..bdd3958 100644 --- a/crates/ui-egui/tests/ui.rs +++ b/crates/ui-egui/tests/ui.rs @@ -123,6 +123,23 @@ fn harness_with( manage: bool, scale: f32, ) -> (Harness<'static, Option>, Rc>>) { + harness_with_title_bar(events, view, theme, manage, scale, artcraft_launcher_ui_egui::TitleBar::Native) +} + +fn harness_with_title_bar( + events: Vec, + view: ViewMode, + theme: egui::Theme, + manage: bool, + scale: f32, + bar: artcraft_launcher_ui_egui::TitleBar, +) -> (Harness<'static, Option>, Rc>>) { + struct HeaderHost(artcraft_launcher_ui_egui::TitleBar); + impl Host for HeaderHost { + fn title_bar(&self) -> artcraft_launcher_ui_egui::TitleBar { + self.0 + } + } // Integration tests compile without cfg!(test), so system_lang() picks up the // developer's locale. Force English so labels match the assertions. artcraft_launcher_ui_egui::i18n::set_test_lang(artcraft_launcher_ui_egui::i18n::Lang::EN); @@ -146,8 +163,8 @@ fn harness_with( *state = Some(LauncherUi::new(ui.ctx(), Box::new(b), s)); } if let Some(l) = state.as_mut() { - l.logic(&ui.ctx().clone(), &mut NoHost); - l.ui(ui, &mut NoHost); + l.logic(&ui.ctx().clone(), &mut HeaderHost(bar)); + l.ui(ui, &mut HeaderHost(bar)); } }, None, @@ -933,3 +950,42 @@ fn the_rate_limit_notice_never_runs_under_the_footer_links() { } } } + +#[test] +fn narrow_header_keeps_the_view_switch_clear_of_brand_text() { + use artcraft_launcher_ui_egui::TitleBar; + for theme in [egui::Theme::Dark, egui::Theme::Light] { + for bar in [TitleBar::Native, TitleBar::MacOs, TitleBar::Custom] { + let (mut h, _) = harness_with_title_bar(events(), ViewMode::Grid, theme, true, 1.0, bar); + for width in (720..=1180).step_by(10).chain([720, 1180]).map(|w| w as f32) { + h.set_size(egui::vec2(width, 900.0)); + h.run_steps(6); + for label in ["Grid", "Table", "Settings", "Check for updates"] { + let rect = h.get_by_label(label).rect(); + assert!(rect.left() >= 0.0 && rect.right() <= width, "{bar:?} {width}: {label} {rect:?}"); + for label in ["Launcher", "Craft App Suite"] { + if let Some(text) = h.query_by_label(label) { + assert!(!rect.intersects(text.rect()), "{bar:?} {width}: {label} overlaps {rect:?}"); + } + } + } + if bar == TitleBar::Custom { + for label in ["Minimize", "Maximize", "Close"] { + let rect = h.get_by_label(label).rect(); + assert!(rect.left() >= 0.0 && rect.right() <= width, "{width}: {label} {rect:?}"); + } + } + if width == 1180.0 { + h.get_by_label("Launcher"); + h.get_by_label("Craft App Suite"); + } + if [720.0, 800.0, 1180.0].contains(&width) { + snapshot(&mut h, &format!("header-{theme:?}-{bar:?}-{width}")); + } + } + h.get_by_label("Table").click(); + h.run_steps(2); + assert_eq!(h.state().as_ref().unwrap().settings.view, ViewMode::Table); + } + } +}