Record a duplicate's inPlace only when a copy is an artboard

Alt-drag, Cmd+Opt-drag and Free Transform on a copy duplicate with
`inPlace: true` for every layer, but the flag only changes anything for
an artboard. With in-place duplicates now refused on strict .atn export,
a recorded copy of a plain layer could no longer be exported, although a
plain Duplicate replays it exactly. Recording now drops `inPlace` when no
copy is an artboard, as `layer.select` already rewrites its recorded
params.

Refs #7200

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Kushagra Saxena
2026-10-19 21:17:40 +05:30
co-authored by Claude Opus 5.5
parent 2401039887
commit aa54979583
3 changed files with 56 additions and 2 deletions
+37
View File
@@ -1025,6 +1025,43 @@ mod tests {
}
}
/// An Alt-drag copy records `inPlace` (#7200), which only matters for an artboard: a plain
/// layer's recorded copy must still export to .atn, while an artboard's must be refused rather
/// than exported as a copy beside the original.
#[test]
fn recorded_in_place_duplicate_keeps_in_place_only_for_artboards() {
let mut s = Session::new();
s.execute("file.new", json!({"width": 8, "height": 8})).unwrap();
s.execute("actions.record", json!({"name": "Layer copy"})).unwrap();
s.execute("layer.duplicate", json!({"inPlace": true})).unwrap();
s.execute("actions.stop", json!({})).unwrap();
s.execute("layer.new.artboard", json!({"name": "Board", "rect": [0, 0, 8, 8]})).unwrap();
s.execute("actions.record", json!({"name": "Board copy"})).unwrap();
s.execute("layer.duplicate", json!({"inPlace": true})).unwrap();
s.execute("actions.stop", json!({})).unwrap();
assert_eq!(s.actions.list[0].steps, vec![("layer.duplicate".to_string(), json!({}))]);
assert_eq!(s.actions.list[1].steps, vec![("layer.duplicate".to_string(), json!({"inPlace": true}))]);
assert!(crate::atn_cmds::export("Audit", &[&s.actions.list[0]], &[], false).is_ok());
assert!(crate::atn_cmds::export("Audit", &[&s.actions.list[1]], &[], false).is_err());
// Several selected layers are copied together: one artboard among them keeps `inPlace`.
let mut s = Session::new();
s.execute("file.new", json!({"width": 8, "height": 8})).unwrap();
let photo = s.active().unwrap().active_layer.unwrap();
s.execute("layer.new.layer", json!({"name": "Logo"})).unwrap();
s.execute("layer.select", json!({"layer": photo.0, "mode": "add"})).unwrap();
s.execute("actions.record", json!({"name": "Layers copy"})).unwrap();
s.execute("layer.duplicate", json!({"inPlace": true})).unwrap();
s.execute("actions.stop", json!({})).unwrap();
assert_eq!(s.active().unwrap().selected_layers().len(), 2, "both layers were copied");
s.execute("layer.new.artboard", json!({"name": "Board", "rect": [0, 0, 8, 8]})).unwrap();
s.execute("layer.select", json!({"layer": photo.0, "mode": "add"})).unwrap();
s.execute("actions.record", json!({"name": "Mixed copy"})).unwrap();
s.execute("layer.duplicate", json!({"inPlace": true})).unwrap();
s.execute("actions.stop", json!({})).unwrap();
assert_eq!(s.actions.list[0].steps, vec![("layer.duplicate".to_string(), json!({}))]);
assert_eq!(s.actions.list[1].steps, vec![("layer.duplicate".to_string(), json!({"inPlace": true}))]);
}
#[test]
fn named_selection_preserves_modes_and_duplicate_occurrences() {
let mut s = Session::new();