UI: a macro question is answered only in the workbook that asked it

The Macros dialog's Delete question and the questions a macro run asks
(approve it, overwrite or move the data in the way) keep the command
and run it again with the answer. When another workbook became active
before the answer (an agent can switch workbooks under the prompt),
the answer ran there: Delete removed the other workbook's macro of the
same name. A question now keeps its workbook, and an answer given while
another one is active does nothing and says why.
This commit is contained in:
prxnvt
2026-10-25 06:48:57 -04:00
parent baf01c4211
commit 0fdb4d03e4
2 changed files with 42 additions and 1 deletions
+12 -1
View File
@@ -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(),
+30
View File
@@ -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());
}