Route UI format dispatch through shared registry

This commit is contained in:
Dylan M. Taylor committed 2026-11-13 01:39:41 -05:00
1 parent aff7435b81
commit d373506feb
8 files changed
+26 -23

No files matched your search

Generated
+8 -7
View File
@@ -1144,7 +1144,7 @@ dependencies = [
[[package]]
name = "craft-eps"
version = "0.1.0"
source = "git+https://github.com/storytold/craft-libs?rev=6ba1ca33ca21c33de55ef155141db08ca6048e8d#6ba1ca33ca21c33de55ef155141db08ca6048e8d"
source = "git+https://github.com/storytold/craft-libs?rev=b4ada28f1#b4ada28f19067d4693e902e0e5f32eb292241e3a"
[[package]]
name = "craft-eps"
@@ -1164,10 +1164,10 @@ dependencies = [
[[package]]
name = "craft-file-formats"
version = "0.1.0"
source = "git+https://github.com/storytold/craft-libs?rev=6ba1ca33ca21c33de55ef155141db08ca6048e8d#6ba1ca33ca21c33de55ef155141db08ca6048e8d"
source = "git+https://github.com/storytold/craft-libs?rev=b4ada28f1#b4ada28f19067d4693e902e0e5f32eb292241e3a"
dependencies = [
"craft-eps 0.1.0 (git+https://github.com/storytold/craft-libs?rev=6ba1ca33ca21c33de55ef155141db08ca6048e8d)",
"craft-svg 0.1.0 (git+https://github.com/storytold/craft-libs?rev=6ba1ca33ca21c33de55ef155141db08ca6048e8d)",
"craft-eps 0.1.0 (git+https://github.com/storytold/craft-libs?rev=b4ada28f1)",
"craft-svg 0.1.0 (git+https://github.com/storytold/craft-libs?rev=b4ada28f1)",
]
[[package]]
@@ -1362,9 +1362,9 @@ source = "git+https://github.com/storytold/craft-libs?rev=ba24fe2435adb3c81ad605
[[package]]
name = "craft-svg"
version = "0.1.0"
source = "git+https://github.com/storytold/craft-libs?rev=6ba1ca33ca21c33de55ef155141db08ca6048e8d#6ba1ca33ca21c33de55ef155141db08ca6048e8d"
source = "git+https://github.com/storytold/craft-libs?rev=b4ada28f1#b4ada28f19067d4693e902e0e5f32eb292241e3a"
dependencies = [
"craft-xml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=6ba1ca33ca21c33de55ef155141db08ca6048e8d)",
"craft-xml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=b4ada28f1)",
"flate2",
"kurbo",
"roxmltree 0.21.2",
@@ -1479,7 +1479,7 @@ dependencies = [
[[package]]
name = "craft-xml"
version = "0.1.0"
source = "git+https://github.com/storytold/craft-libs?rev=6ba1ca33ca21c33de55ef155141db08ca6048e8d#6ba1ca33ca21c33de55ef155141db08ca6048e8d"
source = "git+https://github.com/storytold/craft-libs?rev=b4ada28f1#b4ada28f19067d4693e902e0e5f32eb292241e3a"
dependencies = [
"quick-xml 0.41.0",
"thiserror 2.0.21",
@@ -1967,6 +1967,7 @@ name = "designcraft-ui-egui"
version = "0.20.1"
dependencies = [
"craft-dialogs",
"craft-file-formats",
"craft-keymap",
"craft-prepress",
"craft-ui",
+1 -1
View File
@@ -26,7 +26,7 @@ craft-docx = { git = "https://github.com/storytold/craft-libs", rev = "ba24fe243
craft-wordmodel = { git = "https://github.com/storytold/craft-libs", rev = "ba24fe2435adb3c81ad6057faf36365fbba736cf", version = "=0.1.0" }
craft-image-codecs = { git = "https://github.com/storytold/craft-libs", rev = "a47b78256c6acf3d7fdc4bc7cfbc25c373eac522", version = "=0.1.0" }
craft-psd = { git = "https://github.com/storytold/craft-libs", rev = "a47b78256c6acf3d7fdc4bc7cfbc25c373eac522", version = "=0.1.0" }
craft-file-formats = { git = "https://github.com/storytold/craft-libs", rev = "6ba1ca33ca21c33de55ef155141db08ca6048e8d", version = "=0.1.0" }
craft-file-formats = { git = "https://github.com/storytold/craft-libs", rev = "b4ada28f1", version = "=0.1.0" }
# Shared keyboard bindings: chords, overrides, conflicts, egui dispatch, the Keyboard Shortcuts dialog.
craft-keymap = { git = "https://github.com/storytold/craft-libs", rev = "92d392cff132eaf53e13afff77f38b5c11b73aa0", version = "=0.1.0", features = ["egui", "ui"] }
# Separations, ink coverage and the ink manager; same revision as craft-pdf and the krilla patch.
+1 -1
View File
@@ -136,7 +136,7 @@ pub(super) fn export_text(s: &mut Session, p: &Value) -> Result<Value> {
Some(f @ ("rtf" | "tagged")) => f,
Some("txt") | Some("text") => "txt",
Some(f) => return Err(bad(ID, format!("unknown format `{f}` (txt, rtf, tagged)"))),
None if path.is_some_and(|x| x.to_ascii_lowercase().ends_with(".rtf")) => "rtf",
None if path.is_some_and(|x| craft_file_formats::detect(x, &[]) == Some(craft_file_formats::Format::Rtf)) => "rtf",
None => "txt",
};
let text = match format {
+2 -2
View File
@@ -21,7 +21,7 @@ fn save_bytes(d: &Document, preview: Option<&[u8]>) -> Result<Vec<u8>> {
pub fn with_document_extension(path: &str) -> String {
let p = std::path::Path::new(path);
let ext = p.extension().and_then(std::ffi::OsStr::to_str);
if p.file_name().is_none() || ext.is_some_and(|e| e.eq_ignore_ascii_case(designcraft_format::EXTENSION)) {
if p.file_name().is_none() || ext.is_some_and(|e| craft_file_formats::from_extension(e) == Some(craft_file_formats::Format::DesignCraft)) {
return path.to_string();
}
format!("{path}.{}", designcraft_format::EXTENSION)
@@ -32,7 +32,7 @@ pub fn with_document_extension(path: &str) -> String {
/// that kept it would name the file `Brochure.designcraft.designcraft`. A bare `.designcraft` stays.
pub(super) fn without_native_extension(name: &str) -> &str {
match name.rsplit_once('.') {
Some((stem, ext)) if !stem.is_empty() && ext.eq_ignore_ascii_case(designcraft_format::EXTENSION) => stem,
Some((stem, ext)) if !stem.is_empty() && craft_file_formats::from_extension(ext) == Some(craft_file_formats::Format::DesignCraft) => stem,
_ => name,
}
}
+1
View File
@@ -13,6 +13,7 @@ workspace = true
craft-ui = { workspace = true, features = ["native-windows"] }
craft-window = { workspace = true }
craft-keymap = { workspace = true }
craft-file-formats = { workspace = true }
designcraft-geom = { workspace = true }
designcraft-color = { workspace = true }
designcraft-doc = { workspace = true }
+11 -9
View File
@@ -24,7 +24,7 @@ impl DesignApp {
/// Open (`open`) or place (`place`) the file at `path`, chosen in a dialog or passed by a script.
pub(crate) fn open_picked(&mut self, purpose: &str, path: String) -> Result<Value, String> {
// Image Import Options: a multi-page PDF asks which page.
if purpose == "place" && path.to_ascii_lowercase().ends_with(".pdf") {
if purpose == "place" && craft_file_formats::detect(&path, &[]) == Some(craft_file_formats::Format::Pdf) {
let target = self.session.active().map(|d| d.uid);
let pages = self.services.read.as_mut().and_then(|r| r(&path).ok()).and_then(|b| designcraft_render::pdf_page_count(&b)).unwrap_or(1);
if pages > 1 {
@@ -126,7 +126,7 @@ impl DesignApp {
}
fn import_file(&mut self, file: ImportedFile) -> Result<Value, String> {
let lower = file.name.to_ascii_lowercase();
let format = craft_file_formats::detect(&file.name, &file.bytes);
if let Some(kind) = file.request.purpose.strip_prefix("styles") {
self.activate_import_target(&file.request)?;
let mut params = json!({"name": file.name, "base64": designcraft_engine::cmd::base64_encode(&file.bytes)});
@@ -140,11 +140,11 @@ impl DesignApp {
let layout = opens_as_document(&file.name)
|| (std::path::Path::new(&file.name).extension().is_none() && designcraft_engine::cmd::is_document(&file.bytes));
let place =
file.request.purpose == "place" || (matches!(file.request.purpose.as_str(), "drop" | "open") && !layout && !lower.ends_with(".ase"));
if place || lower.ends_with(".ase") || file.request.purpose == "swatches" {
file.request.purpose == "place" || (matches!(file.request.purpose.as_str(), "drop" | "open") && !layout && format != Some(craft_file_formats::Format::Ase));
if place || format == Some(craft_file_formats::Format::Ase) || file.request.purpose == "swatches" {
self.activate_import_target(&file.request)?;
}
if place && lower.ends_with(".pdf") {
if place && craft_file_formats::detect(&file.name, &file.bytes) == Some(craft_file_formats::Format::Pdf) {
let pages = designcraft_render::pdf_page_count(&file.bytes).unwrap_or(1);
if pages > 1 {
self.ui.dialog =
@@ -154,7 +154,7 @@ impl DesignApp {
}
}
let b64 = designcraft_engine::cmd::base64_encode(&file.bytes);
if lower.ends_with(".ase") || file.request.purpose == "swatches" {
if format == Some(craft_file_formats::Format::Ase) || file.request.purpose == "swatches" {
self.run("swatch.load", json!({"base64": b64}))
} else if file.request.purpose == "place" {
self.place_file(json!({"name": file.name, "base64": b64}))
@@ -198,7 +198,7 @@ impl DesignApp {
/// the pointer when there is none, and clears the flag, so the files after it land at the
/// pointer instead of replacing that graphic.
pub(crate) fn place_dropped(&mut self, path: &str, pointer: Option<egui::Pos2>, frame_free: &mut bool) -> Result<Value, String> {
if path.to_ascii_lowercase().ends_with(".ase") {
if craft_file_formats::detect(path, &[]) == Some(craft_file_formats::Format::Ase) {
return self.run("swatch.load", json!({"path": path}));
}
let document = opens_as_document(path)
@@ -318,8 +318,10 @@ impl DesignApp {
/// Files that open as documents (when dropped or picked) rather than being placed: DesignCraft,
/// IDML, and InDesign documents and templates (converted to IDML on open).
pub fn opens_as_document(name: &str) -> bool {
let n = name.to_ascii_lowercase();
[".designcraft", ".idml", ".indd", ".indt"].iter().any(|ext| n.ends_with(ext))
matches!(
craft_file_formats::detect(name, &[]),
Some(craft_file_formats::Format::DesignCraft | craft_file_formats::Format::Idml | craft_file_formats::Format::Indd)
)
}
#[cfg(test)]
+1 -1
View File
@@ -92,7 +92,7 @@ pub(super) fn export_bytes(app: &mut DesignApp, p: &Value, ext: &str, cmd: &str)
_ => json!({}),
};
if cmd == "file.exportText" {
let txt = path.to_ascii_lowercase().ends_with(".txt");
let txt = craft_file_formats::detect(&path, &[]) == Some(craft_file_formats::Format::PlainText);
params["format"] = json!(if txt { "txt" } else { "rtf" });
}
let r = app.run(cmd, params)?;
+1 -2
View File
@@ -142,8 +142,7 @@ fn run_ui_part1(app: &mut DesignApp, id: &str, p: &Value) -> Option<Result<Value
"app.placeWithOptions" => {
// Word/RTF Import Options: style mapping and conflicts before the text lands.
let Some(path) = p.get("path").and_then(Value::as_str) else { return Some(rerun_with_path(app, "place", id, p, "path")) };
let l = path.to_lowercase();
if !(l.ends_with(".docx") || l.ends_with(".rtf")) {
if !matches!(craft_file_formats::detect(path, &[]), Some(craft_file_formats::Format::Docx | craft_file_formats::Format::Rtf)) {
return Some(app.place_file(json!({"path": path})));
}
let info = match app.run("place.styles", json!({"path": path})) {