diff --git a/crates/ui-egui/src/macro_ui.rs b/crates/ui-egui/src/macro_ui.rs index acbc77a2c..78fee3317 100644 --- a/crates/ui-egui/src/macro_ui.rs +++ b/crates/ui-egui/src/macro_ui.rs @@ -50,6 +50,8 @@ impl MacroUi { /// runs the command again with its parameters added; Cancel drops it. #[derive(Clone, Debug)] pub struct Question { + /// The workbook (`DocState::uid`) the question is about: the answer runs only there. + pub doc: u64, pub title: String, pub text: String, pub command: String, @@ -147,7 +149,8 @@ pub fn ask(app: &mut SheetApp, title: &str, id: &str, params: &Json, e: &str) -> } else { return false; }; - app.macros.question = Some(Question { title: title.into(), text, command: id.into(), params: params.clone(), choices }); + let doc = app.session.active().map_or(0, |d| d.uid); + app.macros.question = Some(Question { doc, title: title.into(), text, command: id.into(), params: params.clone(), choices }); true } @@ -202,6 +205,13 @@ pub fn question_box(app: &mut SheetApp, ctx: &egui::Context) { }); }); match answer { + // Another workbook became active meanwhile (an agent): the answer would run there. + Some(Some(_)) if app.session.active().is_none_or(|d| d.uid != q.doc) => { + app.macros.question = None; + let book = app.session.documents().iter().find(|d| d.uid == q.doc).map(|d| d.display_title()).unwrap_or_default(); + app.message = + Some((q.title.clone(), format!("The question was about “{book}”, which is no longer the active workbook, so nothing was done."))); + } Some(Some(extra)) => { app.macros.question = None; let mut params = q.params.clone(); @@ -441,6 +451,7 @@ pub fn macros_dialog(app: &mut SheetApp, ui: &mut Ui, d: &mut Dialog, open: &mut Kind::Script => ("Delete Script", "automate.deleteScript", "script"), }; app.macros.question = Some(Question { + doc: app.session.active().map_or(0, |d| d.uid), title: title.into(), text: format!("Do you want to delete {what} “{}”?", e.name), command: command.into(), diff --git a/crates/ui-egui/tests/it/macros_ui.rs b/crates/ui-egui/tests/it/macros_ui.rs index 7c18b08ff..c8e6ba490 100644 --- a/crates/ui-egui/tests/it/macros_ui.rs +++ b/crates/ui-egui/tests/it/macros_ui.rs @@ -314,3 +314,33 @@ fn the_macros_and_record_macro_dialogs_fit_a_narrow_window() { } } } + +#[test] +fn a_question_is_answered_in_the_workbook_that_asked_it() { + let mut h = harness("Automate"); + save(&mut h, json!({"name": "Tidy", "steps": []})); + h.state_mut().open_dialog("macros", json!({"name": "Tidy"})); + h.run_steps(2); + h.get_by_label("Delete").click(); + h.run_steps(2); + assert!(h.state().macros.question.is_some()); + // Another workbook with a macro of that name becomes active before the answer (an agent). + h.state_mut().dialog = None; + h.state_mut().session.new_workbook(); + save(&mut h, json!({"name": "Tidy", "steps": []})); + h.get_by_label("Delete").click(); + h.run_steps(3); + assert_eq!(h.state().session.active().unwrap().wb.macros.len(), 1, "the other workbook's macro is kept"); + assert!(h.state().macros.question.is_none()); + assert!(h.state().message.as_ref().is_some_and(|(_, m)| m.contains("Book1")), "{:?}", h.state().message); + // Asked and answered in the same workbook, it deletes there. + h.state_mut().message = None; + h.run_steps(2); + h.state_mut().open_dialog("macros", json!({"name": "Tidy"})); + h.run_steps(2); + h.get_by_label("Delete").click(); + h.run_steps(2); + h.get_all_by_label("Delete").last().unwrap().click(); + h.run_steps(3); + assert!(h.state().session.active().unwrap().wb.macros.is_empty()); +}