diff --git a/crates/engine/src/file_cmds.rs b/crates/engine/src/file_cmds.rs index 5e9f7455c8..7470e78231 100644 --- a/crates/engine/src/file_cmds.rs +++ b/crates/engine/src/file_cmds.rs @@ -988,7 +988,7 @@ fn batch(s: &mut Session, p: &Value) -> Result { // Each result goes to the destination folder, which overrides the action's recorded Save / // Save As steps (Photoshop's "Override Action 'Save As' Commands"). Recorded view steps // (zoom, fit) don't change the output, so they are skipped (#2752). - steps.retain(|(id, _)| !crate::actions_cmds::shell_save_command(id) && !crate::actions_cmds::shell_view_command(id)); + steps.retain(|(id, _)| !crate::actions_cmds::shell_save_command(id) && !crate::actions_cmds::shell_view_command(id) && id != "file.export.quickExport"); if let Some((id, _)) = steps.iter().find(|(id, _)| crate::commands::find(id).is_none()) { return Err(EngineError::BadParams { cmd: cmd.into(), msg: format!("unknown command `{id}` in the action") }); } diff --git a/crates/engine/src/file_cmds/tests.rs b/crates/engine/src/file_cmds/tests.rs index fdfcf6c4b5..73c09020a5 100644 --- a/crates/engine/src/file_cmds/tests.rs +++ b/crates/engine/src/file_cmds/tests.rs @@ -756,6 +756,18 @@ fn load_files_into_stack_and_image_processor_and_batch() { let inv = photocraft_io::import("a.png", &std::fs::read(join(&out, "a.png")).unwrap()).unwrap().document; let px = photocraft_compose::render(&inv, Rect::new(1, 1, 2, 2)).px[0]; assert!(px[0] < 0.01 && px[1] > 0.99 && px[2] > 0.99, "red inverted to cyan: {px:?}"); + // A recorded Quick Export writes to the current document path, but Batch owns + // the destination. Replaying it would fail for scratch documents with no save path. + let quick_out = join(&dir, "batch-with-quick-export"); + let r = s + .execute( + "file.automate.batch", + json!({"steps": [["image.adjustments.invert", {}], ["file.export.quickExport", {}]], "input": input, "output": quick_out, "format": "png"}), + ) + .unwrap(); + assert_eq!(r["files"].as_array().unwrap().len(), 2, "{r}"); + assert!(r["errors"].as_array().unwrap().is_empty(), "{r}"); + assert!(std::path::Path::new(&join(&quick_out, "a.png")).is_file()); assert!(s.execute("file.automate.batch", json!({"steps": [["no.such.command", {}]], "input": input, "output": out})).is_err()); }