mirror of
https://github.com/storytold/designcraft.git
synced 2026-11-12 13:24:56 +00:00
Package: a failed package keeps the dialog open; the ink table's Type column; no document is an error
- When `file.package` fails, the Package or Printing Instructions dialog comes back with its options and instructions, and the status line says why. Before, they were lost. - The Colors and Inks table heads its kind column with the "Type:" key (without its colon). The "Type" key is the menu's and reads Text in most languages. - `app.packageDialog` with no document open is an error rather than a silent success. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
d21459ff3e
commit
c04fa61d17
3 files changed
+47
-10
No files matched your search
@@ -3581,8 +3581,22 @@ pub fn confirm(app: &mut DesignApp) -> Result<Value, String> {
|
||||
}
|
||||
"alert" => Ok(Value::Null),
|
||||
crate::effects_dialog::ID => crate::effects_dialog::confirm(app, &d),
|
||||
crate::package_dialog::ID => crate::package_dialog::confirm(app, &d),
|
||||
crate::package_dialog::INSTRUCTIONS => crate::package_dialog::confirm_instructions(app, &d),
|
||||
crate::package_dialog::ID | crate::package_dialog::INSTRUCTIONS => {
|
||||
let r = if d.id == crate::package_dialog::ID {
|
||||
crate::package_dialog::confirm(app, &d)
|
||||
} else {
|
||||
crate::package_dialog::confirm_instructions(app, &d)
|
||||
};
|
||||
// Packaging failed: the dialog stays open with its options and instructions, and the
|
||||
// status line says why.
|
||||
if let Err(e) = &r
|
||||
&& app.ui.dialog.is_none()
|
||||
{
|
||||
app.status(e.clone());
|
||||
app.ui.dialog = Some(d);
|
||||
}
|
||||
r
|
||||
}
|
||||
"findChange" => {
|
||||
let result = if d.b("objectMode") { Ok(Value::Null) } else { app.run("find.change", find_change_params(&d)) };
|
||||
// Confirmation consumes retained bounds before closing, even on an error.
|
||||
|
||||
@@ -1149,10 +1149,7 @@ fn run_ui_inner(app: &mut DesignApp, id: &str, p: &Value) -> Option<Result<Value
|
||||
Ok(Value::Null)
|
||||
}
|
||||
"app.exportText" => export_bytes(app, p, "rtf", "file.exportText"),
|
||||
"app.packageDialog" => {
|
||||
crate::package_dialog::open(app);
|
||||
Ok(Value::Null)
|
||||
}
|
||||
"app.packageDialog" => crate::package_dialog::open(app).map(|()| Value::Null),
|
||||
"app.language" => {
|
||||
let Some(v) = p.get("lang").and_then(Value::as_str) else { return Some(app.run("app.preferences", json!({}))) };
|
||||
if !crate::i18n::LANGUAGES.iter().any(|(c, _)| *c == v) {
|
||||
|
||||
@@ -33,9 +33,9 @@ const INSTRUCTION_FIELDS: [(&str, &str, usize); 7] = [
|
||||
];
|
||||
|
||||
/// Open the Package dialog on its Summary, with the document's fonts, links and spot inks.
|
||||
pub fn open(app: &mut DesignApp) {
|
||||
pub fn open(app: &mut DesignApp) -> Result<(), String> {
|
||||
if app.session.active().is_none() {
|
||||
return;
|
||||
return Err("no document open".into());
|
||||
}
|
||||
let fonts: Vec<Value> = app
|
||||
.session
|
||||
@@ -85,6 +85,7 @@ pub fn open(app: &mut DesignApp) {
|
||||
ID,
|
||||
json!({"page": "summary", "fonts": fonts, "links": links, "spot": spot, "instructions": false, "idml": true, "pdf": false, "problemsOnly": false}),
|
||||
));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn rows(d: &Dialog, key: &str) -> Vec<Value> {
|
||||
@@ -228,7 +229,9 @@ pub fn show(app: &DesignApp, ui: &mut egui::Ui, d: &mut Dialog) {
|
||||
"inks" => {
|
||||
let mut cells: Vec<_> = PROCESS_INKS.iter().map(|n| (vec![tr(n), tr("Process")], None)).collect();
|
||||
cells.extend(rows(d, "spot").iter().filter_map(Value::as_str).map(|n| (vec![n.to_string(), tr("Spot")], None)));
|
||||
table(ui, "package_inks", &[tr("Name"), tr("Type")], &cells);
|
||||
// The ink's kind: the "Type:" key (the "Type" key is the menu's, which reads Text).
|
||||
let kind = tr("Type:").trim_end_matches([':', ':']).trim_end().to_string();
|
||||
table(ui, "package_inks", &[tr("Name"), kind], &cells);
|
||||
}
|
||||
_ => {
|
||||
ui.horizontal(|ui| {
|
||||
@@ -441,7 +444,7 @@ mod tests {
|
||||
let out = dir.join("Packed Folder");
|
||||
let picked = out.to_string_lossy().to_string();
|
||||
app.services.pick_save = Some(Box::new(move |_| Some(picked.clone())));
|
||||
open(&mut app);
|
||||
open(&mut app).unwrap();
|
||||
let mut h = harness(app);
|
||||
h.run_steps(3);
|
||||
h.get_by_label("Include IDML").click();
|
||||
@@ -454,4 +457,27 @@ mod tests {
|
||||
assert!(out.join("Packed.pdf").exists() && !out.join("Packed.idml").exists());
|
||||
std::fs::remove_dir_all(dir).unwrap();
|
||||
}
|
||||
|
||||
/// Packaging that fails (here, into a folder under a file) keeps the dialog open with its
|
||||
/// options, and the status line says why. Without a document there's nothing to open.
|
||||
#[test]
|
||||
fn a_failed_package_keeps_the_dialog_open() {
|
||||
let dir = temp_dir("fails");
|
||||
let mut app = app_with_missing_link(&dir);
|
||||
let blocker = dir.join("blocker");
|
||||
std::fs::write(&blocker, b"a file, not a folder").unwrap();
|
||||
let picked = blocker.join("Packed Folder").to_string_lossy().to_string();
|
||||
app.services.pick_save = Some(Box::new(move |_| Some(picked.clone())));
|
||||
open(&mut app).unwrap();
|
||||
app.ui.dialog.as_mut().unwrap().fields.insert("pdf".into(), json!(true));
|
||||
assert!(crate::dialogs::confirm(&mut app).is_err());
|
||||
let d = app.ui.dialog.as_ref().expect("the dialog stays open");
|
||||
assert_eq!((d.id.as_str(), d.b("pdf")), (ID, true), "with its options");
|
||||
assert!(!app.ui.status.is_empty());
|
||||
app.run("file.close", json!({})).unwrap();
|
||||
app.ui.dialog = None;
|
||||
assert!(app.run("app.packageDialog", json!({})).is_err());
|
||||
assert!(app.ui.dialog.is_none());
|
||||
std::fs::remove_dir_all(dir).unwrap();
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user