G3: feedback from a command that switched windows shows in the window it left active

after_engine, show_open_warnings and alert bring the per-window state in line
with the engine's active window first, so a notice, message or toast from
opening a workbook (also by a script on the session) lands in the opened
workbook's window instead of being parked with the previous one.
This commit is contained in:
aiongg
2026-10-22 16:29:24 +00:00
parent 5bd5d241a0
commit d4db58cde4
2 changed files with 32 additions and 0 deletions
+7
View File
@@ -648,6 +648,8 @@ impl SheetApp {
/// Shows a command error: a toast for an unavailable command, else a message box.
fn alert(&mut self, e: String) {
// Shown in the window the user ends up in, also after a command that switched windows.
self.follow_active_window();
if e.contains("is not available right now") {
self.toast = Some((e, now_ms()));
} else {
@@ -799,6 +801,8 @@ impl SheetApp {
/// Picks up requests commands made (dialogs, edit mode…).
pub fn after_engine(&mut self) {
// The requests belong to the window the command left active.
self.follow_active_window();
for req in self.session.take_ui_requests() {
match req {
UiRequest::Dialog(name, params) => self.open_dialog(&name, params),
@@ -924,6 +928,9 @@ impl SheetApp {
/// most important one (a preserved VBA project outranks, say, a skipped optional part).
/// Kept deliberately generic: any open-time warning can reach the user this way.
pub fn show_open_warnings(&mut self, r: &Json) {
// The opened workbook's window shows them, however it was opened (a script may have run
// `file.open` on the session directly).
self.follow_active_window();
let Some(list) = r.get("warnings").and_then(Json::as_array) else {
self.notice = None;
return;
+25
View File
@@ -282,3 +282,28 @@ fn menu_commands_follow_the_focused_window_and_leaving_a_window_enters_its_draft
desk.app.run("cell.set", json!({"cell": "B1", "input": "menu"})).unwrap();
assert_eq!(desk.app.session.documents()[0].wb.active().unwrap().value(CellRef::new(0, 1)), Value::text("menu"));
}
#[test]
fn feedback_from_opening_a_workbook_shows_in_its_new_window() {
let mut desk = Desk::new(true);
desk.app.run("cell.set", json!({"cell": "A1", "input": "kept"})).unwrap();
desk.frames(2);
let book1 = desk.window_of(0);
let mut wb = gridcraft_engine::model::Workbook::new();
wb.vba_project = Some(b"\xd0\xcf\x11\xe0\xa1\xb1\x1a\xe1 fake OLE2 vbaProject".to_vec().into());
let b64 = gridcraft_engine::io::base64_encode(&gridcraft_engine::io::save_bytes(&wb, "macros.xlsm").unwrap());
desk.frame_with(|app, _| {
// A script opening the file on the session, then the interface reporting on it.
let r = app.session.run("file.open", json!({"name": "macros.xlsm", "base64": b64})).unwrap();
app.show_open_warnings(&r);
app.run_or_alert("no.such.command", json!({}));
});
desk.frames(2);
let opened = desk.window_of(1);
assert_eq!(desk.windows.shown_windows(), [book1, opened]);
assert_eq!(desk.app.session.active_window(), Some(opened));
assert_eq!(desk.app.notice.as_ref().map(|n| n.kind), Some(gridcraft_ui_egui::NoticeKind::Warning), "the macro notice shows in the opened window");
assert!(desk.app.message.is_some(), "and so does the alert");
desk.app.enter_window(book1);
assert!(desk.app.notice.is_none() && desk.app.message.is_none(), "Book1's window shows neither");
}