Commit Graph
133 Commits
Author SHA1 Message Date
Hakan SevenandClaude Opus 4.8 ec92a0cdc6 chore(release): v0.8.7
Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-07-23 15:22:42 +03:00
Hakan SevenandClaude Fable 5 5f08b77ebc feat(web): copy/paste in text fields via the browser clipboard (#346)
iced's clipboard rides window_clipboard, which has no wasm backend — a
focused text_input captured Ctrl+C/V on the web and did nothing.

Ctrl+V (captured, wasm only): read the async browser clipboard (the
keypress is a user gesture, so it's permitted) and replay the text as
synthetic KeyboardEvents on the winit canvas — the only route into a
focused text_input, since iced exposes no insert-text operation.
Control characters are dropped and the length is capped. The MText and
inline-TEXT editors keep their dedicated paste paths (no double feed),
and an unfocused Ctrl+V still runs PASTECLIP.

Ctrl+C (captured, wasm only): a widget operation pairs each text_input
with its focus state (iced fires both callbacks back-to-back on the
same widget) to collect the focused field's visible text, then writes
it with navigator.clipboard.writeText. Whole-field text, not the
selection — iced doesn't expose the selected range.

Native behaviour is unchanged.

Closes #346

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-07-22 12:47:19 +03:00
Hakan Seven 47f3409588 chore(release): v0.8.6 2026-07-22 00:16:43 +03:00
Hakan SevenandClaude Fable 5 427db6cd17 feat(web): copyable on-page banner for renderer errors (#414)
wgpu/naga report pipeline and shader failures through the log facade,
then leave the canvas empty - with no logger installed on wasm the
message was lost, so a broken GPU path looked like "draws nothing" with
a clean console. Install a web logger that mirrors Error-level records
to the browser console and into a fixed DOM overlay with selectable
text, a Copy button and repeat-collapsing; panics land in the same
banner via a chained hook. Windows Chrome/Edge reporters can now paste
the exact ANGLE/D3D11 error instead of a screenshot of a blank canvas.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-07-21 16:43:35 +03:00
Hakan SevenandClaude Fable 5 d154a01cb4 chore(release): v0.8.5
Co-Authored-By: Claude Fable 5 <[email protected]>
2026-07-21 10:13:27 +03:00
Hakan SevenandClaude Opus 4.8 f797fd800b chore(release): v0.8.4
Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-07-19 02:58:25 +03:00
Hakan Seven 60c70ba023 release: v0.8.3 2026-07-16 11:57:34 +03:00
Hakan SevenandClaude Opus 4.8 9a86a7394c build(deps): compile acadrust from the OpenAEC-Foundation/acadifc fork
Point the acadrust patch at the OpenAEC-Foundation/acadifc fork (still the
`acadrust` crate). Its main carries the Arc copy-on-write entity storage that
makes the undo document clone O(entities) refcount bumps instead of a full deep
copy — cutting the per-edit snapshot on a 788k-entity drawing from ~1.7s to
~70ms. No source changes here: acadrust`s public API is unchanged.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-07-15 07:55:27 +03:00
Hakan SevenandClaude Opus 4.8 4bcf5063e9 release: v0.8.2
Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-07-14 22:29:21 +03:00
Hakan SevenandClaude Opus 4.8 0c4272fbb0 chore(release): bump to 0.8.1
Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-07-13 14:38:56 +03:00
Hakan SevenandClaude Opus 4.8 f3482e8b3e chore(release): bump to 0.8.0
Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-07-11 02:32:06 +03:00
Hakan SevenandClaude Opus 4.8 ba3b3202e8 feat(thumbnails): embed DWG previews and wire cross-platform file thumbnails
Round-trip a raster preview through the DWG's embedded preview slot and
surface it to the OS file managers, so drawings show their contents in
Explorer / Finder / Nautilus instead of a generic document icon.

OCS:
* io::thumbnail — rasterize the scene to a BMP DIB on save (embedded via
  acadrust's new Preview type) and read it back on open for the Start
  page recent list; `--dwg-thumbnail IN OUT SIZE` CLI extracts a badged
  PNG for external thumbnailers.
* io::file_association::install_thumbnailer — self-install the OS
  integration on startup: Linux writes a .thumbnailer + hicolor mimetype
  icons; Windows registers the IThumbnailProvider DLL under HKCU.

Shared core:
* crates/dwg-thumbnailer — lean (image-only) preview extractor + the
  `badge_dwg` full-width "DWG" band, used by every platform so the
  ribbon is single-sourced. Ships an rlib+staticlib.
* crates/dwg-thumbnailer-win — IThumbnailProvider COM in-proc server
  (cfg(windows), CI-built as a workspace member).
* macos/ — QuickLook thumbnail extension (Swift + C-ABI bridge to the
  core staticlib), assembled into a .appex.

Icons & packaging (single SVG source -> per-platform assets in CI):
* assets/mimetypes/image-vnd.{dwg,dxf}.svg — themed file icons.
* packaging: WiX ships dwg/dxf.ico + the thumbnail DLL and points the
  ProgIds at them; Info.plist gets CFBundleTypeIconFile + the QuickLook
  extension in Contents/PlugIns.
* release.yml — generate .ico (Windows) and .icns (macOS) from the SVGs,
  build the QuickLook .appex, and bundle everything.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-07-11 01:27:17 +03:00
Hakan SevenandClaude Opus 4.8 dc7117f203 refactor(config): consolidate settings into one grouped settings.json
App preferences were spread across six flat plain-text files (settings.txt,
recent.txt, recent_limit.txt, statusbar.txt, ribbon.txt, plot.txt), each with a
bespoke line parser and no grouping. Replace them with a single grouped JSON,
serialized via serde (enabling the derive feature; serde_json was already a
dependency).

- New app/config.rs: AppConfig { settings, recent, statusbar, ribbon, plot } →
  <config>/settings.json (pretty JSON), load()/save().
- Make UserSettings, StatusBarConfig/StatusPill, CollapseMode and
  PlotDialogState serde-derived; #[serde(skip)] marks the plot dialog's runtime
  fields so only print preferences persist. Their bespoke .txt load/save is
  removed.
- App gains current_config/apply_config/save_config: one AppConfig::load at
  startup distributes into live state; every settings-change site
  (persist_settings_if_changed, recent add/remove/limit, status-bar pill
  toggle, ribbon density, plot commit) routes through save_config, which diffs
  against the last write to avoid thrashing.
- Clean start: the old flat files are ignored (no migration). ocad.pgp stays a
  separate hand-editable file.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-07-10 16:41:34 +03:00
Hakan Seven 3928f1cfa5 chore(release): v0.7.9 2026-07-10 00:17:32 +03:00
Cerem Cem ASLAN 973dc9de0a Reduce binary size by strip=true 2026-07-09 02:24:38 +03:00
Hakan SevenandClaude Opus 4.8 f91e45a62a chore(release): v0.7.8
Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-07-09 00:42:01 +03:00
Hakan Seven 0e368934ea chore: release v0.7.7 2026-07-08 00:33:34 +03:00
Hakan Seven ced42daff5 chore(release): v0.7.6 2026-07-05 21:05:51 +03:00
Hakan Seven 23d9a261b1 chore(release): v0.7.5 2026-07-04 20:18:47 +03:00
Hakan Seven 33f1150fad chore(release): v0.7.4 2026-07-04 01:46:33 +03:00
Hakan SevenandClaude Opus 4.8 f4fffa1359 chore(release): v0.7.3
Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-07-03 16:55:43 +03:00
Hakan SevenandClaude Opus 4.8 0e74a11724 feat(web): show Patreon supporters on the web build too
The browser can't call the Patreon API directly (CORS, and the token
would be exposed in the bundle), so the web build fetches a
pre-generated supporters.json served on the same origin. The Pages
workflow generates it server-side with the token (CI secret) after the
trunk build. Native keeps its live API fetch.

serde_json moves to the shared dependencies so the wasm build can parse
the list.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-07-02 01:25:24 +03:00
Hakan SevenandClaude Opus 4.8 8a69ef9de3 chore(release): bump to 0.7.2
Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-07-02 01:02:40 +03:00
Hakan SevenandClaude Opus 4.8 53a4882c7f chore(release): bump to 0.7.1
Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-07-01 19:17:42 +03:00
Hakan SevenandClaude Opus 4.8 da76918320 chore(release): bump to 0.7.0
Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-29 16:48:15 +03:00
Hakan SevenandClaude Opus 4.8 76ef544cda chore(release): bump to 0.6.9
Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-29 01:48:04 +03:00
Karim Jerbi 3d23c45016 chore: disable printpdf default features (unused html deps)
printpdf's default = ["html"] pulled in azul-layout, rust-fontconfig,
kuchiki, xmlparser and their transitive trees (~40+ crates including
two with cdylib targets) — none of which are used by the project's
PDF export (only basic primitives like Mm, Line, Polygon, Rgb).

Also fixes a MinGW linker error (export ordinal too large: 100035)
triggered when ld.bfd tries to build a DLL for printpdf with >65535
exported symbols.
2026-06-29 01:06:28 +03:00
Hakan SevenandClaude Opus 4.8 4116b85af0 chore(release): bump to 0.6.8
Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-27 12:23:51 +03:00
Hakan SevenandClaude Opus 4.8 eaf72254e7 chore(release): v0.6.7
Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-26 07:33:41 +03:00
Hakan SevenandClaude Opus 4.8 0efa559bd6 chore(deps): bump acadrust 0.3.4 → 0.4
Tracks acadrust main at 0.4.x: plotstyle/material common-entity
ordering fix plus in-flight DWG reader work. Patch comment updated
to match; drop the git patch once these land in a published 0.4 crate.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-26 07:00:36 +03:00
Karim Jerbi 627761b629 fix(text): render TTF glyphs as solid fills, fix font fallback, correct Z-order
Text elements previously rendered as hollow wireframe outlines and sometimes
fell back to the wrong system font due to case-sensitive exact matching. Also,
the viewport background grid drew on top of solid entities.

Case-insensitive and partial-name fallback matching (e.g., mapping "arialn"
to "Arial Narrow") is now added to `sysfont::canonical_family_name`, ensuring
text resolves to the correct installed system font.

TrueType font contours are now triangulated into solid fills (`fill_tris`)
using `lyon_tessellation` in `ttf_glyph.rs`. To prevent the GPU from misclassifying
this 2D text as a 3D mesh (which broke flat shading), text tessellation splits
the output into separate outline and fill `WireModel`s.

The background grid is extracted from `SelectionCanvas` into `GridCanvas` and
moved beneath the 3D viewport to ensure proper layering. Finally, `DepthBiasState`
is enabled on all face/fill pipelines to apply a polygon offset, perfectly
resolving Z-fighting between coplanar wireframe lines and solid faces.
2026-06-25 18:17:01 +01:00
Hakan SevenandClaude Opus 4.8 44fa9df278 build(web): restore the wasm build — gate native-only deps off wasm
The web build had bit-rotted: native-only features added since it last
compiled pulled crates that don't build for wasm32-unknown-unknown.

- printpdf (PDF export / printing) → native-only target; the web build gets
  stub export_pdf / print_wires. It pulls a wasm-incompatible memchr 1.0.2
  via lopdf → nom_locate, and the web has no filesystem.
- getrandom 0.3 (via ahash via acadrust) → enable its wasm_js feature and add
  the matching --cfg getrandom_backend rustflag in .cargo/config.toml.
- ocs_plugin_api "host" feature (out-of-process plugin runtime: interprocess,
  libloading, memmap2, rkyv) → native-only target; the web gets the
  dependency-free manifest/ribbon contract. The host code was already
  wasm-gated; only the Cargo wiring pulled it in unconditionally.

`trunk build --release` succeeds again.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-25 14:11:18 +03:00
Sebastian dcfaed0182 Initial commit 2026-06-25 00:01:36 +03:00
Hakan SevenandClaude Opus 4.8 8020286553 chore(release): v0.6.6
Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-24 23:22:43 +03:00
Hakan SevenandClaude Opus 4.8 e507e6615b chore(release): v0.6.5
Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-22 20:16:02 +03:00
Hakan SevenandClaude Opus 4.8 7fa12b757b chore(release): bump to 0.6.4
Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-22 01:12:03 +03:00
Hakan SevenandClaude Opus 4.8 54ff2c97e2 chore(release): bump to 0.6.3
Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-20 20:46:53 +03:00
Hakan SevenandClaude Opus 4.8 e1c5917644 fix(web): paste clipboard text into the TEXT / MText editors
Ctrl+V was globally bound to the entity paste command, so it never pasted
into an open text editor, and even when routed there iced's clipboard read
is a no-op on the web. Route Ctrl+V to the focused editor and, on the web,
read the system clipboard via the browser's async Clipboard API (the
keypress is a user gesture, so the read is permitted):

- MText editor: insert at the caret (web + native).
- TEXT field: append on the web; native lets the text_input paste itself.
- No editor open: falls through to the entity paste command as before.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-20 17:05:02 +03:00
Hakan SevenandClaude Opus 4.8 54106ca9b0 feat(web): lazy per-script font loading for international CAD text
The web build has no system-font access, so CAD text in non-Latin scripts
(Cyrillic, Greek, CJK, …) rendered as nothing — build_fallback was a hard
None on wasm (#141). Instead, ship per-script Noto subsets under web/fonts
(one alphabet per file, SIL OFL 1.1) and fetch them lazily over HTTP the
first time a drawing uses that script, then outline glyphs with ttf-parser.

- web_font: Script enum + script_of (char → script font), a per-script
  store with lazy fetch, and a pending queue drained by the app loop.
- CJK is split by language (chinese/japanese/korean). Han ideographs share
  code points but differ by language, so the shared block is routed by the
  document's $DWGCODEPAGE (932→JP, 949→KR, GB/936→CN); kana is always
  Japanese, Hangul always Korean. Re-tessellates when the language changes.
- build_fallback (wasm) outlines from the fetched subset; clear_fallback_cache
  lets glyphs that missed while a font was in flight reappear on load.
- PollWebFonts subscription (web only) + WebFontLoaded message drive fetches.
- Trunk copy-dir serves web/fonts; nothing is bundled into the native binary
  (desktop keeps using system fonts).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-20 16:13:26 +03:00
Hakan SevenandClaude Opus 4.8 79bb1d67b1 feat(cli): full command-line interface via clap
Replace the ad-hoc `--serve` arg sniff with a clap-parsed CLI:

- positional <file> to open at startup (also the OS file-association path)
- --new, --read-only, --backend, --safe-mode/--no-gpu
- --serve/--port (headless JSON automation, unchanged behaviour)
- --export IN OUT (headless format convert via the automation load/save infra)
- --script FILE (run command lines at startup)
- --log/RUST_LOG, plus --version/--help for free

GUI-only options pass to app::boot through a OnceLock config; read-only
gates the save paths. The web build skips parsing (no args).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-20 13:59:20 +03:00
Hakan SevenandClaude Opus 4.8 0dc537b669 chore(release): bump to 0.6.2
Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-19 19:42:27 +03:00
Hakan SevenandClaude Opus 4.8 4d8ea95974 chore(release): bump to 0.6.1
Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-18 16:37:27 +03:00
Hakan SevenandClaude Opus 4.8 4954551808 chore(release): bump to 0.6.0
Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-18 02:01:34 +03:00
Hakan SevenandClaude Opus 4.8 9cb11e77d2 chore(release): bump to 0.5.9
Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-17 16:06:35 +03:00
Hakan SevenandClaude Opus 4.8 eb53e445ab refactor(plugin): drop built-in plugins, external-only
OpenCADStudio no longer bundles plugins — every add-on is an external
cdylib loaded from the plugins folder or installed via the marketplace.

- Remove the demo plugin and the in-tree ocs_example_plugin crate.
- Remove the inventory-based built-in registration path (PluginRegistration,
  all_plugins, installed_manifests); registry now serves core ribbon tabs
  plus loaded external plugins, and try_dispatch routes only to externals.
- Plugin Manager drops the 'compiled into this build' section; the
  enable/disable toggle moves onto loaded external cards.
- Prune the now-dead HostSession/DocumentTab helpers and re-exports.

Part of the #100 extensibility epic (phase 2).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-17 15:50:52 +03:00
Hakan SevenandClaude Opus 4.8 020a3a4c84 feat(plugin): marketplace — install plugins from a curated registry
Add a Plugin Manager marketplace that installs external add-ons from a
GitHub repo's Releases. A curated registry (plugins/registry.json in this
repo, extended by PR) lists discoverable plugins; the host fetches it,
shows each entry with a release dropdown, and on install downloads the
asset matching the user's platform plus plugin.toml into the plugins
folder (API-version checked first). Users can also link arbitrary
owner/repo manually. Linked repos persist in settings.

Desktop only (ureq + serde_json); the install path reuses the phase-2
loader. Part of the #100 extensibility epic (phase 2).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-17 15:24:56 +03:00
Hakan SevenandClaude Opus 4.8 29c71be101 feat(plugin): load external cdylib plugins at runtime (phase 2)
Move BuiltinPlugin into ocs_plugin_api (host feature) so out-of-tree
crates can implement it, and add export_plugin! to emit the two C
symbols a cdylib exposes: ocs_plugin_api_version (checked first, so an
ABI-incompatible build never runs) and ocs_plugin_register -> boxed
BuiltinPlugin. The host loads every compatible package from the plugins
folder at startup via libloading (desktop only), keeps the library
resident for the session, and merges its ribbon tab + command dispatch
into the same paths as built-ins (honouring enable/disable). The Plugin
Manager shows external packages with a Loaded / incompatible status.

Approach B: the plugin hands back a boxed trait object, assuming a
matching toolchain + ocs_plugin_api version (the version symbol enforces
the latter). crates/ocs_example_plugin is the reference cdylib.

Part of the #100 extensibility epic (phase 2).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-17 14:48:56 +03:00
Hakan SevenandClaude Opus 4.8 5ccf5cfe36 feat(plugin): lift host surface behind a HostApi trait (phase 1b)
Plugins targeted the host's concrete HostSession type. Add a HostApi
trait in ocs_plugin_api behind an optional `host` feature (the only thing
that pulls acadrust, so the core crate stays dependency-free). HostSession
implements it and BuiltinPlugin::dispatch now takes `&mut dyn HostApi`, so
an out-of-tree add-on compiles against the contract crate alone. Per-tab
plugin state is reached through object-safe plugin_state* helpers.

Completes the phase-1 host-surface extraction in the #100 epic.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-17 11:31:05 +03:00
Hakan SevenandClaude Opus 4.8 e3c9e538e2 release: v0.5.8
Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-17 01:37:20 +03:00
Hakan SevenandClaude Opus 4.8 17f7924e77 feat(ui): OCS Web button, prefilled feedback, drop Start About button
- Add an "OCS Web" button (bright ribbon-blue, desktop only) to the Start
  page that opens the web build at hakanseven12.github.io/OpenCADStudio.
- Send Feedback now opens the GitHub issue with the body pre-filled:
  app version + platform (OS/arch on desktop, browser user-agent on web),
  via sys::platform_info + sys::percent_encode.
- Remove the redundant About button from the Start page (ABOUT command /
  menu still opens it).

Native + web build; 75 tests pass.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-17 01:34:13 +03:00