From ed63b8f4ab47d12238bc2dca49436f957fac3a38 Mon Sep 17 00:00:00 2001 From: moppeeer Date: Sat, 24 Oct 2026 11:17:28 +0200 Subject: [PATCH] Convert dialogs stay open when the conversion fails An emptied separator field reached table.convertFromText / convertToText, which refuse it; the dialog closed and lost what was typed. On an error the message goes to the status bar and the dialog comes back, as the other dialogs do (Insert Table included, from #1676). Found by CodeRabbit. Co-Authored-By: Claude Opus 5.5 --- crates/ui-egui/src/dialogs.rs | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/crates/ui-egui/src/dialogs.rs b/crates/ui-egui/src/dialogs.rs index 0a2962991..b2e3bd714 100644 --- a/crates/ui-egui/src/dialogs.rs +++ b/crates/ui-egui/src/dialogs.rs @@ -3210,17 +3210,24 @@ pub fn confirm(app: &mut DesignApp) -> Result { None => Err(format!("no page \"{typed}\"")), } } - "convertTextToTable" => { - let same = d.s("columnSeparator") == d.s("rowSeparator"); - let style = Some(d.s("tableStyle")).filter(|s| !s.is_empty() && s != designcraft_doc::BASIC_TABLE); - app.run( - "table.convertFromText", - json!({"columnSeparator": d.s("columnSeparator"), "rowSeparator": d.s("rowSeparator"), - "columns": if same { json!(d.n("columns").unwrap_or(1.0).max(1.0) as u64) } else { Value::Null }, "tableStyle": style}), - ) - } - "convertTableToText" => { - app.run("table.convertToText", json!({"columnSeparator": d.s("columnSeparator"), "rowSeparator": d.s("rowSeparator")})) + "convertTextToTable" | "convertTableToText" => { + let r = if d.id == "convertTextToTable" { + let same = d.s("columnSeparator") == d.s("rowSeparator"); + let style = Some(d.s("tableStyle")).filter(|s| !s.is_empty() && s != designcraft_doc::BASIC_TABLE); + app.run( + "table.convertFromText", + json!({"columnSeparator": d.s("columnSeparator"), "rowSeparator": d.s("rowSeparator"), + "columns": if same { json!(d.n("columns").unwrap_or(1.0).max(1.0) as u64) } else { Value::Null }, "tableStyle": style}), + ) + } else { + app.run("table.convertToText", json!({"columnSeparator": d.s("columnSeparator"), "rowSeparator": d.s("rowSeparator")})) + }; + // On an error (an emptied separator field) the dialog stays open to be corrected. + if let Err(e) = &r { + app.status(e.clone()); + app.ui.dialog = Some(d); + } + r } "insertTable" => { // The table and its style in one step; a style that is gone leaves the document alone, @@ -9861,6 +9868,10 @@ mod tests { assert!(crate::menus::menu_enabled(&app, "app.convertTextToTableDialog")); app.run("app.convertTextToTableDialog", json!({})).unwrap(); assert_eq!(app.ui.dialog.as_ref().map(|d| d.id.as_str()), Some("convertTextToTable")); + // An emptied separator: the command refuses it and the dialog stays open, as typed. + ctl(&mut app, "ui.dialog.set", json!({"field": "rowSeparator", "value": ""})); + assert_eq!(ctl(&mut app, "ui.dialog.confirm", json!({}))["ok"], false); + assert_eq!(app.ui.dialog.as_ref().map(|d| (d.id.as_str(), d.s("rowSeparator"))), Some(("convertTextToTable", String::new()))); for (field, value) in [("columnSeparator", json!("paragraph")), ("rowSeparator", json!("paragraph")), ("columns", json!(2))] { ctl(&mut app, "ui.dialog.set", json!({"field": field, "value": value})); }