Redact: Save writes in place once the web build delivered the redactions

In the web build Save kept sending Save As to the host after the redacted
file was delivered, because the delivered steps stay counted for the
_Redacted name. Save now asks where only for steps applied since the last
delivery.
This commit is contained in:
dotCooCoo
2026-10-30 22:04:03 -07:00
parent 0eceb8d2b2
commit ebafc30ed1
3 changed files with 38 additions and 3 deletions
+3 -2
View File
@@ -451,8 +451,9 @@ pub struct DocView {
/// Redact tool: the box being drawn, and a mark to add (page, quads) for the app to style.
pub redact_drag: crate::redact_ui::AreaDrag,
pub pending_redaction: Option<(usize, Vec<[f64; 8]>)>,
/// How many Apply redactions steps are in effect in this view. While it is above 0, Save asks
/// where and proposes the name with `_Redacted` ([`pdfcraft_engine::redacted_file_name`]).
/// How many Apply redactions steps are in effect in this view. While it is above 0, Save
/// proposes the name with `_Redacted` ([`pdfcraft_engine::redacted_file_name`]), and while it is
/// above `redactions_downloaded`, Save asks where.
/// Undo of an Apply redactions step takes one off and Redo adds it back. Reload and a desktop
/// save set it to 0, and Revert sets it to `redactions_downloaded`; after a desktop save the document has the name it was saved
/// under. A web download keeps it, so later downloads carry the `_Redacted` name.
+4 -1
View File
@@ -49,7 +49,10 @@ impl PdfCraftApp {
let Some(doc) = self.session.get(id) else { return false };
let (name, path) = (doc.name.clone(), doc.path.clone());
// After Apply redactions, Save asks where and proposes the name with `_Redacted`.
// In the web build a delivered step stays counted, so only the steps applied since the
// last delivery make Save ask where.
let redacted = self.views.get(index).is_some_and(|v| v.redactions_applied > 0);
let not_delivered = self.views.get(index).is_some_and(|v| v.redactions_applied > v.redactions_downloaded);
let name = if redacted { pdfcraft_engine::redacted_file_name(&name) } else { name };
// Undo past a saved Apply redactions brings back content that the file on disk has
// redacted: ask where instead of writing it over that file. In the web build a delivered
@@ -59,7 +62,7 @@ impl PdfCraftApp {
.views
.get(index)
.is_some_and(|v| v.redactions_undone_after_save > 0 || v.saved_redactions_cut_off || v.redactions_applied < v.redactions_downloaded);
let target = if redacted || unredacted { SaveTarget::As } else { target };
let target = if not_delivered || unredacted { SaveTarget::As } else { target };
#[cfg(not(target_arch = "wasm32"))]
{
let doc_path = path.clone();
+31
View File
@@ -280,6 +280,37 @@ fn undoing_delivered_redactions_asks_where() {
let _ = std::fs::remove_dir_all(&dir);
}
/// Once every Apply redactions step is delivered, Save writes in place again even though the web
/// build keeps the steps counted for the `_Redacted` name.
#[test]
fn delivered_redactions_save_in_place() {
let dir = std::env::temp_dir().join(format!("pdfcraft-redacted-delivered-save-{}", 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);
// The state a web save leaves: the step is delivered and stays counted.
h.state_mut().views[0].redactions_downloaded = 1;
assert!(h.state_mut().save_active(SaveTarget::InPlace), "Save writes in place after the step is delivered");
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() {