diff --git a/crates/engine/src/lib.rs b/crates/engine/src/lib.rs index c3f645cc..d96717a1 100644 --- a/crates/engine/src/lib.rs +++ b/crates/engine/src/lib.rs @@ -682,7 +682,28 @@ impl Session { self.journal.drain(..1000); } } - Ok(r) + Ok(if outer { self.with_editing(id, r) } else { r }) + } + + /// In Slide Master / layout (or handout / notes master) view the insert commands edit the + /// master or layout, not a slide; their answer says so with `editing: {kind, name}`, as + /// `slide.inspect` does. Nothing is added on slides, so those answers stay as they were. + fn with_editing(&self, id: &str, mut r: Value) -> Value { + let inserts = id.starts_with("insert.") || matches!(id, "shape.insert" | "shape.freeform" | "shape.connect" | "slide.new"); + let (true, Some(st), Some(o)) = (inserts, self.active(), r.as_object_mut()) else { return r }; + let doc = &st.doc; + let edited = match st.selection.target { + Target::Master { master } => doc.masters.get(master).map(|m| ("master", m.name.clone())), + Target::Layout { master, layout } => doc.masters.get(master).and_then(|m| m.layouts.get(layout)).map(|l| ("layout", l.name.clone())), + t @ (Target::Handout | Target::NotesMaster) => { + page_master(doc, t).map(|m| (if matches!(t, Target::Handout) { "handout" } else { "notesMaster" }, m.name.clone())) + } + Target::Slides => None, + }; + if let Some((kind, name)) = edited { + o.entry("editing").or_insert_with(|| serde_json::json!({"kind": kind, "name": name})); + } + r } pub fn commands(&self) -> Vec { diff --git a/crates/engine/src/tests.rs b/crates/engine/src/tests.rs index 4dfc21f4..692d6eab 100644 --- a/crates/engine/src/tests.rs +++ b/crates/engine/src/tests.rs @@ -5646,3 +5646,23 @@ fn invalid_ids_array_never_falls_back_to_the_selection() { assert!(s.doc().unwrap().shape(deckcraft_model::ShapeId(a as u32)).is_some(), "shape deleted for {ids}"); } } + +/// In Slide Master / layout view the insert commands edit the master or layout; their answers say +/// so with `editing`, and on slides carry no such key. +#[test] +fn insert_answers_carry_editing_in_master_and_layout_view() { + let mut s = session(); + let ins = json!({"preset": "rect", "rect": [10.0, 10.0, 100.0, 100.0]}); + s.execute("view.slideMaster", &json!({"layout": 0})).unwrap(); + let r = s.execute("shape.insert", &ins).unwrap(); + assert_eq!(r["editing"]["kind"], "layout", "{r}"); + assert!(r["editing"]["name"].is_string(), "{r}"); + let r = s.execute("insert.textBox", &json!({"rect": [10.0, 10.0, 100.0, 50.0], "text": "x"})).unwrap(); + assert_eq!(r["editing"]["kind"], "layout", "{r}"); + s.execute("view.slideMaster", &json!({"master": 0})).unwrap(); + let r = s.execute("shape.insert", &ins).unwrap(); + assert_eq!(r["editing"]["kind"], "master", "{r}"); + s.execute("view.closeMaster", &json!({})).unwrap(); + let r = s.execute("shape.insert", &ins).unwrap(); + assert!(r.get("editing").is_none(), "{r}"); +}