From d271298362af27a67c419d3a06caeda58d9a5fb5 Mon Sep 17 00:00:00 2001 From: NetterSilver <133535268+Silvertree2010@users.noreply.github.com> Date: Tue, 20 Oct 2026 14:34:47 +0000 Subject: [PATCH 1/2] Refuse PDF page ranges in the Place PDF dialog instead of using page 1 Fixes #1337 Co-Authored-By: Claude Haiku 5.5 Co-Authored-By: Claude Sonnet 5.5 --- crates/ui-egui/src/dialogs.rs | 8 ++++++++ crates/ui-egui/src/lib.rs | 13 +++++++++++++ 2 files changed, 21 insertions(+) diff --git a/crates/ui-egui/src/dialogs.rs b/crates/ui-egui/src/dialogs.rs index 8b404378..1c0bfcfc 100644 --- a/crates/ui-egui/src/dialogs.rs +++ b/crates/ui-egui/src/dialogs.rs @@ -3268,6 +3268,14 @@ pub fn confirm(app: &mut DesignApp) -> Result { } "pdfImport" => { let crop = d.s("crop"); + if !d.s("page").trim().is_empty() && d.n("page").is_none() { + // A range or list ("4-5", "2,5") is not a page number: refuse it rather than place page 1. + let e = "Enter a single page number; one page is placed at a time".to_string(); + let mut d = d; + d.fields.insert("status".into(), json!(e)); + app.ui.dialog = Some(d); + return Err(e); + } if d.b("async") { return app.confirm_pdf_import(d.n("page").unwrap_or(1.0).max(1.0) as u64, if crop.is_empty() { "crop".into() } else { crop }); } diff --git a/crates/ui-egui/src/lib.rs b/crates/ui-egui/src/lib.rs index cb98cac7..bea9fbfd 100644 --- a/crates/ui-egui/src/lib.rs +++ b/crates/ui-egui/src/lib.rs @@ -2951,6 +2951,19 @@ mod browser_import_tests { assert_eq!(pixels.data().iter().filter(|p| p.r > 240 && p.g < 10 && p.b < 10).count(), 0); } + #[test] + fn pdf_options_refuse_a_page_range_instead_of_placing_page_one() { + for spec in ["4-5", "2,5", "2-3"] { + let mut app = app(); + let request = app.import_request("place"); + deliver(&mut app, request, "three.pdf", pdf()); + app.ui.dialog.as_mut().unwrap().fields.insert("page".into(), json!(spec)); + assert!(dialogs::confirm(&mut app).is_err(), "{spec}"); + assert!(app.session.doc().unwrap().doc.assets.is_empty(), "{spec}"); + assert_eq!(app.ui.dialog.as_ref().unwrap().id, "pdfImport", "{spec}"); + } + } + #[test] fn place_loads_the_cursor_unless_a_frame_can_take_the_graphic() { let mut app = app(); From 0d139559bd721d1bd2b206c3e5b512c5c1ae6c4b Mon Sep 17 00:00:00 2001 From: Brandon Thomas Date: Fri, 23 Oct 2026 17:11:13 -0400 Subject: [PATCH 2/2] Place PDF: the page field takes one whole page number of 1 or more Co-Authored-By: Claude Opus 5.5 --- crates/ui-egui/src/dialogs.rs | 28 ++++++++++++++++++---------- crates/ui-egui/src/lib.rs | 2 +- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/crates/ui-egui/src/dialogs.rs b/crates/ui-egui/src/dialogs.rs index 1c0bfcfc..7651cfff 100644 --- a/crates/ui-egui/src/dialogs.rs +++ b/crates/ui-egui/src/dialogs.rs @@ -3268,21 +3268,29 @@ pub fn confirm(app: &mut DesignApp) -> Result { } "pdfImport" => { let crop = d.s("crop"); - if !d.s("page").trim().is_empty() && d.n("page").is_none() { - // A range or list ("4-5", "2,5") is not a page number: refuse it rather than place page 1. - let e = "Enter a single page number; one page is placed at a time".to_string(); - let mut d = d; - d.fields.insert("status".into(), json!(e)); - app.ui.dialog = Some(d); - return Err(e); - } + // One page number, 1 or more; a blank field is page 1. A range or list ("4-5", "2,5"), a + // fraction or a negative is refused rather than placing some other page. + let raw = if d.fields.get("page").is_none_or(Value::is_null) { String::new() } else { d.s("page") }; + let page = match raw.trim() { + "" => 1, + t => match t.parse::() { + Ok(n) if n >= 1 => n, + _ => { + let e = "Enter a single page number; one page is placed at a time".to_string(); + let mut d = d; + d.fields.insert("status".into(), json!(e)); + app.ui.dialog = Some(d); + return Err(e); + } + }, + }; if d.b("async") { - return app.confirm_pdf_import(d.n("page").unwrap_or(1.0).max(1.0) as u64, if crop.is_empty() { "crop".into() } else { crop }); + return app.confirm_pdf_import(page, if crop.is_empty() { "crop".into() } else { crop }); } if let Some(target) = d.fields.get("target").and_then(Value::as_u64) { app.activate_import_target(&crate::ImportRequest { purpose: "place".into(), target: Some(target) })?; } - app.place_file(json!({"path": d.s("path"), "pdfPage": d.n("page").unwrap_or(1.0).max(1.0) as u64, "pdfCrop": if crop.is_empty() { "crop".to_string() } else { crop }})) + app.place_file(json!({"path": d.s("path"), "pdfPage": page, "pdfCrop": if crop.is_empty() { "crop".to_string() } else { crop }})) } "print" => { let pages = if d.s("range") == "all" { Value::Null } else { json!(d.s("pages")) }; diff --git a/crates/ui-egui/src/lib.rs b/crates/ui-egui/src/lib.rs index bea9fbfd..7f7a650b 100644 --- a/crates/ui-egui/src/lib.rs +++ b/crates/ui-egui/src/lib.rs @@ -2953,7 +2953,7 @@ mod browser_import_tests { #[test] fn pdf_options_refuse_a_page_range_instead_of_placing_page_one() { - for spec in ["4-5", "2,5", "2-3"] { + for spec in ["4-5", "2,5", "2-3", "2.5", "-3", "0", "nan", "inf"] { let mut app = app(); let request = app.import_request("place"); deliver(&mut app, request, "three.pdf", pdf());