mirror of
https://github.com/storytold/photocraft.git
synced 2026-10-24 09:57:08 -06:00
fix(atn): keep a Save with a destination but no format
A recorded Save with an In path and no As format was still imported as a Save As going by the file extension alone. Without the format there's nothing to check the destination against, so keep it as a Photoshop step and let playback stop there.
This commit is contained in:
@@ -1571,32 +1571,26 @@ fn path_extension(path: &str) -> Option<String> {
|
||||
}
|
||||
|
||||
/// `save`: a plain Save, or a Save As (`As` format, `In` destination, `Cpy` As a Copy).
|
||||
/// Only a destination that is a file of the recorded format imports: a folder (#5430), an
|
||||
/// unknown format or a mismatched extension stays a kept Photoshop step, so playback stops
|
||||
/// Only a destination that is a file of the recorded format imports: a folder (#5430), a missing
|
||||
/// or unknown format or a mismatched extension stays a kept Photoshop step, so playback stops
|
||||
/// before writing rather than saving over the played file (#7102).
|
||||
fn save_from(d: &Descriptor) -> Mapped {
|
||||
let unsupported = Mapped::Unsupported { harmless: false };
|
||||
let dest = d.get("In ");
|
||||
let format = match d.get("As ") {
|
||||
None if dest.is_none() => return step("file.save", json!({})),
|
||||
None => None,
|
||||
// A format that isn't a descriptor can't be checked against the destination.
|
||||
Some(_) => match get_obj(d, "As ") {
|
||||
Some(f) => Some(f),
|
||||
None => return unsupported,
|
||||
},
|
||||
};
|
||||
let Some(path) = dest.and_then(path_text) else { return unsupported };
|
||||
if d.get("As ").is_none() && d.get("In ").is_none() {
|
||||
return step("file.save", json!({}));
|
||||
}
|
||||
// A Save As needs a format descriptor to check the destination against: without one (or
|
||||
// with a format that isn't a descriptor) the step is kept.
|
||||
let Some(format) = get_obj(d, "As ") else { return unsupported };
|
||||
let Some(path) = d.get("In ").and_then(path_text) else { return unsupported };
|
||||
if get_bool(d, "DIDr") == Some(true) {
|
||||
return unsupported;
|
||||
}
|
||||
let Some(ext) = path_extension(&path) else { return unsupported };
|
||||
if let Some(f) = format {
|
||||
let class = trimmed(&f.class_id);
|
||||
let Some((_, exts)) = SAVE_FORMATS.iter().find(|(c, _)| *c == class) else { return unsupported };
|
||||
if !exts.contains(&ext.as_str()) {
|
||||
return unsupported;
|
||||
}
|
||||
let class = trimmed(&format.class_id);
|
||||
let Some((_, exts)) = SAVE_FORMATS.iter().find(|(c, _)| *c == class) else { return unsupported };
|
||||
if !exts.contains(&ext.as_str()) {
|
||||
return unsupported;
|
||||
}
|
||||
step(if get_bool(d, "Cpy ") == Some(true) { "file.saveACopy" } else { "file.saveAs" }, json!({"path": path}))
|
||||
}
|
||||
|
||||
@@ -1455,10 +1455,12 @@ fn save_as_that_cannot_be_mapped_stops_playback_instead_of_saving_over_the_file(
|
||||
// A format that isn't a descriptor, with and without a destination.
|
||||
item("save", "Save", Some(desc("null").with("As ", long(1.0)))),
|
||||
item("save", "Save", Some(desc("null").with("As ", long(1.0)).with("In ", path_value("/out/result.png")))),
|
||||
// A destination with no format at all.
|
||||
item("save", "Save", Some(desc("null").with("In ", path_value("/out/result.png")))),
|
||||
]);
|
||||
let imp = import(&atn::write(&file).unwrap()).unwrap();
|
||||
let ids: Vec<&str> = imp.actions[0].steps.iter().map(|(id, _)| id.as_str()).collect();
|
||||
assert_eq!(ids, [PHOTOSHOP_STEP; 7]);
|
||||
assert_eq!(ids, [PHOTOSHOP_STEP; 8]);
|
||||
assert!(imp.actions[0].disabled.is_empty(), "kept saves stay on, so playback stops on them");
|
||||
// The kept steps are written back byte for byte.
|
||||
let a = &imp.actions[0];
|
||||
|
||||
Reference in New Issue
Block a user