This commit is contained in:
bflatastic 2026-10-09 13:57:37 +07:00
commit a27c912f8a
2 changed files with 39 additions and 1 deletions

View File

@ -114,11 +114,17 @@ pub(super) fn show_preview(ui: &mut egui::Ui, tex: Option<&egui::TextureHandle>,
/// Open `bytes` (or place them with the `file.place` params `place`) through the dialog when the
/// file is a PDF (or `.ai`/`.ait`) with several pages or a password; false when there's nothing to
/// ask (the caller goes on).
/// ask (the caller goes on), including a file that carries its VectorCraft document when opening.
pub fn offer(app: &mut VectorcraftApp, name: &str, bytes: &[u8], path: Option<String>, place: Option<&Value>) -> bool {
if !fileio::detect(name, bytes).is_some_and(|f| matches!(f.id, "pdf" | "ai" | "ait")) {
return false;
}
// A file carrying its VectorCraft document (a saved .ai, or a PDF saved with Preserve Editing)
// opens as that document, every artboard and layer: there are no pages to pick. Placing still
// asks, since a place takes one page.
if place.is_none() && vectorcraft_pdf::editing_with(bytes, None).is_some() {
return false;
}
let (pages, locked) = match vectorcraft_pdf::info(bytes, None) {
Ok(i) if i.pages.len() > 1 => (i.pages.len(), false),
Err(PdfError::NeedsPassword) => (0, true),

View File

@ -165,3 +165,35 @@ fn placing_a_pdf_page_asks_for_the_page_and_crop_box() {
assert!(app.ui.dialog.is_none());
assert_eq!(placed(&app).1.width(), 80.0);
}
/// A saved `.ai` with several artboards carries its VectorCraft document: opening it restores that
/// document (artboards, layers) instead of asking which pages to import.
#[test]
fn opening_a_saved_ai_with_several_artboards_restores_it_without_asking() {
let mut app = app();
app.run("artboard.new", json!({"width": 200, "height": 100, "name": "Second"})).unwrap();
app.run("layer.new", json!({"name": "Front"})).unwrap();
app.run("shape.rectangle", json!({"x": 10, "y": 10, "width": 50, "height": 40})).unwrap();
let saved = app.run("document.save", json!({"format": "ai"})).unwrap();
let bytes = vectorcraft_format::base64_decode(saved["dataBase64"].as_str().unwrap()).unwrap();
assert!(vectorcraft_pdf::info(&bytes, None).unwrap().pages.len() > 1, "a page per artboard");
io::open_bytes(&mut app, "two.ai", &bytes, Some("/tmp/two.ai".into())).unwrap();
assert!(app.ui.dialog.is_none(), "no Import PDF dialog");
assert_eq!(app.session.documents().len(), 2);
let doc = &app.session.active().unwrap().doc;
assert_eq!(doc.artboards.len(), 2);
assert_eq!(doc.artboards[1].name, "Second");
assert!(doc.layers.iter().any(|l| l.name.as_deref() == Some("Front")), "layers come back");
}
/// A PDF without a VectorCraft document still asks, and placing a saved `.ai` still asks for the page.
#[test]
fn placing_a_saved_ai_still_asks_for_the_page() {
let mut app = app();
app.run("artboard.new", json!({"width": 200, "height": 100})).unwrap();
let saved = app.run("document.save", json!({"format": "ai"})).unwrap();
let bytes = vectorcraft_format::base64_decode(saved["dataBase64"].as_str().unwrap()).unwrap();
assert!(import_pdf::offer(&mut app, "two.ai", &bytes, None, Some(&json!({}))));
assert_eq!(app.ui.dialog.as_ref().unwrap().str("mode"), "place");
}