diff --git a/crates/ui-egui/src/editing/save.rs b/crates/ui-egui/src/editing/save.rs index 855c2faea9..e3e9b108d6 100644 --- a/crates/ui-egui/src/editing/save.rs +++ b/crates/ui-egui/src/editing/save.rs @@ -77,9 +77,11 @@ impl PdfCraftApp { let dialog = in_document_folder(dialog, doc_path.as_deref()); // The bytes are taken once the user has chosen, so edits made meanwhile are saved too. self.ask_one(crate::pickers::Ask::Save(dialog), None, move |app, dest| { - // An Undo past saved redactions while the dialog was open makes the name - // it proposed wrong: ask again with the name for the restored content. - if !unredacted && let Some(index) = app.views.iter().position(|v| v.id == id && restores_saved_redactions(v)) { + // An Apply redactions or an Undo of one while the dialog was open makes the + // name it proposed wrong: ask again with the name for the current content. + let asked = (redacted, unredacted); + let changed = |v: &crate::DocView| v.id == id && (v.redactions_applied > 0, restores_saved_redactions(v)) != asked; + if let Some(index) = app.views.iter().position(changed) { app.save_then(index, SaveTarget::As, after); return; } diff --git a/crates/ui-egui/tests/it/redact.rs b/crates/ui-egui/tests/it/redact.rs index 62611f9001..ccb3a267ef 100644 --- a/crates/ui-egui/tests/it/redact.rs +++ b/crates/ui-egui/tests/it/redact.rs @@ -361,6 +361,45 @@ fn undoing_saved_redactions_while_the_save_dialog_is_open_asks_again() { let _ = std::fs::remove_dir_all(&dir); } +/// Undo of Apply redactions while the Save dialog that proposed the `_Redacted` name is open +/// makes Save ask again, so the unredacted content is not saved under that name. +#[test] +fn undoing_apply_redactions_while_the_save_dialog_is_open_asks_again() { + let dir = std::env::temp_dir().join(format!("pdfcraft-redacted-dialog-unapply-{}", std::process::id())); + let _ = std::fs::remove_dir_all(&dir); + std::fs::create_dir_all(&dir).unwrap(); + let original = dir.join("contract.pdf"); + std::fs::write(&original, include_bytes!("../data/form.pdf")).unwrap(); + let path = original.to_string_lossy().into_owned(); + let mut h = Harness::builder().with_size(egui::vec2(1400.0, 900.0)).build_eframe(move |_cc| { + let mut app = PdfCraftApp::new(); + app.set_option("language", "en").unwrap(); + app.open_path(&path); + app + }); + crate::support::settle(&mut h); + h.state_mut().execute("redact.pages"); + h.run_steps(2); + h.get_by_label("OK").click(); + h.run_steps(3); + assert!(h.state_mut().execute("redact.apply")); + h.run_steps(2); + h.get_by_label("Apply").click(); + h.run_steps(4); + let copy = dir.join("contract_Redacted.pdf"); + h.state_mut().pick_override = Some(vec![copy.to_string_lossy().into_owned()]); + assert!(!h.state_mut().save_active(SaveTarget::InPlace)); + h.state_mut().execute("edit.undo"); + assert_eq!(h.state().views[0].redactions_applied, 0); + let elsewhere = dir.join("contract_copy.pdf"); + h.state_mut().pick_override = Some(vec![elsewhere.to_string_lossy().into_owned()]); + h.run_steps(4); + h.state_mut().pick_override = None; + assert!(!copy.exists(), "the unredacted content is not saved under the _Redacted name"); + assert!(elsewhere.exists(), "Save asked again and wrote where the user chose"); + let _ = std::fs::remove_dir_all(&dir); +} + /// Undo of Apply redactions brings back Save in place; Redo makes Save ask where again. #[test] fn undoing_apply_redactions_saves_in_place_again() {