An unwrapped title carried a long file name past the viewport: egui's Modal sizes to its content, so the centered panel grew to the name's full width, clipped its own message and pushed Save/Cancel off-screen (reported on Windows, reproduced everywhere). Wrap the title to the dialog width in the save prompt and the password prompt, and pin the title and all three buttons inside a 1365x719 screen in a regression test. Co-authored-by: Mawfyy <mawfy12@gmail.com> Co-authored-by: Brandon Thomas <echelon@gmail.com>
This commit is contained in:
parent
607d3d1c0e
commit
0bbba8cafa
|
|
@ -130,6 +130,7 @@ Newest first. One line per session: the date, what moved, and the new overall pe
|
|||
- **2026-10-07 (community, #190):** Create PDF from Images offers embedded resolution, 72 DPI, or custom DPI (1–1200) without resampling. The engine and doc_create share the choice; Windows image context menus open the chooser through --create-images. Overall estimate unchanged (about 30–35%).
|
||||
|
||||
- **2026-10-08 (community):** Cut and stack in Print > Multiple: single-sided n-up sheets can be cut into cell piles and restacked in selected page order, with aligned gutter marks and blanks kept in their cells. Available through doc_print; duplex is refused. Grid-size overflow returns an error. No change to the parity count or the overall estimate (about 30–35%).
|
||||
- **2026-10-07 (community, #161):** The "Save changes?" prompt keeps a long file name inside the modal: the title wraps to the dialog width, so the centered panel no longer stretches past the viewport, clips its message and pushes Save/Cancel off-screen (Windows report). The password prompt's file-name line wraps the same way, and a regression test pins the title and all three buttons inside a 1365×719 screen. Parity counts unchanged; ≈ 30–35%.
|
||||
- **2026-10-07 (community, #143):** Windows MSI gets a full-UI welcome dialog with a "Create a desktop shortcut" checkbox (on by default; `INSTALLDESKTOPSHORTCUT=0` for unattended installs), progress, files in use, repair/remove, and a "Setup completed successfully" screen with Finish (plus distinct failed/cancelled screens). Start Menu and desktop shortcuts are now plain links to `pdfcraft.exe` instead of advertised MSI shortcuts. Packaging checks the compiled MSI's shortcut, checkbox and dialog tables; the ARM64 smoke test checks both links' targets, their removal on uninstall, and the opt-out. Installer polish only; feature counts unchanged. ≈ 30–35%.
|
||||
- **2026-10-07 (localization):** The interface translates through the same system as PhotoCraft: one TSV catalog per language (`crates/ui-egui/src/i18n/ja.tsv`), the `tl!` macro, entries keyed by command id or with plural forms, and catalog tests (format, duplicates, placeholders, command ids). Catalogs are validated strictly (unknown escapes, reserved contexts, placeholders, ellipses, plural forms), a bad line is skipped and logged at run time, `fmt` substitutes in one pass, the drawing language is per thread, and each `.tsv` is an attributed asset (`kind = "translation"`, checked by `cargo xtask assets`); validation, attribution and the language-switch control test folded in from #175. The 49 existing Japanese strings moved over unchanged, plus `Auto`. The `language` preference now defaults to `auto` (follow the system language; English when it has no catalog); `en`/`ja` still persist, and unknown values are rejected. Not covered: dialogs and panels, Windows system-language detection. ≈ 30–35% (unchanged).
|
||||
- **2026-10-07 (session 16):** PrintCraft is renamed PdfCraft: repo `storytold/pdfcraft`, crates and binaries `pdfcraft*`, bundle id `ai.storyteller.pdfcraft`. On first launch the app moves the old PrintCraft settings and crash-recovery folders to the new name, so upgrades keep recent files, preferences and unsaved work. No feature change. ≈ 30–35%.
|
||||
|
|
|
|||
|
|
@ -1336,9 +1336,12 @@ fn save_prompt(app: &mut PdfCraftApp, ctx: &egui::Context) {
|
|||
ui.set_width(420.0);
|
||||
ui.horizontal(|ui| {
|
||||
ui.add(crate::icons::image("save", 22.0, t.accent));
|
||||
ui.label(
|
||||
egui::RichText::new(crate::i18n::fmt(tl!("Save changes to “{name}” before closing?"), &[("name", &name)]))
|
||||
.font(theme::semibold(16.0)),
|
||||
ui.add(
|
||||
egui::Label::new(
|
||||
egui::RichText::new(crate::i18n::fmt(tl!("Save changes to “{name}” before closing?"), &[("name", &name)]))
|
||||
.font(theme::semibold(16.0)),
|
||||
)
|
||||
.wrap(),
|
||||
);
|
||||
});
|
||||
ui.add_space(6.0);
|
||||
|
|
@ -1437,7 +1440,7 @@ fn password(app: &mut PdfCraftApp, ctx: &egui::Context) {
|
|||
ui.label(egui::RichText::new(tl!("Password required")).font(theme::semibold(17.0)));
|
||||
});
|
||||
ui.add_space(6.0);
|
||||
ui.label(crate::i18n::fmt(tl!("“{name}” is protected. Enter a password to open it."), &[("name", &prompt.name)]));
|
||||
ui.add(egui::Label::new(crate::i18n::fmt(tl!("“{name}” is protected. Enter a password to open it."), &[("name", &prompt.name)])).wrap());
|
||||
ui.add_space(8.0);
|
||||
let r = ui.add(egui::TextEdit::singleline(&mut prompt.input).password(true).hint_text(tl!("Password")).desired_width(f32::INFINITY));
|
||||
// Enter submits. The field keeps focus (we request it every frame), so check the key
|
||||
|
|
|
|||
|
|
@ -387,6 +387,30 @@ fn quitting_with_unsaved_changes_asks_for_each_document() {
|
|||
assert!(h.state().close_request.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn save_prompt_stays_inside_the_screen_for_a_long_filename() {
|
||||
// Issue #161: an unwrapped title carrying a long filename widened the centered modal past
|
||||
// the viewport, clipping the message and pushing the Save/Cancel buttons off-screen.
|
||||
let name = "Psychology_ The Science of Mind and Behaviour, -- Nigel Holt, Andy Bremner, Michael \
|
||||
Vliek, Ed Sutherland, -- 5, 2024 -- McGraw-Hill Education (UK) Ltd -- isbn13 97815268.pdf";
|
||||
let mut h = Harness::builder().with_size(egui::vec2(1365.0, 719.0)).build_eframe(move |_cc| {
|
||||
let mut app = PdfCraftApp::new();
|
||||
app.open_bytes(name, None, fixture(1)).expect("fixture opens");
|
||||
app.close_request = Some(CloseRequest::Tab(0));
|
||||
app
|
||||
});
|
||||
h.run_steps(4);
|
||||
let screen = egui::Rect::from_min_size(egui::Pos2::ZERO, egui::vec2(1365.0, 719.0));
|
||||
let inside = |r: egui::Rect| screen.contains(r.min) && screen.contains(r.max);
|
||||
let title = h.get_by_label_contains("Save changes to");
|
||||
let title_rect = title.rect();
|
||||
assert!(inside(title_rect), "the title rect {title_rect:?} leaves the screen");
|
||||
for button in ["Save", "Cancel", "Don't save"] {
|
||||
let rect = h.get_by_label(button).rect();
|
||||
assert!(inside(rect), "the {button} button rect {rect:?} leaves the screen");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn document_properties_edit_is_one_undoable_step() {
|
||||
let mut h = harness(1, |app| app.set_option("dialog", "properties").unwrap());
|
||||
|
|
|
|||
|
|
@ -574,7 +574,7 @@ milestone = "M4"
|
|||
status = "shipped"
|
||||
commands = ["file.close"]
|
||||
tools = ["doc_close"]
|
||||
evidence = ["crates/ui-egui/tests/editing.rs::closing_a_dirty_tab_asks_and_cancel_keeps_it", "crates/ui-egui/tests/editing.rs::closing_a_dirty_tab_can_save_first", "crates/ui-egui/tests/editing.rs::quitting_with_unsaved_changes_asks_for_each_document"]
|
||||
evidence = ["crates/ui-egui/tests/editing.rs::closing_a_dirty_tab_asks_and_cancel_keeps_it", "crates/ui-egui/tests/editing.rs::closing_a_dirty_tab_can_save_first", "crates/ui-egui/tests/editing.rs::quitting_with_unsaved_changes_asks_for_each_document", "crates/ui-egui/tests/editing.rs::save_prompt_stays_inside_the_screen_for_a_long_filename"]
|
||||
notes = ""
|
||||
|
||||
[[feature]]
|
||||
|
|
|
|||
Loading…
Reference in New Issue