forked from 1b-agent/opencadstudio-upstream
web: XREFs, data links & extraction, ARCHIVE transmittals, worker-side saves
The last four big web-vs-desktop gaps.
XREFs: XATTACH reads the picked drawing's bytes and registers them
name-keyed (the image/PDF-underlay pattern), pre-parses on the web
worker, and the commit merge produces the same xref block flow as
native. Opened drawings resolve xrefs from the registry (trailing-name
match) before cache build; unresolved references produce ONE warning
listing the names and the fix — drop the referenced files on the page
(drops and picker opens now register their bytes) and reopen or
XRELOAD. XRELOAD works off the registry on unsaved drawings too.
Data Link & Extraction: spreadsheet links read picked xlsx/csv bytes
(calamine from slices / CSV from string) through a session registry,
so preview, refresh, and table-insert work on web; extraction takes
external drawings via a multi-file picker parsed on the worker, and
outputs CSV/TXT/.dxex via download_bytes. The disabled 'Add folder'
button explains why.
ARCHIVE/ETRANSMIT: assembles the drawing plus registered images, PDF
underlays, and session plot tables into a deterministic ZIP (minimal
writer over flate2 — no new dependency) delivered as
{stem}_transmit.zip; skipped dependencies are reported by name.
Save/autosave off the UI thread: the parse worker gains a serialize
action (protocol v5) — the document is prepared once on the main
thread (clone, styles, dimension bake), then the DWG/DXF writer pass,
the dominant cost, runs on the worker; any worker failure falls back
to inline serialization with the identical shared implementation.
The save path also clears the dirty flag only when the tab didn't
change mid-write, and the runtime-fields sidecar now carries
graphic_data, fixing a pre-existing loss of raw DWG round-trip bytes
on web-opened documents.
This commit is contained in:
1 parent
c643a10ed9
commit
2e1006348b
44 files changed
+2564
-330
No files matched your search
+80
-26
@@ -1143,26 +1143,46 @@ impl OpenCADStudio {
|
||||
|
||||
Task::none()
|
||||
}
|
||||
Message::XAttachPick => Task::perform(
|
||||
async {
|
||||
let handle = crate::sys::file_dialog()
|
||||
.set_title(crate::t!("Select External Reference File").as_ref())
|
||||
.add_filter(
|
||||
crate::t!("CAD Files").as_ref(),
|
||||
&["dwg", "dxf", "bak", "DWG", "DXF", "BAK"],
|
||||
)
|
||||
.add_filter(crate::t!("DWG Files").as_ref(), &["dwg", "DWG"])
|
||||
.add_filter(crate::t!("DXF Files").as_ref(), &["dxf", "DXF"])
|
||||
.add_filter(crate::t!("Backup Files").as_ref(), &["bak", "BAK"])
|
||||
.pick_file()
|
||||
.await;
|
||||
match handle {
|
||||
Some(h) => Ok(crate::sys::handle_path(&h)),
|
||||
None => Err("Cancelled".to_string()),
|
||||
}
|
||||
},
|
||||
Message::XAttachPickResult,
|
||||
),
|
||||
Message::XAttachPick => {
|
||||
// Web: the browser hands back bytes, not a path — read them,
|
||||
// register them name-keyed (so reloads and re-opens of the
|
||||
// host drawing re-resolve the xref in-session) and pre-parse
|
||||
// on the worker in one step. The returned name-only PathBuf
|
||||
// is what the native branch's `handle_path` yields there.
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
{
|
||||
Task::perform(
|
||||
crate::io::pick_and_register_xref_web(),
|
||||
Message::XAttachPickResult,
|
||||
)
|
||||
}
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
{
|
||||
Task::perform(
|
||||
async {
|
||||
let handle = crate::sys::file_dialog()
|
||||
.set_title(crate::t!("Select External Reference File").as_ref())
|
||||
.add_filter(
|
||||
crate::t!("CAD Files").as_ref(),
|
||||
&["dwg", "dxf", "bak", "DWG", "DXF", "BAK"],
|
||||
)
|
||||
.add_filter(crate::t!("DWG Files").as_ref(), &["dwg", "DWG"])
|
||||
.add_filter(crate::t!("DXF Files").as_ref(), &["dxf", "DXF"])
|
||||
.add_filter(
|
||||
crate::t!("Backup Files").as_ref(),
|
||||
&["bak", "BAK"],
|
||||
)
|
||||
.pick_file()
|
||||
.await;
|
||||
match handle {
|
||||
Some(h) => Ok(crate::sys::handle_path(&h)),
|
||||
None => Err("Cancelled".to_string()),
|
||||
}
|
||||
},
|
||||
Message::XAttachPickResult,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Message::XAttachPickResult(Ok(path)) => {
|
||||
use crate::command::CadCommand;
|
||||
@@ -1255,9 +1275,13 @@ impl OpenCADStudio {
|
||||
self.on_data_extraction_browse_settings_result(path)
|
||||
}
|
||||
Message::DataExtractionAddDrawings => self.on_data_extraction_add_drawings(),
|
||||
Message::DataExtractionAddDrawingsResult(paths) => {
|
||||
Message::DataExtractionAddDrawingsResult(Ok(paths)) => {
|
||||
self.on_data_extraction_add_drawings_result(paths)
|
||||
}
|
||||
Message::DataExtractionAddDrawingsResult(Err(error)) => {
|
||||
self.data_extraction.error = error;
|
||||
Task::none()
|
||||
}
|
||||
Message::DataExtractionAddFolder => self.on_data_extraction_add_folder(),
|
||||
Message::DataExtractionAddFolderResult(path) => {
|
||||
self.on_data_extraction_add_folder_result(path)
|
||||
@@ -1291,13 +1315,22 @@ impl OpenCADStudio {
|
||||
}
|
||||
|
||||
Message::DataExtractionSaveResult(csv, Some(path)) => {
|
||||
match std::fs::write(&path, csv.as_bytes()) {
|
||||
let fname = path
|
||||
.file_name()
|
||||
.map(|n| n.to_string_lossy().into_owned())
|
||||
.unwrap_or_else(|| path.to_string_lossy().into_owned());
|
||||
// The browser has no writable path behind the picked name:
|
||||
// the CSV leaves as a download instead of an fs::write.
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
let write_result: Result<(), String> = {
|
||||
crate::sys::download_bytes(&fname, csv.as_bytes());
|
||||
Ok(())
|
||||
};
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
let write_result = std::fs::write(&path, csv.as_bytes()).map_err(|e| e.to_string());
|
||||
match write_result {
|
||||
Ok(()) => {
|
||||
let rows = csv.lines().count().saturating_sub(1);
|
||||
let fname = path
|
||||
.file_name()
|
||||
.map(|n| n.to_string_lossy().into_owned())
|
||||
.unwrap_or_else(|| path.to_string_lossy().into_owned());
|
||||
self.command_line.push_output(
|
||||
crate::tf!("DATAEXTRACTION {rows} rows → \"{fname}\"").as_ref(),
|
||||
);
|
||||
@@ -8205,6 +8238,27 @@ impl OpenCADStudio {
|
||||
screenshot,
|
||||
} => self.on_web_save_screenshot(tab_id, filename, ext, version, bounds, screenshot),
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
Message::WebSaveSerialized {
|
||||
tab_id,
|
||||
filename,
|
||||
autosave_key,
|
||||
version,
|
||||
geometry_epoch,
|
||||
edit_revision,
|
||||
camera_generation,
|
||||
result,
|
||||
} => self.on_web_save_serialized(
|
||||
tab_id,
|
||||
filename,
|
||||
autosave_key,
|
||||
version,
|
||||
geometry_epoch,
|
||||
edit_revision,
|
||||
camera_generation,
|
||||
result,
|
||||
),
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
Message::SaveFileInUseRetry => self.on_save_file_in_use_retry(),
|
||||
|
||||
|
||||
Reference in new issue
Block a user