Commit Graph
14 Commits
Author SHA1 Message Date
Karim Jerbi 6025d8be44 style: rustfmt the tree so the CI lint check passes 2026-10-15 04:10:06 +01:00
Afonsop db8db14006 feat: web automation wrapper (#1349), DATALINK table on web, System theme; honest decode accounting
Ported from 2c38de53 (#1717). Main already carries the hatch PDF draw
order fix (#1345), the numeric set_properties compare (#1348) and the
web open from bytes, so those parts stay out; what remains:

#1349 — window.ocsControl.ready/request promise wrapper with an
ocs-ready event (web/ocs-control.js, loaded by the web page), and the
startup donation prompt is suppressed once a control request is seen
(opt-in pre-boot via localStorage["opencadstudio.automation"] = "1").
docs/automation/web.md documents both. The control protocol stays at 1.

DATALINK CSV-to-table works on web (picker + bytes through the session
registry — was std::fs, silently dead); COLORSCHEME accepts System
(prefers-color-scheme on web, AppsUseLightTheme on Windows).

Decode accounting, made honest per the fix-of-fix review: into_rgba8
allocates the RGBA destination while the native buffer is alive for
every non-Rgba8 layout (L8 5, La8 6, Rgb8 7, L16 6, La16 8 B/px
peaks — the formula now says so), GIF bills the screen+frame
coexistence at 8 B/px, and TIFF drops the 3x multipliers both ways —
tiff 0.11 splits the given budget between frame and scratch (a total
ceiling), so the old double-billing refused honest 16-bit GeoTIFFs
~2.25x early while admitting hostile chunk transients at 3x.

(cherry picked from commit 2c38de53)
2026-10-12 12:02:05 +03:00
Afonsop 8a5d343927 fix: final pre-PR review sweep
The final holistic + quality audit (three reviewers) returned GO with
four majors; all fixed.

- Start-page recents were the last unguarded writer of the open slot
  on web: clicking one under the open overlay clobbered the in-flight
  open and silently lost its bytes. Refused with the same in-progress
  notice the picker uses.
- The web quit-after-save continuation stalled: a Quit pending now
  survives the tab-save AND continues — offering to save the next
  dirty tab or finishing the quit, mirroring native.
- Data-extraction's multi-file pick is capped (16): every picked file
  becomes a full parsed document held for the session, and one giant
  pick could exhaust the wasm heap.
- The xref registry tests raced each other on the process-global
  registry (reproduced 3/10 at high thread counts — CI roulette); they
  now hold a module-level guard.

Minors: the collision warning is cataloged in all 21 locales; the
docs' parallelism detail header no longer contradicts its own table;
the drop-filter and name-hash helpers gained inline tests (their only
prior coverage was a verbatim copy in the red-team suites).

(cherry picked from commit f70d3fda)

Ported onto main (#1717 review): the collision message is filed under
the file group it is looked up in (it sat under view), the data-link
warning reuses that cataloged text, and the command-reference string
that rode along in the locale hunks stays out.
2026-10-12 12:02:05 +03:00
Afonsop 108ef045b8 web: worker-route WBLOCK/SAVEALL/ARCHIVE; close the follow-up review
WBLOCK, SAVEALL, and web ARCHIVE now serialize through the Web Worker
like SAVE/AUTOSAVE: prepare on the main thread, writer pass on the
worker, inline fallback on any worker failure. SAVEALL clears each
tab's dirty flag under the same unchanged-tab race guard the single
save uses; ARCHIVE assembles the ZIP in the completion handler so the
transmittal matches the snapshot taken at command time.

The review of the previous fix commit found the collision refusal
still REPLACED the registry bytes — the exact silent retargeting it
was meant to prevent. The refusal now keeps the old registration, the
extraction settings picker reports refused picks in the wizard's error
slot (previously silent, and the stale collision flag could surface as
a wrong-file warning on an unrelated browse), and the xref registry's
same-name ambiguity is documented as a browser fundamental (native
distinguishes by folder): newest registration wins consistently for
resolution, ARCHIVE, and XRELOAD — matching what the drawing displays.
Also: the Quit pending-close survives a successful web tab-save
(continue the quit instead of dropping it), the last ZIP64 sentinel
(central size) is rejected like the other four, and the new behaviors
gained regression tests (collision keeps old bytes, registry eviction,
including the deadlock fix for the guard-scoping that test exposed).

(cherry picked from commit b635d56c)

Ported onto main (#1717 review): ARCHIVE and SAVEALL serialize
document_for_save() like a single web Save; the ZIP is built with the
zip crate; WBLOCK keeps its native background-task title.
2026-10-12 12:02:04 +03:00
Afonsop 8968e79942 fix: close the review findings on the last web wave
Full verification of the XREF/data/ARCHIVE/worker wave (three
reviewers, one forensic) found no blockers and no crossfire damage;
five majors and several minors are fixed here.

- ARCHIVE now packages XREFs: the bytes registry added by the same
  commit is consulted (the in-code 'no xref store exists' comment was
  false within the commit), and the drawing is packaged only after
  the full save preparation — without it kernel solids shipped
  without their ACIS data.
- PendingClose stores the stable tab id instead of a vector index:
  the web save now completes asynchronously, and closing a lower tab
  during the serialization window shifted indices — closing the WRONG
  tab, or panicking on a stale one. All producers and consumers
  resolve the id at use.
- The xref bytes registry is capped (6 entries, oldest evicted): every
  open, drop, and pick registered full drawing bytes with no bound —
  an OOM waiting to happen. Reopened recents register too, so any
  entry path can serve as another drawing's xref.
- A re-picked data-link source with the same name but different bytes
  no longer silently replaces the first (the browser hands back bare
  names, so two same-named files collided and every reference read
  the newer pick): the pick is refused and the user is told why.
- The unresolved-xref warning lists file names (what to drop on the
  page), not internal block names; the ZIP writer refused the ZIP64
  sentinel values (0xFFFF counts, 0xFFFFFFFF sizes/offsets) instead
  of emitting archives that send strict readers hunting for a ZIP64
  EOCD that is absent; docs note the worker-side saves.

Known follow-ups documented, not fixed here: the serde-skipped
ExtendedEntity/CadDocument raw bytes still drop on worker crossings
(needs codec accessors — upstream), and WBLOCK/SAVEALL/ARCHIVE
still serialize inline (the worker route is a small follow-up).

(cherry picked from commit 6f429f24)

Ported onto main (#1717 review): main already keys PendingClose by tab
id, so those hunks stay as on main; the ZIP64 guard is moot with the zip
crate; the unresolved-xref names split on both path separators, since
Path does not split Windows paths in the browser build.
2026-10-12 12:02:04 +03:00
Afonsop 61c32c7f74 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 ZIP 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.

(cherry picked from commit 2e100634)

Ported onto main (#1717 review): the new ocs_save crate builds on the
pinned codec; the hand-written ZIP writer is replaced by the zip crate
already in the tree; ARCHIVE packs registered xref bytes too and
serializes document_for_save() like a web Save; the web save prepares
document_for_save() (prepare_document_for_save now takes the copy by
value, so no second clone); the wasm resolve_path consults the xref
registry, so every reference lookup — not just resolve — finds dropped
files; XRELOAD keeps main's undo, unload and stale-baseline handling;
native data extraction streams the source drawings one at a time.
2026-10-12 12:02:04 +03:00
Karim Jerbi 9cf9ff2c5c style: apply cargo fmt across workspace 2026-10-11 03:14:29 +01:00
Hakan SevenandClaude Opus 5.5 34dbc13db0 fix(i18n): named-argument messages no longer print a stray placeholder
Eight messages with %{name} arguments went through the positional
formatter, which printed "%3" for a count, and their catalog entries
held %__ocs_fmt_N__ where the named form is expected. They take named
arguments now, and the entries — and those of the selection and HATCHEDIT
prompts with the same fault — use __ocs_arg_<name>__.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 12:51:33 +03:00
Karim Jerbi a0308dfa88 fix(data-link): clamp cell-range column window to the data width
Bug:
crop_range bounded the row axis with skip/take over the file's real rows
but left the column axis unbounded: c0..=c1 collects one String per
column, and a range like A1:ZZZZZZ1 parses to roughly 308 million
columns, causing a capacity overflow while allocating a row.

Reproduce:
1. Data Link -> pick any CSV/xlsx, set Cell Range to A1:ZZZZZZ1 (or any
   range whose parsed column index is enormous).
2. Before: "capacity overflow" abort while building the preview.
3. After: the window is cropped to the file's widest row; columns past
   the data yield nothing beyond the data width.

Fix:
c1 is clamped to widest.saturating_sub(1) before the range is collected,
so the span is provably at most the file's own data - allocation is
O(file). Rows outside the file still come back empty (in-range blank
padding inside the data width is preserved), and c0 > c1 naturally
yields an empty window. Regression tests cover the 13-Z capacity-overflow
input and a 6-Z range that now crops.
2026-09-30 19:15:49 +01:00
Hakan SevenandClaude Opus 5.5 f537aff75c feat: node graph overlay; move to opencadcodec/opencadkernel/opencadgraph
The codec and kernel repositories and crates are renamed opencadcodec and
opencadkernel. Inside OCS they are depended on under short keys, so code
reads `codec::`, `kernel::` and the new `graph::` (opencadgraph, the node
graph engine). File-format and protocol spellings stay as they were: the
ACIS product id `acadrust`, the ACADRUST_* switches and the plugin
version keys `acadrust_version` / `acadrust_source`.

A button left of MCP on the command line opens a translucent node graph
over the viewport, with a palette of object, input, math, logic, list,
text and geometry nodes added by click or drag. An object node owns
drawing entities and its rows are the Properties panel's own rows for
them: the single-object page is extracted from refresh_properties as
entity_property_sections, values use the control protocol's
property_json, and writes go through set_property_value with a property
target override, so the panel, MCP and the graph share one read/write
path. A list reaching an object row makes one entity per element. Each
graph action is one undo step; the canvas pans and zooms.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 07:34:23 +03:00
Hakan Seven c9350d7b7b fix(web): disable unsupported folder picker 2026-09-14 20:24:34 +03:00
Hakan Seven 6c0badbdc8 fix: resolve annotation pull request findings 2026-09-14 20:16:46 +03:00
ramox81 666b28ffe3 fix(annotate): reject invalid linked ranges 2026-09-14 15:07:51 +03:00
ramox81 a35c996f9f fix(annotate): complete table and data workflows 2026-09-14 14:54:55 +03:00