From c2ed2dd3a93dc9d322f309cc132aca06b34559ed Mon Sep 17 00:00:00 2001 From: dotCooCoo Date: Thu, 12 Nov 2026 21:38:46 -0800 Subject: [PATCH] Links: Find in Folder copies the files of images in symbols and patterns With Copy into the document's folder, an image picked in the Links panel by the id of an object in a symbol, graph design, pattern or opacity mask was relinked to the found file instead of a copy, because the check for an image looked only in the layers. --- crates/ui-egui/src/dialogs/find_links.rs | 5 ++-- .../ui-egui/src/dialogs/find_links/tests.rs | 29 +++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/crates/ui-egui/src/dialogs/find_links.rs b/crates/ui-egui/src/dialogs/find_links.rs index 05f0e85b60..2e99f5e97e 100644 --- a/crates/ui-egui/src/dialogs/find_links.rs +++ b/crates/ui-egui/src/dialogs/find_links.rs @@ -112,11 +112,12 @@ pub(crate) fn find_in_folder_command(app: &mut VectorcraftApp, folder: Option bool { let Some(id) = id.as_u64() else { return false }; let st = app.session.active(); - st.and_then(|st| st.doc.node(vectorcraft_doc::NodeId(id))).is_some_and(|n| matches!(n.kind, vectorcraft_doc::NodeKind::Image(_))) + st.and_then(|st| st.doc.stored_node(vectorcraft_doc::NodeId(id))).is_some_and(|(n, _)| matches!(n.kind, vectorcraft_doc::NodeKind::Image(_))) } /// Make the dialog's document the active one: it may be another tab's. diff --git a/crates/ui-egui/src/dialogs/find_links/tests.rs b/crates/ui-egui/src/dialogs/find_links/tests.rs index 4722b8b327..0b618c7e6f 100644 --- a/crates/ui-egui/src/dialogs/find_links/tests.rs +++ b/crates/ui-egui/src/dialogs/find_links/tests.rs @@ -255,6 +255,35 @@ fn copy_into_the_documents_folder_copies_before_relinking() { assert!(!frame(&mut app).contains("Copy into the document's folder")); } +/// Copy into the document's folder copies the file of an image in a symbol's art too, picked in the +/// Links panel by its id. +#[test] +fn copy_takes_an_image_in_a_symbol_into_the_documents_folder() { + let root = folder("copy-symbol"); + let mut app = app_for(&root); + app.run("file.new", json!({"width": 400, "height": 300})).unwrap(); + let orig = at(&root, "orig/a.png"); + write(&orig, &png(3)); + let placed = app.run("file.place", json!({"path": orig})).unwrap()["ids"][0].clone(); + app.run("symbol.new", json!({"name": "Mark", "ids": [placed]})).unwrap(); + let doc = at(&root, "doc/doc.vectorcraft"); + std::fs::create_dir_all(doc.parent().unwrap()).unwrap(); + app.run("document.save", json!({"path": doc})).unwrap(); + write(&at(&root, "found/a.png"), &png(3)); + let list = app.run("links.list", json!({})).unwrap(); + let row = list["links"].as_array().unwrap().iter().find(|r| r["owner"]["kind"] == "symbol").cloned().expect("the symbol's image"); + app.run("ui.findLinksInFolder", json!({"folder": root.join("found"), "ids": [row["id"]]})).unwrap(); + searched(&mut app); + app.ui.dialog.as_mut().unwrap().fields.insert("copy".into(), json!(true)); + let r = super::super::confirm(&mut app).unwrap(); + assert_eq!((r["relinked"].as_array().map(Vec::len), &r["failed"]), (Some(1), &json!([])), "{r}"); + let copy = at(&root, "doc/a.png"); + assert_eq!(std::fs::read(©).unwrap(), png(3)); + let list = app.run("links.list", json!({})).unwrap(); + let row = list["links"].as_array().unwrap().iter().find(|r| r["owner"]["kind"] == "symbol").cloned().unwrap(); + assert_eq!(row["path"], json!(copy), "{list}"); +} + /// With Copy into the document's folder, a placed document is relinked where its file is. #[test] fn copy_leaves_placed_documents_where_they_are() {