diff --git a/crates/ui-egui/src/dialogs/script_run.rs b/crates/ui-egui/src/dialogs/script_run.rs index eb89bd174..8f5e3b109 100644 --- a/crates/ui-egui/src/dialogs/script_run.rs +++ b/crates/ui-egui/src/dialogs/script_run.rs @@ -182,6 +182,22 @@ pub(crate) fn ask_to_close(app: &mut VectorcraftApp) { app.ui.dialog = Some(Dialog::new(CLOSE_KIND, fields)); } +/// Closes the question quitting asks once the run it asks about has ended, and forgets the +/// script's dialog it was asked over once the run no longer waits at that dialog, so Cancel does +/// not show it again. +pub(crate) fn settle_close(app: &mut VectorcraftApp) { + if !app.ui.dialog.as_ref().is_some_and(|d| d.kind == CLOSE_KIND) { + return; + } + if !app.session.script_running() { + app.ui.dialog = None; + } else if app.session.script_dialog().is_none() + && let Some(d) = app.ui.dialog.as_mut() + { + d.fields.remove(super::PARENT); + } +} + /// Shows the dialog the running script waits at. pub(crate) fn open_notice(app: &mut VectorcraftApp, d: &ScriptDialog) { let fields = json!({ diff --git a/crates/ui-egui/src/script_runs.rs b/crates/ui-egui/src/script_runs.rs index 65a9dc9eb..02c222974 100644 --- a/crates/ui-egui/src/script_runs.rs +++ b/crates/ui-egui/src/script_runs.rs @@ -15,6 +15,7 @@ pub fn poll(app: &mut VectorcraftApp) { if !app.session.script_running() { return; } + script_run::settle_close(app); if ask(app) { return; } @@ -31,6 +32,7 @@ pub fn poll(app: &mut VectorcraftApp) { if app.ui.dialog.as_ref().is_some_and(|d| d.kind == script_run::GROWTH_KIND) { app.ui.dialog = None; } + script_run::settle_close(app); match result { Ok(_) => app.status(format!("Ran {name}")), Err(e) => failed(app, e.to_string()), diff --git a/crates/ui-egui/src/tests/script_dialogs.rs b/crates/ui-egui/src/tests/script_dialogs.rs index da09c777b..b3750001a 100644 --- a/crates/ui-egui/src/tests/script_dialogs.rs +++ b/crates/ui-egui/src/tests/script_dialogs.rs @@ -220,6 +220,32 @@ fn close_while_notification_waits_abandons_or_resumes() { assert_eq!(app.ui.status, "The script was stopped and its changes were undone"); } +#[test] +fn close_question_ends_with_a_run_stopped_another_way() { + let mut app = app(); + start(&mut app, &format!("{DRAW} vc.log(prompt('Name', ''));")); + assert!(until_dialog(&mut app)); + dialogs::script_run::ask_to_close(&mut app); + assert_eq!(app.ui.dialog.as_ref().unwrap().kind, CLOSE_KIND); + assert_eq!(app.run("script.stop", json!({})).unwrap()["stopped"], true); + script_runs::poll(&mut app); + assert!(!app.session.script_running()); + assert!(app.ui.dialog.is_none(), "the question about a run that has ended closes"); + dialogs::cancel(&mut app); + assert!(app.ui.dialog.is_none(), "Cancel does not show the stopped script's dialog again"); + assert_eq!(objects(&app), 0); + // Asked to stop, the run no longer waits at its dialog before its next slice ends it. + let mut app = self::app(); + start(&mut app, &format!("{DRAW} vc.log(prompt('Name', ''));")); + assert!(until_dialog(&mut app)); + dialogs::script_run::ask_to_close(&mut app); + app.run("script.stop", json!({})).unwrap(); + dialogs::script_run::settle_close(&mut app); + assert_eq!(app.ui.dialog.as_ref().unwrap().kind, CLOSE_KIND, "the run has not ended yet"); + dialogs::cancel(&mut app); + assert!(app.ui.dialog.is_none(), "Cancel does not show a dialog the run no longer waits at"); +} + #[test] fn notification_layout_with_long_text_and_small_window() { let mut app = app();