From 795fb53c5d6b715ceb34f0860baf4904d0535b16 Mon Sep 17 00:00:00 2001 From: Max Abramowitz Date: Thu, 15 Oct 2026 12:57:11 -0400 Subject: [PATCH] M3: the community card on Home can be closed for the rest of the run The ArtCraft community card on Home gets a close button. Closing it hides the card until the next launch; the choice is deliberately not remembered, and the same links stay in the top bar's Discord button and the Help menu. A UI regression covers closing and the fresh-launch default. Co-Authored-By: Claude Opus 5.5 --- ROADMAP.md | 1 + crates/ui-egui/src/home.rs | 44 +++++++++++++++++++------------- crates/ui-egui/src/lib.rs | 3 +++ crates/ui-egui/tests/it/links.rs | 13 ++++++++++ 4 files changed, 43 insertions(+), 18 deletions(-) diff --git a/ROADMAP.md b/ROADMAP.md index bc057209c2..dfc89b4525 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -281,6 +281,7 @@ Ranked; detail and the full milestone table in [docs/roadmap.md](docs/roadmap.md - **2026-10-15 (M12, XFA, #2574):** A `pageArea` with no `` repeats without limit instead of taking a subform's default of one use, so a later page area with `occur max="1"` is no longer drawn (with a copy of its fields) over every body page. Synthetic regression test; the page area's `occur min` (a once-only page of its own) is still not laid out, recorded in `form.xfa-dynamic`. Estimates unchanged. - **2026-10-14 (M12, reading colours, #2059):** Pending page backgrounds use the document's reading colour immediately, preventing white flashes while scrolling to uncached pages. A headless canvas regression covers three pending pages in every preset and a custom background. Estimates unchanged. - **2026-10-15 (community, M6, #2608):** In Prepare a form the selected field moves with the arrow keys: a point per press, ten with Shift, as the object nudge and dragging it do. Each press is one undo step ("Change field properties"), and the keys no longer turn the page while a field is selected. Estimates unchanged. +- **2026-10-15 (M3, closable community card):** The ArtCraft community card on Home has a close button that hides it for the rest of the run; it returns on the next launch, and its links stay in the top bar's Discord button and the Help menu. A UI regression covers closing and the fresh-launch default. Estimates unchanged. - **2026-10-13 (community, M3, #1569 review):** Pixel-only Wayland wheel, wheel-tilt and continuous input use standalone moved events, so Ctrl zoom does not remain latched after the modifier is released (#991); vendored winit patch (13), with a policy test. Estimates unchanged. - **2026-10-15 (M14, #2383 candidate):** Device-limit requests now clamp unsupported maxima and minimum alignments before enabling the adapter's full 2D texture extent. This addresses the reported V3D request of 16 shader variables on an adapter supporting 15. Synthetic regressions fail before the clamp and pass afterward, along with the existing HiDPI case and Windows GPU-required application tests. Raspberry Pi startup remains unverified; milestone and overall estimates are unchanged. - **2026-10-12 (M6):** XFDF field import and data-file extraction join all text nodes in a value, preserving text after XML comments and processing instructions. Synthetic regressions cover Unicode, CDATA, empty values and PDF save/reopen. Estimates unchanged. diff --git a/crates/ui-egui/src/home.rs b/crates/ui-egui/src/home.rs index 3e70f34e42..ddd60f0bde 100644 --- a/crates/ui-egui/src/home.rs +++ b/crates/ui-egui/src/home.rs @@ -29,26 +29,34 @@ pub fn show(app: &mut PdfCraftApp, ui: &mut egui::Ui) { .font(theme::regular(14.0)), ); ui.add_space(14.0); - egui::Frame::NONE - .fill(t.card) - .stroke(Stroke::new(1.0, t.border)) - .corner_radius(CornerRadius::same(12)) - .inner_margin(egui::Margin::same(14)) - .show(ui, |ui| { - ui.set_width(ui.available_width()); - ui.horizontal(|ui| { - widgets::artcraft_mark(ui, 28.0); - ui.vertical(|ui| { - ui.label(egui::RichText::new(tl!("Join the ArtCraft community")).font(theme::semibold(15.0))); - ui.label(egui::RichText::new(tl!("Get help, share feedback and follow development on Discord.")).color(t.text_muted)); + if !app.community_card_closed { + egui::Frame::NONE + .fill(t.card) + .stroke(Stroke::new(1.0, t.border)) + .corner_radius(CornerRadius::same(12)) + .inner_margin(egui::Margin::same(14)) + .show(ui, |ui| { + ui.set_width(ui.available_width()); + ui.horizontal(|ui| { + widgets::artcraft_mark(ui, 28.0); + ui.vertical(|ui| { + ui.label(egui::RichText::new(tl!("Join the ArtCraft community")).font(theme::semibold(15.0))); + ui.label(egui::RichText::new(tl!("Get help, share feedback and follow development on Discord.")).color(t.text_muted)); + }); + // Closed for this run only: the card is back on the next launch. + ui.with_layout(egui::Layout::right_to_left(egui::Align::Min), |ui| { + if icons::button(ui, "x", 24.0, false, tl!("Close")).clicked() { + app.community_card_closed = true; + } + }); }); + ui.add_space(8.0); + if let Some(cmd) = widgets::community_links(ui) { + app.execute(cmd); + } }); - ui.add_space(8.0); - if let Some(cmd) = widgets::community_links(ui) { - app.execute(cmd); - } - }); - ui.add_space(22.0); + ui.add_space(22.0); + } egui::Frame::NONE .fill(t.card) diff --git a/crates/ui-egui/src/lib.rs b/crates/ui-egui/src/lib.rs index 64b22ff18e..5287858aa9 100644 --- a/crates/ui-egui/src/lib.rs +++ b/crates/ui-egui/src/lib.rs @@ -834,6 +834,8 @@ pub struct PdfCraftApp { pub replace_draft: Option, /// The last web link the app asked the system to open (tests and automation). pub last_opened_url: Option, + /// The home screen's community card was closed; it comes back next launch (not remembered). + pub community_card_closed: bool, /// A document asked to open this address; the user hasn't answered yet (#90, #91). pub pending_link: Option, /// A document just opened asks to be shown in Full Screen mode (`/PageMode /FullScreen`): @@ -1099,6 +1101,7 @@ impl PdfCraftApp { control: None, bookmark_rename: None, last_opened_url: None, + community_card_closed: false, pending_link: None, pending_full_screen: None, pending_remote_link: None, diff --git a/crates/ui-egui/tests/it/links.rs b/crates/ui-egui/tests/it/links.rs index b08036b11d..f08e9d4356 100644 --- a/crates/ui-egui/tests/it/links.rs +++ b/crates/ui-egui/tests/it/links.rs @@ -42,6 +42,19 @@ fn home_screen_links() { } } +#[test] +fn home_community_card_closes_for_this_run() { + let mut h = harness(|_| {}); + h.get_by_label("Join the ArtCraft community"); + h.get_by_label("Close").click(); + h.run_steps(2); + assert!(h.state().community_card_closed); + assert!(h.query_by_label("Join the ArtCraft community").is_none()); + assert!(h.query_by_label("Join our Discord").is_none()); + // Not remembered: a fresh app shows the card again. + assert!(!PdfCraftApp::new().community_card_closed); +} + #[test] fn about_dialog_shows_the_brand_and_links() { let pdf = b"%PDF-1.7\n1 0 obj << /Type /Catalog /Pages 2 0 R >> endobj\n2 0 obj << /Type /Pages /Kids [3 0 R] /Count 1 >> endobj\n3 0 obj << /Type /Page /Parent 2 0 R /MediaBox [0 0 200 200] >> endobj\ntrailer << /Root 1 0 R >>\n%%EOF";