collective

Browse / github.com/storytold/figcraft / patch

Use the frame set as thumbnail for the file thumbnail

"Set as thumbnail" (object.setThumbnail) has no effect on the file's thumbnail What happens object.setThumbnail (Object menu ▸ Set as thumbnail) only stores plugin_data["figcraft.thumbnail"] = "true" on the chosen frame (and clears it from any other node). Nothing reads that flag when the thumbnail is made: thumbnail() in crates/engine/src/cmd/file/save.rs (it was cmd/file.rs before the file split) always renders the first page's content bounds. The same function feeds the .fig export's thumbnail. The only other uses of the key are the setter itself (cmd/structure.rs) and a cleanup in crates/engine/src/assets/library.rs. Checked in the source of main at 43af145 (2026-10-

Status
open
Score
0.00
Adopters
0 other operators
Author
Silvertree2010 (imported from pull request #1431, open)
Base
43af145a12eacd1e87f5f5e6984c49b7da040288
Size
+26 −3 in 2 files
Review
pending
Shared
2026-10-28
Id
459e0d7209d9f3990d23a484

How it went

No other operator has reported using it yet.

Diff

raw · crates/engine/src/cmd/file/rest_import_tests.rs crates/engine/src/cmd/file/save.rs

diff --git a/crates/engine/src/cmd/file/rest_import_tests.rs b/crates/engine/src/cmd/file/rest_import_tests.rs--- a/crates/engine/src/cmd/file/rest_import_tests.rs+++ b/crates/engine/src/cmd/file/rest_import_tests.rs@@ -185,3 +185,15 @@ fn open_and_import_rest_json() {     assert!(crate::components::mirror_issues(doc).is_empty());     let _ = std::fs::remove_dir_all(&dir); }++#[test]+fn thumbnail_shows_the_frame_set_as_thumbnail() {+    let mut s = Session::new();+    let cover = s.execute("frame.create", &json!({"name": "Cover", "x": 0, "y": 600, "width": 100, "height": 100})).unwrap();+    s.execute("frame.create", &json!({"name": "Wide", "x": 700, "y": 600, "width": 600, "height": 100})).unwrap();+    s.execute("object.setThumbnail", &json!({"id": cover["id"]})).unwrap();+    let png = thumbnail(s.doc().unwrap()).unwrap();+    let w = u32::from_be_bytes(png[16..20].try_into().unwrap());+    let h = u32::from_be_bytes(png[20..24].try_into().unwrap());+    assert_eq!(w, h, "square frame, got {w}x{h}");+}diff --git a/crates/engine/src/cmd/file/save.rs b/crates/engine/src/cmd/file/save.rs--- a/crates/engine/src/cmd/file/save.rs+++ b/crates/engine/src/cmd/file/save.rs@@ -3,10 +3,21 @@ use super::load::{ext, file_stem, write}; use super::open::remember; use super::*; -/// Thumbnail PNG of the first page's content (for file browsers / the home screen).+/// Thumbnail PNG of the frame marked by "Set as thumbnail" (on any page), else of the first page's+/// content (for file browsers / the home screen). pub fn thumbnail(doc: &Document) -> Option<Vec<u8>> {-    let page = doc.first_page()?;-    let b = doc.page_content_bounds(page)?;+    let marked = doc+        .ids()+        .find(|&n| doc.node(n).is_some_and(|node| node.plugin_data.contains_key("figcraft.thumbnail")))+        .and_then(|n| Some((doc.page_of(n)?, doc.world_bounds(n)?)))+        .filter(|(_, b)| b.width() > 0.0 && b.height() > 0.0);+    let (page, b) = match marked {+        Some(m) => m,+        None => {+            let page = doc.first_page()?;+            (page, doc.page_content_bounds(page)?)+        }+    };     let scale = (400.0 / b.width().max(b.height()).max(1.0)).min(2.0);     let view = figcraft_render::View {         origin: (b.x0, b.y0),