Edit: duplicating during a text edit ends the edit (#2226)

Edit > Duplicate replaces the layer selection with the copies, but an
open in-canvas text edit stayed on the original layer: typing kept
editing a layer that was no longer selected. When the duplicate leaves
the edited layer deselected, end the edit the way #2096's Deselect All
does (text_edit::end_edit), in the command every caller — menu, shortcut,
MCP — dispatches through.

Co-Authored-By: GLM-5.3-Flash <noreply@z.ai>
This commit is contained in:
SusieeTheFemboyandGLM-5.3-Flash committed 2026-10-29 05:22:56 +01:00
1 parent 990fa668cd
commit 60a356ea14
2 files changed
+19

No files matched your search

+5
View File
@@ -146,6 +146,11 @@ fn duplicate(s: &mut Session, p: &Value) -> Result<Value> {
st.selected_layers = created.clone();
Ok(created)
})?;
// Duplicating selects the copies, so an open text edit on a now-deselected layer ends
// (#2226): typing must not keep editing an unselected layer.
if s.state.text_edit.as_ref().is_some_and(|e| !s.state.selected_layers.contains(&e.layer)) {
super::text_edit::end_edit(s, &Value::Null)?;
}
Ok(json!(new.iter().map(|l| l.0).collect::<Vec<_>>()))
}
+14
View File
@@ -199,6 +199,20 @@ fn typing_deleting_and_caret_movement() {
assert!(s.state.text_edit.is_none());
}
/// Duplicating during a text edit moves the selection to the copy: the edit on the original ends
/// (#2226), as in After Effects — typing must not keep editing an unselected layer.
#[test]
fn duplicate_during_a_text_edit_ends_the_edit() {
let (mut s, t) = session("Hello");
s.execute("text.edit", json!({"layer": t, "caret": 5})).unwrap();
let copy = s.execute("edit.duplicate", json!({"layers": [t]})).unwrap()[0].as_u64().unwrap();
assert_ne!(copy, t, "the duplicate is created");
assert_eq!(s.state.selected_layers, vec![effectcraft_project::LayerId(copy)], "the copy is selected");
assert!(s.state.text_edit.is_none(), "the edit ended with the selection move (#2226)");
assert_eq!(doc(&s, t).text, "Hello", "the original keeps its text");
assert_eq!(doc(&s, copy).text, "Hello", "and the copy carries it");
}
#[test]
fn caret_style_applies_to_the_next_typed_text() {
let (mut s, t) = session("ab");