From ebc82ca0d5754e488776a96d276edd722109597d Mon Sep 17 00:00:00 2001 From: dotCooCoo Date: Sat, 14 Nov 2026 11:43:39 -0800 Subject: [PATCH] Links: Sort by Size in the panel menu lists the smallest file first The Links panel menu gets Sort by Size beside Sort by Name, Kind and Status, and links.list takes sort: "size". A row's size is the file size Link Info shows: the file's size now, else the size the document keeps of it. Rows without a size (embedded images, a missing file whose size is not kept) come last, and equal sizes go by name. The size is read only when sorting by it, and under automation read roots a file outside them is not read. Every catalog with Sort by Status gets a Sort by Size row; the Ukrainian Sort by Status row, which read "Sort by:", now says "Sort by Status". --- crates/engine/src/cmd/links.rs | 34 +++++++++++++++++++--- crates/engine/src/tests/linkspanel.rs | 37 +++++++++++++++++++++++- crates/ui-egui/src/i18n/bg.tsv | 1 + crates/ui-egui/src/i18n/bs.tsv | 1 + crates/ui-egui/src/i18n/ca.tsv | 1 + crates/ui-egui/src/i18n/cs.tsv | 1 + crates/ui-egui/src/i18n/da.tsv | 1 + crates/ui-egui/src/i18n/de.tsv | 1 + crates/ui-egui/src/i18n/el.tsv | 1 + crates/ui-egui/src/i18n/es.tsv | 1 + crates/ui-egui/src/i18n/fi.tsv | 1 + crates/ui-egui/src/i18n/fr.tsv | 1 + crates/ui-egui/src/i18n/hi.tsv | 1 + crates/ui-egui/src/i18n/hu.tsv | 1 + crates/ui-egui/src/i18n/id.tsv | 1 + crates/ui-egui/src/i18n/it.tsv | 1 + crates/ui-egui/src/i18n/ja.tsv | 1 + crates/ui-egui/src/i18n/ka.tsv | 1 + crates/ui-egui/src/i18n/ko.tsv | 1 + crates/ui-egui/src/i18n/nl.tsv | 1 + crates/ui-egui/src/i18n/pl.tsv | 1 + crates/ui-egui/src/i18n/pt-br.tsv | 1 + crates/ui-egui/src/i18n/ru.tsv | 1 + crates/ui-egui/src/i18n/sv.tsv | 1 + crates/ui-egui/src/i18n/tr.tsv | 1 + crates/ui-egui/src/i18n/uk.tsv | 3 +- crates/ui-egui/src/i18n/vi.tsv | 1 + crates/ui-egui/src/i18n/zh-hans.tsv | 1 + crates/ui-egui/src/i18n/zh-hant.tsv | 1 + crates/ui-egui/src/panels/links.rs | 2 +- crates/ui-egui/src/panels/tests_links.rs | 12 ++++++-- docs/mcp.md | 6 ++-- docs/target-app-parity.md | 1 + 33 files changed, 110 insertions(+), 11 deletions(-) diff --git a/crates/engine/src/cmd/links.rs b/crates/engine/src/cmd/links.rs index 9a026598e8..ecc4a12bff 100644 --- a/crates/engine/src/cmd/links.rs +++ b/crates/engine/src/cmd/links.rs @@ -81,7 +81,7 @@ pub fn specs() -> Vec { "Links", [], None, - "{show?: all (default)|missing|modified|embedded, sort?: name|kind (file format)|status (missing, modified, ok, embedded); default: stacking order; top first, dcsTransparency?: false (Show DCS Transparency Interactions: mark the images placed from DCS files that are transparent, themselves or a group or layer holding them, or that overlap a visible object with its own transparency; it looks at every object, so it takes longer)} every image object and placed document the document stores, as the Links panel lists them: those in the layers, then those in opacity-mask art and in the art of symbols, graph designs, patterns and stored brushes (one row per stored object, never one per symbol instance, pattern tile or brushed stroke) → {links: [{id, name, linked, status: ok|modified|missing|embedded, format (DCS for an image placed from a DCS file), pixelWidth, pixelHeight, path?, found?: path (found away from its path), page?, preview?: true (showing the saved preview), note?: said of an image past the decode allowance (shown at reduced size, or too large to draw), document?: true (a placed document: pageWidth and pageHeight in pt instead of pixels), dcsTransparency?: true (with dcsTransparency), owner?: {kind: layers|symbol|graphDesign|pattern|brush, name? (of the symbol, graph design, pattern or brush), index? (a brush's place in the Brushes panel, from 0), tile?: side|outerCorner|innerCorner|start|end (a pattern brush's tile), maskOf?: id (in the opacity-mask art of that object)} (an object outside the layer tree)}], missing, modified, embedded}; under automation read roots, path and found are left out when the file they name is outside the roots", + "{show?: all (default)|missing|modified|embedded, sort?: name|kind (file format)|status (missing, modified, ok, embedded)|size (the linked file's size in bytes as Link Info shows it, smallest first; rows without one, embedded images and missing files whose size is not kept, last; equal sizes by name); default: stacking order; top first, dcsTransparency?: false (Show DCS Transparency Interactions: mark the images placed from DCS files that are transparent, themselves or a group or layer holding them, or that overlap a visible object with its own transparency; it looks at every object, so it takes longer)} every image object and placed document the document stores, as the Links panel lists them: those in the layers, then those in opacity-mask art and in the art of symbols, graph designs, patterns and stored brushes (one row per stored object, never one per symbol instance, pattern tile or brushed stroke) → {links: [{id, name, linked, status: ok|modified|missing|embedded, format (DCS for an image placed from a DCS file), pixelWidth, pixelHeight, path?, found?: path (found away from its path), page?, preview?: true (showing the saved preview), note?: said of an image past the decode allowance (shown at reduced size, or too large to draw), document?: true (a placed document: pageWidth and pageHeight in pt instead of pixels), dcsTransparency?: true (with dcsTransparency), owner?: {kind: layers|symbol|graphDesign|pattern|brush, name? (of the symbol, graph design, pattern or brush), index? (a brush's place in the Brushes panel, from 0), tile?: side|outerCorner|innerCorner|start|end (a pattern brush's tile), maskOf?: id (in the opacity-mask art of that object)} (an object outside the layer tree)}], missing, modified, embedded}; under automation read roots, path and found are left out when the file they name is outside the roots", has_doc, list ), @@ -2211,6 +2211,16 @@ fn document_row(p: &PlacedDocument) -> Value { json!({ "format": pdf.map_or("VectorCraft", |f| f.label), "document": true, "pageWidth": p.width, "pageHeight": p.height }) } +/// The size in bytes of the file that link `l` (of `st`) names, as Link Info shows it: the file's +/// size now, else the size the document keeps of it when the caller may see its path. +fn link_file_size(st: &crate::DocState, l: &LinkInfo) -> Option { + let doc_path = LinkBase::of(st).doc; + let kept = l.size.filter(|_| path_shown(&l.path, doc_path)); + let roots = crate::file_access::current().or_else(|| st.opened_by.clone()); + let now = crate::file_access::confine(roots.as_ref(), || fileio::document_path(&l.path, doc_path).ok().as_deref().and_then(file_stamp)); + now.map(|s| s.0).or(kept) +} + /// Sort rank of a `links.list` status: missing, modified, ok, embedded. fn status_rank(status: &str) -> usize { ["missing", "modified", "ok", "embedded"].iter().position(|s| *s == status).unwrap_or(4) @@ -2277,8 +2287,14 @@ fn list(s: &mut Session, p: &Value) -> Result { if !matches!(show, "all" | "missing" | "modified" | "embedded") { return Err(bad(C, format!("show `{show}`: all, missing, modified or embedded"))); } + let sort = str_param(p, "sort"); + if let Some(x) = sort.filter(|x| !matches!(*x, "name" | "kind" | "status" | "size")) { + return Err(bad(C, format!("sort `{x}`: name, kind, status or size"))); + } let interactions = if switch_or(p, "dcsTransparency", false, C)? { dcs_transparency(&st.doc) } else { BTreeSet::new() }; let statuses = statuses(st); + // The file size of each listed row's link, read only to sort by size. + let mut sizes: BTreeMap = BTreeMap::new(); // The layer tree's objects, top first as the Layers panel lists them, then the others in the // order they are stored (opacity-mask art, symbols, graph designs, patterns, the art of the // stored brushes), each once. @@ -2326,6 +2342,11 @@ fn list(s: &mut Session, p: &Value) -> Result { } let doc_path = LinkBase::of(st).doc; if let Some(l) = link { + if sort == Some("size") + && let Some(size) = link_file_size(st, l) + { + sizes.insert(n.id.0, size); + } note_path(&mut row, "path", &l.path, doc_path); if let Some(page) = l.page { row["page"] = json!(page); @@ -2346,12 +2367,17 @@ fn list(s: &mut Session, p: &Value) -> Result { rows.push(row); } let text = |r: &Value, k: &str| r[k].as_str().unwrap_or_default().to_lowercase(); - match str_param(p, "sort") { - None => {} + match sort { Some("name") => rows.sort_by_cached_key(|r| text(r, "name")), Some("kind") => rows.sort_by_cached_key(|r| (text(r, "format"), text(r, "name"))), Some("status") => rows.sort_by_cached_key(|r| (status_rank(r["status"].as_str().unwrap_or_default()), text(r, "name"))), - Some(x) => return Err(bad(C, format!("sort `{x}`: name, kind or status"))), + // Smallest file first; rows without a file size (embedded images, a missing file whose + // size the document does not keep) come last; equal sizes by name. + Some("size") => rows.sort_by_cached_key(|r| { + let size = r["id"].as_u64().and_then(|id| sizes.get(&id).copied()); + (size.is_none(), size.unwrap_or(0), text(r, "name")) + }), + _ => {} } let count = |k: &str| counts.get(k).copied().unwrap_or(0); Ok(json!({ "links": rows, "missing": count("missing"), "modified": count("modified"), "embedded": count("embedded") })) diff --git a/crates/engine/src/tests/linkspanel.rs b/crates/engine/src/tests/linkspanel.rs index a9a3a17ec7..a1402cc43f 100644 --- a/crates/engine/src/tests/linkspanel.rs +++ b/crates/engine/src/tests/linkspanel.rs @@ -248,7 +248,42 @@ fn the_list_shows_each_image_with_its_status() { assert_eq!(run(&mut s, "links.list", json!({"show": "missing"}))["links"][0]["id"], linked.0); assert_eq!(run(&mut s, "links.list", json!({"sort": "name"}))["links"][0]["name"], "a.png"); assert!(s.execute("links.list", &json!({"show": "broken"})).is_err()); - assert!(s.execute("links.list", &json!({"sort": "size"})).is_err()); + assert!(s.execute("links.list", &json!({"sort": "date"})).is_err()); +} + +#[test] +fn sort_by_size_lists_the_smallest_file_first() { + let dir = Folder::new("list-size"); + let files = [("a.png", png(600, 300, RED)), ("b.png", png(10, 10, BLUE)), ("c.png", png(100, 100, RED)), ("d.png", png(10, 10, BLUE))]; + let mut s = session(); + for (name, bytes) in &files { + let path = dir.file(name); + write(&path, bytes); + place(&mut s, &path); + } + let e = dir.file("e.png"); + write(&e, &png(1, 1, RED)); + place_embedded(&mut s, &e); + let names = |s: &mut Session| -> Vec { + let l = run(s, "links.list", json!({"sort": "size"})); + l["links"].as_array().unwrap().iter().map(|r| r["name"].as_str().unwrap_or_default().to_string()).collect() + }; + // Smallest first, equal sizes by name, the embedded image (no file) last. + let mut want: Vec<(usize, &str)> = files.iter().map(|(n, b)| (b.len(), *n)).collect(); + want.sort(); + assert!(want[0].0 < want[2].0 && want[2].0 < want[3].0, "{want:?}"); + let mut want: Vec = want.iter().map(|(_, n)| n.to_string()).collect(); + want.push("e.png".into()); + assert_eq!(names(&mut s), want); + // A missing file sorts by the size the document keeps of it. + std::fs::remove_file(dir.file("a.png")).unwrap(); + assert_eq!(names(&mut s), want); + // A modified file sorts by its size now. + let bigger = png(900, 900, BLUE); + assert!(bigger.len() > files[0].1.len()); + write(&dir.file("c.png"), &bigger); + let got = names(&mut s); + assert_eq!(got[got.len() - 2..], ["c.png".to_string(), "e.png".to_string()]); } #[test] diff --git a/crates/ui-egui/src/i18n/bg.tsv b/crates/ui-egui/src/i18n/bg.tsv index 28944173dd..a736f0afb7 100644 --- a/crates/ui-egui/src/i18n/bg.tsv +++ b/crates/ui-egui/src/i18n/bg.tsv @@ -3378,6 +3378,7 @@ digits Malayalam Малаялам Solid Плътен Sort by Kind Сортиране по вид Sort by Name Сортиране по име + Sort by Size Сортиране по размер Sort by Status Сортиране по състояние Source code on GitHub Изходен код в GitHub Source Sans 3 Source Sans 3 diff --git a/crates/ui-egui/src/i18n/bs.tsv b/crates/ui-egui/src/i18n/bs.tsv index 01b90e5148..491d47b3e5 100644 --- a/crates/ui-egui/src/i18n/bs.tsv +++ b/crates/ui-egui/src/i18n/bs.tsv @@ -2246,6 +2246,7 @@ digits Malayalam Malajalam @msg paths entry {i} needs path and ids (object ids no other entry has) unos {i} u paths treba path i ids (ID-ove objekata koje nema nijedan drugi unos) @msg scope missingInFolder takes path: the folder of that file is searched for the other missing links scope missingInFolder uzima path: u folderu te datoteke traže se ostale nedostajuće veze Show Missing Prikaži nedostajuće + Sort by Size Sortiraj po veličini Sort by Status Sortiraj po statusu Clear Overrides Očisti zamjene Create New {kind} Style Kreiraj novi {kind} stil diff --git a/crates/ui-egui/src/i18n/ca.tsv b/crates/ui-egui/src/i18n/ca.tsv index 4ddd1d5605..7d429cba40 100644 --- a/crates/ui-egui/src/i18n/ca.tsv +++ b/crates/ui-egui/src/i18n/ca.tsv @@ -4407,6 +4407,7 @@ digits Malayalam Malaiàlam Sort by Luminance Ordena per lluminositat Sort by Name Ordena per nom Sort by Popularity Ordena per popularitat + Sort by Size Ordena per mida Sort by Status Ordena per estat Sort Swatches Ordena les mostres Source code on GitHub Codi font a GitHub diff --git a/crates/ui-egui/src/i18n/cs.tsv b/crates/ui-egui/src/i18n/cs.tsv index 211982f086..56beb650a6 100644 --- a/crates/ui-egui/src/i18n/cs.tsv +++ b/crates/ui-egui/src/i18n/cs.tsv @@ -2277,6 +2277,7 @@ digits Malayalam Malajálamské @msg paths entry {i} needs path and ids (object ids no other entry has) položka {i} v paths potřebuje path a ids (ID objektů, které nemá žádná jiná položka) @msg scope missingInFolder takes path: the folder of that file is searched for the other missing links scope missingInFolder bere path: ve složce tohoto souboru se hledají ostatní chybějící propojení Show Missing Zobrazit chybějící + Sort by Size Seřadit podle velikosti Sort by Status Seřadit podle stavu Clear Overrides Vymazat přepsání Create New {kind} Style Vytvořit nový styl ({kind}) diff --git a/crates/ui-egui/src/i18n/da.tsv b/crates/ui-egui/src/i18n/da.tsv index b3de0ae89a..c40e8ba109 100644 --- a/crates/ui-egui/src/i18n/da.tsv +++ b/crates/ui-egui/src/i18n/da.tsv @@ -2077,6 +2077,7 @@ digits Malayalam Malayalam @msg paths entry {i} needs path and ids (object ids no other entry has) post {i} i paths skal have path og ids (objekt-id'er, som ingen anden post har) @msg scope missingInFolder takes path: the folder of that file is searched for the other missing links scope missingInFolder tager path: der søges efter de andre manglende links i den fils mappe Show Missing Vis manglende + Sort by Size Sortér efter størrelse Sort by Status Sortér efter status Clear Overrides Ryd tilsidesættelser Create New {kind} Style Opret ny {kind}-typografi diff --git a/crates/ui-egui/src/i18n/de.tsv b/crates/ui-egui/src/i18n/de.tsv index d0610144ef..f4b89ab2bf 100644 --- a/crates/ui-egui/src/i18n/de.tsv +++ b/crates/ui-egui/src/i18n/de.tsv @@ -3441,6 +3441,7 @@ effect Points Punkte Solid Gefüllt Sort by Kind Nach Art sortieren Sort by Name Nach Name sortieren + Sort by Size Nach Größe sortieren Sort by Status Nach Status sortieren Source code on GitHub Quellcode auf GitHub Source Sans 3 Source Sans 3 diff --git a/crates/ui-egui/src/i18n/el.tsv b/crates/ui-egui/src/i18n/el.tsv index d03f8c6958..df26f8c952 100644 --- a/crates/ui-egui/src/i18n/el.tsv +++ b/crates/ui-egui/src/i18n/el.tsv @@ -3997,6 +3997,7 @@ digits Malayalam Μαλαγιάλαμ Social Square Post 1080×1080 Τετράγωνη δημοσίευση κοινωνικών δικτύων 1080×1080 Sort by Kind Ταξινόμηση κατά είδος Sort by Name Ταξινόμηση κατά όνομα + Sort by Size Ταξινόμηση κατά μέγεθος Sort by Status Ταξινόμηση κατά κατάσταση Source code on GitHub Πηγαίος κώδικας στο GitHub Space After Paragraph Διάστημα μετά την παράγραφο diff --git a/crates/ui-egui/src/i18n/es.tsv b/crates/ui-egui/src/i18n/es.tsv index 3e8bd23752..4d6a5ccbf7 100644 --- a/crates/ui-egui/src/i18n/es.tsv +++ b/crates/ui-egui/src/i18n/es.tsv @@ -3471,6 +3471,7 @@ digits Malayalam Malayálam Solid Sólido Sort by Kind Ordenar por tipo Sort by Name Ordenar por nombre + Sort by Size Ordenar por tamaño Sort by Status Ordenar por estado Source code on GitHub Código fuente en GitHub Source Sans 3 Source Sans 3 diff --git a/crates/ui-egui/src/i18n/fi.tsv b/crates/ui-egui/src/i18n/fi.tsv index d408220f47..8a070b02a7 100644 --- a/crates/ui-egui/src/i18n/fi.tsv +++ b/crates/ui-egui/src/i18n/fi.tsv @@ -2238,6 +2238,7 @@ digits Malayalam Malajalam @msg paths entry {i} needs path and ids (object ids no other entry has) paths-merkintä {i} tarvitsee path- ja ids-arvot (objektitunnukset, joita millään muulla merkinnällä ei ole) @msg scope missingInFolder takes path: the folder of that file is searched for the other missing links scope missingInFolder ottaa path-arvon: muita puuttuvia linkkejä haetaan tämän tiedoston kansiosta Show Missing Näytä puuttuvat + Sort by Size Lajittele koon mukaan Sort by Status Lajittele tilan mukaan Clear Overrides Tyhjennä ohitukset Create New {kind} Style Luo uusi tyyli: {kind} diff --git a/crates/ui-egui/src/i18n/fr.tsv b/crates/ui-egui/src/i18n/fr.tsv index 318bbbeb44..e1358f294b 100644 --- a/crates/ui-egui/src/i18n/fr.tsv +++ b/crates/ui-egui/src/i18n/fr.tsv @@ -3463,6 +3463,7 @@ digits Malayalam Malayalam Solid Plein Sort by Kind Trier par type Sort by Name Trier par nom + Sort by Size Trier par taille Sort by Status Trier par état Source code on GitHub Code source sur GitHub Source Sans 3 Source Sans 3 diff --git a/crates/ui-egui/src/i18n/hi.tsv b/crates/ui-egui/src/i18n/hi.tsv index 78c0a9a7eb..cd1e5aad83 100644 --- a/crates/ui-egui/src/i18n/hi.tsv +++ b/crates/ui-egui/src/i18n/hi.tsv @@ -4765,6 +4765,7 @@ antiAlias Sharp शार्प Sort by Luminance द्वारा क्रमबद्ध Luminance Sort by Name नाम से क्रमबद्ध करें Sort by Popularity लोकप्रियता द्वारा क्रमबद्ध + Sort by Size आकार द्वारा क्रमबद्ध Sort by Status स्थिति द्वारा क्रमबद्ध Sort By: द्वारा क्रमबद्ध: Sort Objects ऑब्जेक्ट्स को क्रमबद्ध करें diff --git a/crates/ui-egui/src/i18n/hu.tsv b/crates/ui-egui/src/i18n/hu.tsv index a1f6100b2f..b599e5f1e4 100644 --- a/crates/ui-egui/src/i18n/hu.tsv +++ b/crates/ui-egui/src/i18n/hu.tsv @@ -4123,6 +4123,7 @@ mark-style Japanese Japán Sort by Luminance Rendezés fénysűrűség szerint Sort by Name Rendezés név szerint Sort by Popularity Rendezés gyakoriság szerint + Sort by Size Rendezés méret szerint Sort by Status Rendezés állapot szerint Source code on GitHub Forráskód a GitHubon Source Image Forráskép diff --git a/crates/ui-egui/src/i18n/id.tsv b/crates/ui-egui/src/i18n/id.tsv index c7c6b956db..b04fedeafc 100644 --- a/crates/ui-egui/src/i18n/id.tsv +++ b/crates/ui-egui/src/i18n/id.tsv @@ -2077,6 +2077,7 @@ digits Malayalam Malayalam @msg paths entry {i} needs path and ids (object ids no other entry has) entri paths {i} memerlukan path dan ids (id objek yang tidak dimiliki entri lain) @msg scope missingInFolder takes path: the folder of that file is searched for the other missing links scope missingInFolder menerima path: tautan hilang lainnya dicari di folder file tersebut Show Missing Tampilkan yang hilang + Sort by Size Urutkan berdasarkan ukuran Sort by Status Urutkan berdasarkan status Clear Overrides Hapus penimpaan Create New {kind} Style Buat gaya {kind} baru diff --git a/crates/ui-egui/src/i18n/it.tsv b/crates/ui-egui/src/i18n/it.tsv index 6743704785..2485893186 100644 --- a/crates/ui-egui/src/i18n/it.tsv +++ b/crates/ui-egui/src/i18n/it.tsv @@ -3516,6 +3516,7 @@ digits Malayalam Malayalam Solid Pieno Sort by Kind Ordina per tipo Sort by Name Ordina per nome + Sort by Size Ordina per dimensione Sort by Status Ordina per stato Source code on GitHub Codice sorgente su GitHub Source Sans 3 Source Sans 3 diff --git a/crates/ui-egui/src/i18n/ja.tsv b/crates/ui-egui/src/i18n/ja.tsv index c9cdb8fcbe..83b8ea1bc6 100644 --- a/crates/ui-egui/src/i18n/ja.tsv +++ b/crates/ui-egui/src/i18n/ja.tsv @@ -4023,6 +4023,7 @@ file-filter Templates テンプレート Small Thumbnails 小さいサムネール Smooth Color スムーズカラー Social Square Post 1080×1080 ソーシャル正方形投稿 1080×1080 + Sort by Size サイズ順に並べ替え Sort by Status 状態順に並べ替え Specified Distance 距離 Specified Steps ステップ数 diff --git a/crates/ui-egui/src/i18n/ka.tsv b/crates/ui-egui/src/i18n/ka.tsv index 55f726dc38..ac3456b931 100644 --- a/crates/ui-egui/src/i18n/ka.tsv +++ b/crates/ui-egui/src/i18n/ka.tsv @@ -2005,6 +2005,7 @@ digits Malayalam მალაიალამური @msg paths entry {i} needs path and ids (object ids no other entry has) paths-ის ჩანაწერს {i} სჭირდება path და ids (ობიექტის ID-ები, რომლებიც სხვა ჩანაწერს არ აქვს) @msg scope missingInFolder takes path: the folder of that file is searched for the other missing links scope missingInFolder იღებს path-ს: სხვა დაკარგული ბმულები ამ ფაილის საქაღალდეში იძებნება Show Missing დაკარგულების ჩვენება + Sort by Size ზომის მიხედვით სორტირება Sort by Status სტატუსის მიხედვით სორტირება Clear Overrides ცვლილებების გასუფთავება Create New {kind} Style ახალი სტილის შექმნა ({kind}) diff --git a/crates/ui-egui/src/i18n/ko.tsv b/crates/ui-egui/src/i18n/ko.tsv index abe2b4bc28..479c35ed50 100644 --- a/crates/ui-egui/src/i18n/ko.tsv +++ b/crates/ui-egui/src/i18n/ko.tsv @@ -4011,6 +4011,7 @@ file-filter Templates 템플릿 Small Thumbnails 작은 축소판 Smooth Color 부드러운 색상 Social Square Post 1080×1080 소셜 정사각형 게시물 1080×1080 + Sort by Size 크기순 정렬 Sort by Status 상태순 정렬 Specified Distance 지정 거리 Specified Steps 지정 단계 diff --git a/crates/ui-egui/src/i18n/nl.tsv b/crates/ui-egui/src/i18n/nl.tsv index ed281382a4..70f3a6aad8 100644 --- a/crates/ui-egui/src/i18n/nl.tsv +++ b/crates/ui-egui/src/i18n/nl.tsv @@ -2595,6 +2595,7 @@ digits Malayalam Malayalam @msg paths entry {i} needs path and ids (object ids no other entry has) item {i} van paths heeft path en ids nodig (object-id's die geen ander item heeft) @msg scope missingInFolder takes path: the folder of that file is searched for the other missing links scope missingInFolder neemt path: in de map van dat bestand wordt naar de andere ontbrekende koppelingen gezocht Show Missing Ontbrekende weergeven + Sort by Size Sorteren op grootte Sort by Status Sorteren op status Clear Overrides Onderdrukkingen wissen Create New {kind} Style Nieuwe {kind}stijl maken diff --git a/crates/ui-egui/src/i18n/pl.tsv b/crates/ui-egui/src/i18n/pl.tsv index 08e96e6a35..5d3de88c7a 100644 --- a/crates/ui-egui/src/i18n/pl.tsv +++ b/crates/ui-egui/src/i18n/pl.tsv @@ -2196,6 +2196,7 @@ digits Malayalam Malajalam @msg paths entry {i} needs path and ids (object ids no other entry has) wpis {i} w paths wymaga path i ids (identyfikatorów obiektów, których nie ma żaden inny wpis) @msg scope missingInFolder takes path: the folder of that file is searched for the other missing links scope missingInFolder przyjmuje path: w folderze tego pliku szukane są pozostałe brakujące łącza Show Missing Pokaż brakujące + Sort by Size Sortuj według rozmiaru Sort by Status Sortuj według stanu Clear Overrides Wyczyść zastąpienia Create New {kind} Style Utwórz nowy styl: {kind} diff --git a/crates/ui-egui/src/i18n/pt-br.tsv b/crates/ui-egui/src/i18n/pt-br.tsv index 79c4d9dc8e..767c78ff24 100644 --- a/crates/ui-egui/src/i18n/pt-br.tsv +++ b/crates/ui-egui/src/i18n/pt-br.tsv @@ -5201,6 +5201,7 @@ axis Both Ambos Corner Canto Smooth Color Cor Suave Social Square Post 1080×1080 Post Social Quadrado 1080×1080 + Sort by Size Ordenar por Tamanho Sort by Status Ordenar por Status Source Sans 3 Source Sans 3 Specified Distance Distância Especificada diff --git a/crates/ui-egui/src/i18n/ru.tsv b/crates/ui-egui/src/i18n/ru.tsv index 9f608618e7..5c41fea970 100644 --- a/crates/ui-egui/src/i18n/ru.tsv +++ b/crates/ui-egui/src/i18n/ru.tsv @@ -3503,6 +3503,7 @@ digits Malayalam Малаялам Solid Сплошной Sort by Kind Сортировать по типу Sort by Name Сортировать по имени + Sort by Size Сортировать по размеру Sort by Status Сортировать по состоянию Source code on GitHub Исходный код на GitHub Source Sans 3 Source Sans 3 diff --git a/crates/ui-egui/src/i18n/sv.tsv b/crates/ui-egui/src/i18n/sv.tsv index 6156ca23d5..cff877a7ad 100644 --- a/crates/ui-egui/src/i18n/sv.tsv +++ b/crates/ui-egui/src/i18n/sv.tsv @@ -3393,6 +3393,7 @@ digits Malayalam Malayalam Solid Enfärgad Sort by Kind Sortera efter typ Sort by Name Sortera efter namn + Sort by Size Sortera efter storlek Sort by Status Sortera efter status Source code on GitHub Källkod på GitHub Source Sans 3 Source Sans 3 diff --git a/crates/ui-egui/src/i18n/tr.tsv b/crates/ui-egui/src/i18n/tr.tsv index 7120d44707..907fc4f9a6 100644 --- a/crates/ui-egui/src/i18n/tr.tsv +++ b/crates/ui-egui/src/i18n/tr.tsv @@ -3267,6 +3267,7 @@ digits Malayalam Malayalam Solid Katı Sort by Kind Türe göre sırala Sort by Name Ada Göre Sırala + Sort by Size Boyuta göre sırala Sort by Status Duruma göre sırala Source code on GitHub GitHub'daki kaynak kodu Source Sans 3 Kaynak Sans 3 diff --git a/crates/ui-egui/src/i18n/uk.tsv b/crates/ui-egui/src/i18n/uk.tsv index 84f296b0a6..c78b864c2d 100644 --- a/crates/ui-egui/src/i18n/uk.tsv +++ b/crates/ui-egui/src/i18n/uk.tsv @@ -3509,7 +3509,8 @@ effect Points Точки Solid Суцільний Sort by Kind Сортувати за типом Sort by Name Сортувати за назвою - Sort by Status Сортувати за: + Sort by Size Сортувати за розміром + Sort by Status Сортувати за станом Source code on GitHub Вихідний код GitHub Source Sans 3 Source Sans 3 Space After Paragraph Інтервал після абзацу diff --git a/crates/ui-egui/src/i18n/vi.tsv b/crates/ui-egui/src/i18n/vi.tsv index e8b9e5758f..27355ae856 100644 --- a/crates/ui-egui/src/i18n/vi.tsv +++ b/crates/ui-egui/src/i18n/vi.tsv @@ -3857,6 +3857,7 @@ mark-style Japanese Kiểu Nhật Sort Sắp xếp Sort by Kind Sắp xếp theo loại Sort by Name Sắp xếp theo tên + Sort by Size Sắp xếp theo kích thước Sort by Status Sắp xếp theo trạng thái Source code on GitHub Mã nguồn trên GitHub Source Image Ảnh nguồn diff --git a/crates/ui-egui/src/i18n/zh-hans.tsv b/crates/ui-egui/src/i18n/zh-hans.tsv index 719968086f..cd2c86aa1e 100644 --- a/crates/ui-egui/src/i18n/zh-hans.tsv +++ b/crates/ui-egui/src/i18n/zh-hans.tsv @@ -3332,6 +3332,7 @@ digits Malayalam 马拉雅拉姆数字 Solid 实心 Sort by Kind 按类型排序 Sort by Name 按名称排序 + Sort by Size 依大小排序 Sort by Status 依状态排序 Source code on GitHub GitHub 源代码 Source Sans 3 Source Sans 3 diff --git a/crates/ui-egui/src/i18n/zh-hant.tsv b/crates/ui-egui/src/i18n/zh-hant.tsv index 121a8b8c02..e5dd468d37 100644 --- a/crates/ui-egui/src/i18n/zh-hant.tsv +++ b/crates/ui-egui/src/i18n/zh-hant.tsv @@ -4589,6 +4589,7 @@ digits Malayalam 馬來亞拉姆數字 Solid 實心 Sort by Kind 依類型排序 Sort by Name 依名稱排序 + Sort by Size 依大小排序 Sort by Status 依狀態排序 Source code on GitHub GitHub 上的原始碼 Source Sans 3 Source Sans 3 diff --git a/crates/ui-egui/src/panels/links.rs b/crates/ui-egui/src/panels/links.rs index f9d9b524c9..244a67ddb8 100644 --- a/crates/ui-egui/src/panels/links.rs +++ b/crates/ui-egui/src/panels/links.rs @@ -29,7 +29,7 @@ pub const ID: &str = "links"; /// Seconds between two looks at the linked files (they change outside the app). const RECHECK: f64 = 2.0; const SHOW: [(&str, &str); 4] = [("all", "Show All"), ("missing", "Show Missing"), ("modified", "Show Modified"), ("embedded", "Show Embedded")]; -const SORT: [(&str, &str); 3] = [("name", "Sort by Name"), ("kind", "Sort by Kind"), ("status", "Sort by Status")]; +const SORT: [(&str, &str); 4] = [("name", "Sort by Name"), ("kind", "Sort by Kind"), ("status", "Sort by Status"), ("size", "Sort by Size")]; const THUMBS: [(f32, &str); 4] = [(0.0, "No Thumbnails"), (18.0, "Small Thumbnails"), (28.0, "Medium Thumbnails"), (44.0, "Large Thumbnails")]; /// The panel's options (flyout). diff --git a/crates/ui-egui/src/panels/tests_links.rs b/crates/ui-egui/src/panels/tests_links.rs index 6b773e9d3b..8b3e065a64 100644 --- a/crates/ui-egui/src/panels/tests_links.rs +++ b/crates/ui-egui/src/panels/tests_links.rs @@ -90,8 +90,16 @@ fn the_panel_lists_the_images_with_link_info_for_the_selected_one() { assert!(text.contains("Linked") && text.contains("300 × 200 px") && text.contains("Location"), "{text}"); // The flyout draws with every item. let menu = painted_text(&mut app, super::links::menu); - for item in ["Relink to Folder…", "Embed Image(s)", "Placement Options…", "Show Missing", "Sort by Status", "Large Thumbnails", "Show in Folder"] - { + for item in [ + "Relink to Folder…", + "Embed Image(s)", + "Placement Options…", + "Show Missing", + "Sort by Status", + "Sort by Size", + "Large Thumbnails", + "Show in Folder", + ] { assert!(menu.contains(item), "{item}: {menu}"); } } diff --git a/docs/mcp.md b/docs/mcp.md index 2e43c14d0e..b844faca6d 100644 --- a/docs/mcp.md +++ b/docs/mcp.md @@ -7434,8 +7434,10 @@ listed in `warnings`. ASCII and binary DXF files are read; DWG files answer an e ## Links panel -`links.list {show?: all|missing|modified|embedded, sort?: name|kind|status}` lists every image in the layers, top -first, as the Links panel does, then every image and placed document in opacity-mask art and in the art of symbols, +`links.list {show?: all|missing|modified|embedded, sort?: name|kind|status|size}` lists every image in the layers, top +first, as the Links panel does (`sort: "size"`, the panel menu's Sort by Size, puts the smallest file first by the +size Link Info shows; rows without one, embedded images and missing files whose size is not kept, come last, and equal +sizes go by name), then every image and placed document in opacity-mask art and in the art of symbols, graph designs, patterns and stored brushes, one row per stored object (never one per symbol instance, pattern tile or brushed stroke): `{id, name, linked, status: ok|modified|missing|embedded, format, pixelWidth, pixelHeight, path?, found?, page?, preview?, note?, owner?}` (`owner`, for an object outside the layer tree: diff --git a/docs/target-app-parity.md b/docs/target-app-parity.md index c6375f3aa3..80a3ab8623 100644 --- a/docs/target-app-parity.md +++ b/docs/target-app-parity.md @@ -1850,6 +1850,7 @@ Moved from the ROADMAP's "Shipped so far" on 2026-10-10. Update it when a featur - On Windows, a document opened from a mapped network drive finds its links stored with the share's own path (`\\server\share\…`), as the same document opened from the share does; links on other computers stay missing. - On Windows, a link on a drive mapped to a network share other than the document's (`Y:\…`) is missing, with the reason that the path is on another computer, as a link stored with that share's own path is; links on this computer's drives and on the document's share are followed. - In the Links panel, Shift-click selects a range of links and Ctrl/Cmd-click adds or removes one. + - The Links panel menu's Sort by Size ([Links panel](https://helpx.adobe.com/illustrator/desktop/add-and-import-files/import-from-other-apps/links-panel-in-illustrator.html)) lists the links by file size, smallest first (`links.list {sort: "size"}`). VectorCraft's own rules: a file's size is the one Link Info shows, rows without one (embedded images, a missing file whose size the document does not keep) come last, and equal sizes go by name. - When a document opens with notes and with linked files that changed on disk (Update Links: Manually) or, on the web, can't be read, the status bar shows the line about the linked files, then counts the notes and names the first, and hovering it lists the notes. The same holds when the line about modified files follows the Linked File Not Found dialog, and File › New from Template… shows the notes of the file it opens as File › Open does (`an_open_with_modified_links_keeps_link_notice_and_import_notes_reachable`, `new_from_template_preserves_open_warnings`, `an_open_with_unreadable_links_keeps_import_notes_reachable`, `modified_links_after_the_missing_ones_keep_the_open_notes`, `combined_open_and_link_status_lists_notes_on_hover_and_for_accessibility`). - On the web, when a document opens with linked files that can't be read and linked files that changed on disk (Update Links: Manually), the status bar shows the line about the unreadable files, and the line about the changed files is the first of the notes its hover lists, ahead of the open's notes. With Ask When Modified the update question opens and the line about the unreadable files stays (`a_web_open_with_unreadable_and_modified_links_keeps_both_lines`). - Linked images and placed documents kept only in symbols, graph designs, patterns or opacity masks are listed in the Links panel after the layers' own, one row per stored object, with their status in its Missing and Modified filters, in Check Links, in the missing and modified files reported when a document opens, in the link watch and in Find in Folder; Relink, Update, Embed, Placement Options and Link Info act on them, and Go To says they have no place on the canvas. Opening a document gives such an object whose id is 0 or repeats another object's a new id.