Plug-ins: OK after a failed preview runs the filter in the background

A light filter that reports its progress kept a failed preview's
interaction open, so OK ran it again on the UI thread without progress
or Cancel. A failed preview is now rolled back and the run goes to the
background.
This commit is contained in:
dotCooCoo
2026-11-11 14:24:03 -08:00
parent 96e20d548d
commit 736f73125f
2 changed files with 26 additions and 4 deletions
+6 -4
View File
@@ -245,12 +245,14 @@ fn body(app: &mut VectorcraftApp, ui: &mut egui::Ui, d: &mut Dialog) -> bool {
}
/// OK: a filter keeps its previewed run as one undo step; a heavy one, which has no preview, and a
/// light one that runs in the background ([`in_background`]) with Preview off, start in the
/// background ([`run`]) and the dialog closes. A preview still shown when Preview was just turned
/// off is rolled back first.
/// light one that runs in the background ([`in_background`]) with Preview off or a failed preview,
/// start in the background ([`run`]) and the dialog closes. A preview still shown when Preview was
/// just turned off, or a preview that failed, is rolled back first.
fn confirm(app: &mut VectorcraftApp, d: &Dialog) -> Result<Value, String> {
let own_run = d.str("__command").is_empty();
let kept = |plugin: &Plugin| plugin.manifest().budget == Budget::Light && d.bool("preview") && app.session.in_interaction();
let kept = |plugin: &Plugin| {
plugin.manifest().budget == Budget::Light && d.bool("preview") && app.session.in_interaction() && !d.fields.contains_key(form::REFUSED)
};
match registry::get(&d.str("__plugin")) {
Some(plugin) if own_run && in_background(plugin.manifest()) && !kept(&plugin) => {
if d.fields.contains_key(form::PREVIEWED) && app.session.in_interaction() {
+20
View File
@@ -327,6 +327,26 @@ fn ok_runs_a_light_progress_filter_in_the_background_without_a_preview() {
assert_eq!(app.session.doc().unwrap().history.undo.len(), undo + 3);
}
/// In the dialog of a light filter that reports its progress, a failed preview is not kept: OK
/// rolls it back and runs the filter in the background instead of again on the UI thread.
#[test]
fn ok_after_a_failed_preview_runs_a_light_progress_filter_in_the_background() {
let mut app = app();
let id = "test.ui.light.progress.fails";
install_light(&mut app, id, true, r#"{"size":{"type":"number","min":1,"max":9,"default":3}}"#, "(unreachable)");
let doc = app.session.doc().unwrap().doc.clone();
app.run("plugin.dialog", json!({"id": id})).unwrap();
frame(&mut app);
assert!(app.session.in_interaction(), "the preview's interaction");
assert!(app.ui.dialog.as_ref().unwrap().fields.contains_key("__refused"), "the preview failed");
dialogs::confirm(&mut app).unwrap();
assert!(app.ui.dialog.is_none());
assert!(!app.session.in_interaction(), "the failed preview was rolled back");
assert_eq!(app.plugin_runs.running.len(), 1, "running in the background");
finish_runs(&mut app);
assert_eq!(app.session.doc().unwrap().doc, doc);
}
/// A light filter without the `progress` permission still runs at once, on the UI thread.
#[test]
fn a_light_filter_that_does_not_report_progress_runs_at_once() {