From ddc93d84572105e05a7b4dd5b62eb8f01e2eba89 Mon Sep 17 00:00:00 2001 From: aiongg Date: Mon, 12 Oct 2026 03:57:01 +0000 Subject: [PATCH] Threading: autoflow errors name the command that autoflows text.thread with autoflow reported its autoflow errors as file.place. --- crates/engine/src/cmd/place_text.rs | 17 +++++++++-------- crates/engine/src/cmd/thread.rs | 4 ++-- crates/engine/src/lib.rs | 2 +- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/crates/engine/src/cmd/place_text.rs b/crates/engine/src/cmd/place_text.rs index b93f2b9ff..5bbb59ac1 100644 --- a/crates/engine/src/cmd/place_text.rs +++ b/crates/engine/src/cmd/place_text.rs @@ -124,24 +124,25 @@ fn fit(d: &Document, sid: StoryId) -> (Option, usize, usize) { } /// Thread new frames on new pages (margin rectangles) until the story fits. Returns pages added. -/// A story on a parent spread doesn't autoflow: its frames thread only on that parent. -pub(crate) fn autoflow(d: &mut Document, sid: StoryId, max_pages: usize) -> Result { - let last = d.story(sid).and_then(|s| s.frames.last().copied()).ok_or_else(|| bad("file.place", "the story has no frame"))?; +/// A story on a parent spread doesn't autoflow: its frames thread only on that parent. Errors +/// name `cmd`, the command that autoflows. +pub(crate) fn autoflow(d: &mut Document, sid: StoryId, max_pages: usize, cmd: &str) -> Result { + let last = d.story(sid).and_then(|s| s.frames.last().copied()).ok_or_else(|| bad(cmd, "the story has no frame"))?; if !matches!(d.find(last).map(|l| l.spread), Some(SpreadRef::Doc(_))) { - return Err(bad("file.place", "autoflow works only from a frame on a document page")); + return Err(bad(cmd, "autoflow works only from a frame on a document page")); } let mut added = 0; loop { let (overset, held, full) = fit(d, sid); let Some(at) = overset else { return Ok(added) }; if added >= max_pages { - return Err(bad("file.place", format!("autoflow stopped after {max_pages} pages"))); + return Err(bad(cmd, format!("autoflow stopped after {max_pages} pages"))); } let len = d.story(sid).map_or(0, |s| s.len()); // Frames still needed at the rate the full ones are filled (at least one); with no full // frame to go by yet, one more page. let want = held.checked_div(full).map_or(1, |per_frame| len.saturating_sub(at).div_ceil(per_frame.max(1))).clamp(1, max_pages - added); - let last = *d.story(sid).and_then(|s| s.frames.last()).ok_or_else(|| bad("file.place", "the story has no frame"))?; + let last = *d.story(sid).and_then(|s| s.frames.last()).ok_or_else(|| bad(cmd, "the story has no frame"))?; let mut page = d.page_of_item(last).unwrap_or(d.page_count().saturating_sub(1)); let parent = d.page_loc(page).and_then(|(si, pi)| d.spreads[si].pages[pi].parent); d.insert_pages(Some(page), want, parent)?; @@ -149,7 +150,7 @@ pub(crate) fn autoflow(d: &mut Document, sid: StoryId, max_pages: usize) -> Resu let mut prev = last; for _ in 0..want { page += 1; - let (si, pi) = d.page_loc(page).ok_or_else(|| bad("file.place", "page insert failed"))?; + let (si, pi) = d.page_loc(page).ok_or_else(|| bad(cmd, "page insert failed"))?; let r = d.spreads[si].pages[pi].margin_rect(); let (fid, _) = d.add_text_frame(SpreadRef::Doc(si), r, layer, "", ParaFormat::default())?; d.thread(prev, fid)?; @@ -235,7 +236,7 @@ pub(super) fn place_text(s: &mut Session, p: &Value, name: &str, bytes: &[u8]) - *sel = designcraft_doc::Selection::items(vec![fid]); sid }; - let pages = if autoflow_on { autoflow(d, sid, 2000)? } else { 0 }; + let pages = if autoflow_on { autoflow(d, sid, 2000, "file.place")? } else { 0 }; let overset = fit(d, sid).0.is_some(); Ok(json!({"story": sid.0, "pagesAdded": pages, "overset": overset, "warnings": warnings})) }) diff --git a/crates/engine/src/cmd/thread.rs b/crates/engine/src/cmd/thread.rs index 71c877bf8..f215492eb 100644 --- a/crates/engine/src/cmd/thread.rs +++ b/crates/engine/src/cmd/thread.rs @@ -92,7 +92,7 @@ fn thread(s: &mut Session, p: &Value) -> Result { d.check_thread(from, to)?; d.thread_keeping_story(from, to)?; let sid = d.item(from).and_then(|i| i.text_frame()).map(|t| t.story).ok_or_else(|| bad("text.thread", "threading lost the story"))?; - let pages = if autoflow { super::place_text_autoflow(d, sid, AUTOFLOW_MAX_PAGES)? } else { 0 }; + let pages = if autoflow { super::place_text_autoflow(d, sid, AUTOFLOW_MAX_PAGES, "text.thread")? } else { 0 }; *sel = Selection::items(vec![joined]); Ok(json!({"story": sid.0, "from": from.0, "to": to.0, "overset": overset(d, sid), "pagesAdded": pages})) }) @@ -292,7 +292,7 @@ mod tests { let undo = s.doc().unwrap().history.undo.len(); let doc = s.doc().unwrap().doc.clone(); let e = s.execute("text.thread", &json!({"from": a, "rect": [72, 300, 300, 700], "spread": parent, "autoflow": true})).unwrap_err(); - assert!(e.to_string().contains("document page"), "{e}"); + assert!(e.to_string().contains("text.thread"), "{e}"); assert_eq!(s.doc().unwrap().history.undo.len(), undo); assert_eq!(*s.doc().unwrap().doc, *doc); assert_eq!(s.doc().unwrap().doc.page_count(), 2); diff --git a/crates/engine/src/lib.rs b/crates/engine/src/lib.rs index 8f89aefa7..f24750c64 100644 --- a/crates/engine/src/lib.rs +++ b/crates/engine/src/lib.rs @@ -468,7 +468,7 @@ impl Session { } let mut d = (*st.doc).clone(); if overset { - let _ = cmd::place_text_autoflow(&mut d, sid, 500); + let _ = cmd::place_text_autoflow(&mut d, sid, 500, "Smart Text Reflow"); } else { // Drop empty trailing frames on the last pages (one frame, nothing else there). while let Some(story) = d.story(sid) {