diff --git a/crates/ui-egui/src/dialogs/swatch_conflict.rs b/crates/ui-egui/src/dialogs/swatch_conflict.rs index 490646e852..fb8b528b01 100644 --- a/crates/ui-egui/src/dialogs/swatch_conflict.rs +++ b/crates/ui-egui/src/dialogs/swatch_conflict.rs @@ -5,7 +5,8 @@ //! //! Fields: `conflicts` (as `clipboard.conflicts` lists them: `[{name, document, clipboard, spot}]`), //! `index` (the one asked about), `choice` (`merge` or `add`), `applyToAll`, `choices` (the -//! answers so far, by swatch name), `__command` and `__params` (the paste to run). +//! answers so far, by swatch name), `__command` and `__params` (the paste to run), and `__doc` +//! (the uid of the document it asks about). use egui::vec2; use serde_json::{Map, Value, json}; @@ -39,7 +40,7 @@ pub fn ask(app: &mut VectorcraftApp, command: &str, params: &Value) -> Option Option &[Value] { d.fields.get("conflicts").and_then(Value::as_array).map_or(&[], Vec::as_slice) } @@ -102,8 +106,14 @@ fn body(_: &mut VectorcraftApp, ui: &mut egui::Ui, d: &mut Dialog) -> bool { false } -/// Record the answer; ask about the next conflict, or paste once every one is answered. +/// Record the answer; ask about the next conflict, or paste once every one is answered. When +/// another document has become the active one since an immediate paste asked, it closes as Cancel +/// does and pastes nothing (a deferred paste goes back to its own document). fn confirm(app: &mut VectorcraftApp, d: &Dialog) -> DialogResult { + if d.fields.get("__deferredPaste").is_none() && d.fields.get(DOC).and_then(Value::as_u64) != app.session.active().map(|doc| doc.uid) { + app.ui.dialog = None; + return Ok(json!({})); + } let choice = d.str("choice"); if !matches!(choice.as_str(), "merge" | "add") { return Err(format!("choice must be \"merge\" or \"add\", not `{choice}`")); diff --git a/crates/ui-egui/src/tests/clipboard.rs b/crates/ui-egui/src/tests/clipboard.rs index d3b0c25a65..1892df67be 100644 --- a/crates/ui-egui/src/tests/clipboard.rs +++ b/crates/ui-egui/src/tests/clipboard.rs @@ -104,6 +104,22 @@ fn apply_to_all_answers_the_rest_and_cancel_pastes_nothing() { assert!(app.ui.dialog.is_none()); } +#[test] +fn ok_pastes_nothing_after_another_document_became_active() { + let mut app = conflicting(); + run(&mut app, "edit.paste", json!({})); + set(&mut app, "applyToAll", json!(true)); + app.run("document.activate", json!({"index": 0})).unwrap(); + let before = objects(&app); + let undo = app.session.active().unwrap().history.undo.len(); + dialogs::confirm(&mut app).unwrap(); + assert!(app.ui.dialog.is_none(), "it closes as Cancel does"); + assert_eq!(objects(&app), before, "the document made active pastes nothing"); + assert_eq!(app.session.active().unwrap().history.undo.len(), undo); + app.run("document.activate", json!({"index": 1})).unwrap(); + assert!(objects(&app).is_empty(), "the document it asked in pastes nothing"); +} + #[test] fn paste_goes_to_the_centre_of_the_view() { let mut app = VectorcraftApp::new(Session::new(), Default::default());