Commit graph cad-editor/Cargo.toml
Author SHA1 Message Date
Hakan Seven
e3c9e538e2 release: v0.5.8
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 01:37:20 +03:00
Hakan Seven
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 <noreply@anthropic.com>
2026-06-17 01:34:13 +03:00
Hakan Seven
fefae274d4 feat(wasm): web Save/Save As go through the dialog with a direct download
On the web, Save and Save As now open the in-app Save dialog (filename +
format) like the desktop, and the unsaved-changes prompt's Save routes
through it too — instead of an immediate rfd download. Confirm serializes
to bytes and downloads directly via a Blob + hidden `<a download>` click
(a user gesture), so there is no intermediate "click to download" link.

Replaces the rfd-based download_web / WebSaveResult round-trip with a
synchronous sys::download_bytes. Native save is unchanged.

Native + web build; 75 tests pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 00:52:20 +03:00
Hakan Seven
93d136c5db fix: Donate button (Start tab gate + web window.open)
- Add DONATE to the Start-tab command allowlist; it was blocked there
  with "No drawing open" while REPORT/CHANGELOG/ABOUT were allowed, so
  the Donate button did nothing on the welcome screen.
- Implement sys::open_url on wasm via web_sys window.open(_blank) — it
  was a no-op stub, so Donate, Release Notes and Send Feedback opened
  nothing on the web. The click is a user gesture, so the pop-up blocker
  allows it.

Native + web build.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 00:27:33 +03:00
Hakan Seven
c49ad887b8 fix(wasm): make the web build actually run in the browser
With the wasm bundle building, get it rendering in a browser:

- Enable iced `webgl` so wgpu uses WebGL2 where WebGPU is absent
  (e.g. Firefox by default), and `fira-sans` so UI text has an
  embedded font (the web has no system fonts) — without it every
  label was blank.
- Replace `std::time::Instant` with `iced::time::Instant` (web-safe);
  `Instant::now()` panics ("time not implemented") on wasm and crashed
  at boot via the command line.
- Skip the batched-hatch pipeline on wasm: its bind group needs
  vertex-stage storage buffers, which WebGL2 lacks (validation error
  on "New drawing"). Fields become Option; upload/draw guard on them.
  Hatches don't draw on the web for now; everything else does.
- Fix the trunk feature flag (`data-cargo-no-default-features`) and
  ignore the `dist/` build output.

Native build + 75 tests unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 17:53:56 +03:00
Hakan Seven
9ca19a9db8 feat(wasm): sequential rayon shim for the web build
wasm32 has no threads, so rayon's global pool would panic at runtime.
Add `crate::par::prelude`: native re-exports `rayon::prelude`, wasm
provides sequential `std`-iterator equivalents (par_iter / into_par_iter
/ flat_map_iter over slices, Vec, HashMap, HashSet). All call sites now
`use crate::par::prelude::*;` instead of rayon directly.

- wire_gpu's rayon `reduce` (2-arg, no std equivalent) is cfg-split to
  a sequential flat_map concat on wasm.
- rayon moves to a non-wasm target dependency.

Native still runs in parallel; all 75 tests pass. wasm bin compiles.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 17:11:20 +03:00
Hakan Seven
157d54a4d4 feat(wasm): single-window web entry + trunk harness (issue #45)
The binary now compiles for wasm32 as a runnable web target:

- Split the main-window render into `view_main`, bypassing the
  multi-window id dispatch the browser cannot use.
- Add `run_web` / `boot_web`: a single-window `iced::application`
  entry for wasm (the browser canvas is the only window). Native
  keeps the multi-window `iced::daemon` via cfg-split in `main`.
- Add a `console_error_panic_hook` (wasm-only) for readable panics.
- Add `index.html` + `Trunk.toml` so `trunk serve` builds the wasm
  bundle (no-default-features → no solid3d) with COOP/COEP headers.

Native build and all 75 tests unchanged. Browser runtime (rayon
threads, canvas attach, real file I/O) is the next iteration.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 13:16:35 +03:00
Hakan Seven
b2e20c95fe feat(wasm): compile the library for wasm32 (issue #45 groundwork)
First step toward a web build: the library now compiles for
wasm32-unknown-unknown with --no-default-features.

- Add a `solid3d` feature (default on) gating truck-meshalgo /
  truck-shapeops / lzma-sys. These pull vtkio → xz2 → lzma-sys (C),
  which cannot cross-compile to wasm. Without the feature the 3-D
  solid path (tessellation, booleans, ACIS import) becomes no-ops;
  2-D CAD is unaffected. Native builds keep the feature by default.
- Move native-only crates (ureq, open) to non-wasm target deps and
  add cfg shims: update-check is a no-op on wasm, and a new `sys`
  module provides open_url + handle_path (rfd FileHandle → PathBuf;
  synthesizes a name-based path on the web).

Native build + all 75 tests unchanged. Browser runtime wiring
(entry point, trunk, real file I/O) is a follow-up.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 13:01:19 +03:00
Hakan Seven
cd048165a9 feat(fonts): system TrueType support with shaping and fallback
Add a TrueType/OpenType render path alongside the LFF stroke engine so
users can pick fonts installed on their machine for text and MText.

- Discover system families via fontdb (sysfont) and list them in the
  text-style picker.
- Extract glyph outlines with ttf-parser, flattened into wire strokes
  normalized to the same 9-unit cap-height space as LFF glyphs.
- Shape runs with cosmic-text (ligatures, Arabic joining, kerning, bidi)
  plus automatic font fallback: a glyph missing from the chosen family
  is taken from another installed font.
- Unify both sources behind a single Face type; a shared run tokenizer
  drives the stroke (per-glyph) and shaped (TTF) renderers identically.
- Stroke fonts now fall back to a system TTF (cosmic-text picks it) for
  characters no LFF font covers, replacing the unicode/iso3098 chain.

Also trim the embedded LFF set from 47 to 26, keeping the AutoCAD-SHX
equivalents and dropping LibreCAD-only fonts now covered by TrueType.

LFF builtins keep priority over same-named system fonts so DXF text
renders identically across machines.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 11:18:17 +03:00
Hakan Seven
1d4243ba7e chore(release): bump to 0.5.7
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 04:30:27 +03:00
Hakan Seven
084dfb1bdb fix(windows): embed the app icon into the .exe
The Windows executable carried no icon, so Explorer, the taskbar, the
Start-menu tile and file-association entries showed a generic icon. Embed
AppIcon.ico via winresource in build.rs, and generate the .ico from the logo
before the build (it was produced after the build, too late to embed). Local
and non-Windows builds skip the step when the .ico is absent.

Fixes #107.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 04:10:01 +03:00
Hakan Seven
56a449e5ed fix(dynamic-input): free F12 by dropping iced's debug feature
The `debug` feature on iced installs a built-in F12 devtools hook that opens
the comet debugger (and prompts to install it when missing). That intercepted
F12 before OCS could toggle dynamic input. Drop the feature so F12 reaches the
app's own handler.

Fixes the F12 part of #101.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 03:46:24 +03:00
Hakan Seven
72ec1146df refactor(plugin): extract ocs_plugin_api crate for the stable add-on contract
Move the dependency-free, semver-versioned half of the plugin contract into a
standalone workspace crate `crates/ocs_plugin_api`:

- manifest types: PluginManifest, ApiVersion, API_VERSION
- ribbon vocabulary: CadModule trait + ToolDef/RibbonGroup/RibbonItem/IconKind/
  ModuleEvent/StyleKey

The host re-exports them from `crate::plugin::manifest` and `crate::modules`, so
every existing call site is unchanged. The acadrust-typed runtime surface
(HostSession) stays in the host binary; lifting it behind a HostApi trait in the
same crate is the remaining phase-1b step.

Part of #100. Docs updated in docs/plugin-architecture.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 01:36:04 +03:00
Hakan Seven
7a4ddbc62e chore(release): bump to 0.5.6
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 01:33:55 +03:00
Hakan Seven
dfb2c6f9d7 chore(release): bump to 0.5.5
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 11:20:18 +03:00
Hakan Seven
37ef813814 chore(release): bump to 0.5.4
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 14:21:02 +03:00
Claude
5ba7101022
feat(app): silently register as a .dwg/.dxf handler so portable builds show in "Open with"
Installed builds already register a handler (MSI ProgIDs, the Linux
.desktop MimeType, the macOS Info.plist), but the portable .exe and the
AppImage register nothing, so they never appear in the OS "Open with"
list. Add a best-effort, idempotent runtime registration that runs
silently on a detached thread at startup:

  * Windows — writes HKCU\Software\Classes\Applications\OpenCADStudio.exe
    (open command + FriendlyAppName + SupportedTypes .dwg/.dxf), which is
    what lists the exe in "Open with → Choose another app".
  * Linux — writes a user-level .desktop pointing at the running binary
    ($APPIMAGE when set) and refreshes the desktop database. Skipped when
    a system package already provides the desktop entry, so we never
    shadow a distro install.
  * macOS — no-op; .app bundles auto-register with LaunchServices.

Unlike the default-app prompt this changes no defaults and shows no UI;
it only makes the binary discoverable as a handler.

https://claude.ai/code/session_01DFVSKgViFaxEjZD2KsTdtt
2026-06-12 08:00:18 +00:00
Claude
a7d85fe148
feat(app): first-launch prompt to set Open CAD Studio as default for .dwg/.dxf
On the first launch that hasn't answered it yet, the app shows a small
dialog offering to become the default handler for .dwg and .dxf files.
The choice is persisted (default_assoc_prompted) so the prompt never
reappears.

The platform plumbing lives in io/file_association.rs:
  * Windows — opens the OS's own per-app default-programs dialog via
    IApplicationAssociationRegistrationUI::LaunchAdvancedAssociationUI,
    passing the "Open CAD Studio" RegisteredApplications name the MSI
    registers. Modern Windows guards the actual default behind a
    UserChoice hash, so this is the supported consent path.
  * Linux — xdg-mime default against the installed .desktop file, whose
    MimeType entries already cover image/vnd.dwg and image/vnd.dxf.
  * macOS — LSSetDefaultRoleHandlerForContentType binds the DWG/DXF UTIs
    declared in Info.plist to the app bundle id.

The work runs on a dedicated thread (the Windows dialog is modal) with
the result delivered back through a oneshot channel and surfaced in the
command line.

https://claude.ai/code/session_01DFVSKgViFaxEjZD2KsTdtt
2026-06-12 07:50:41 +00:00
Hakan Seven
c9071579a2 chore: release v0.5.3 2026-06-12 01:48:34 +03:00
Hakan Seven
8f39e77a0d chore: release v0.5.2 2026-06-11 14:41:24 +03:00
Hakan Seven
fb9f5bd4e5 chore(release): bump to 0.5.1
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 00:00:46 +03:00
Hakan Seven
7f94a9d66a chore(release): bump to 0.5.0
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 15:35:08 +03:00
Hakan Seven
70702d063f perf(hash): swap std HashMap/HashSet for rustc-hash FxHash
Phase 4.1. Handle / u64 keys dominate the hot maps (block_defn,
hatch / image / mesh caches, draw-depth map, viewport wire caches);
the default SipHash is wasted work on integer keys. Alias the std
types to rustc_hash::FxHashMap / FxHashSet crate-wide so every map and
set — including the cross-module draw-depth map shared between scene
and the GPU pipelines — uses the faster hasher consistently.

Mechanical: no behavioural change. Constructors moved from ::new() to
::default() (Fx variants carry no RandomState). Build + 13 tests green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 00:35:53 +03:00
Hakan Seven
b466747074 chore(release): v0.4.9
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 00:14:47 +03:00
Hakan Seven
edc8cbc969 feat(scale): drive scales from the drawing's scale list
Read the model-space annotation scale from the standard CANNOSCALE /
CANNOSCALEVALUE header variables instead of a user-variable hack, and
populate both the status-bar scale picker and the viewport Scale
property purely from the drawing's ACAD_SCALELIST — no built-in
fallback set. Xref-derived scales (`_XREF` suffix, `name|` prefix)
are filtered out so only the host drawing's own scales appear.

Bumps the patched acadrust to the commit that adds CANNOSCALE/
CANNOSCALEVALUE read/write.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 16:18:01 +03:00
Hakan Seven
8699a730bf chore(release): v0.4.8
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 11:40:16 +03:00
Hakan Seven
e708f90517 fix(macos): statically link liblzma so the app launches (#56)
vtkio (via truck-meshalgo → xz2 → lzma-sys) linked the system liblzma
dynamically, baking a Homebrew path (/opt/homebrew/.../liblzma.5.dylib)
into the macOS binary. The .app then crashed on launch on any Mac
without that exact library. Enable lzma-sys's `static` feature so
liblzma is compiled from the bundled source into the binary, making it
self-contained on every platform (verified: no dynamic liblzma link).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 02:34:56 +03:00
Hakan Seven
b0e9270a7e chore(release): bump to 0.4.7
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 00:53:38 +03:00
Hakan Seven
7bf9ce31ae feat(model): 3D solid modelling tab — primitives + boolean ops
Rename the Home tab to "Draw" and add a Model tab beside it with two
groups:

- Model: BOX / CYLINDER / CONE / SPHERE / WEDGE / TORUS, placed with a
  footprint + height. Each is built as a real ACIS Solid3D (acadrust
  primitive builders) plus a truck B-rep, tessellated into the shaded
  mesh pipeline, with edge wires for picking + wireframe.
- Design: UNION / SUBTRACT / INTERSECT via truck-shapeops.

A session-only Scene.model_solids cache holds each solid's truck B-rep
so the boolean tools can combine and chain them. Supersedes the old
command-line BOX/SPHERE/CYLINDER (insert::solid3d_cmds keeps EXTRUDE/
REVOLVE/SWEEP/LOFT).

Known limitations: booleans need solids created this session; curved
ACIS primitives render in-session but not after reload (the SAT
tessellator handles only planar caps); geometry assumes world_offset 0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 19:27:06 +03:00
Hakan Seven
83d36e02e3 chore(release): bump to 0.4.6
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 14:46:16 +03:00
Hakan Seven
ac9022676f feat(mtext): editable preview with caret, blink, and new-line support
Type directly into the rendered MText preview: click to position the
caret, insert/delete, Enter for a new line, Space for a literal space,
and arrow keys to move. The caret blinks when idle.

Keep the trailing empty paragraph in the editor so the caret appears on a
fresh line immediately after Enter, before any typing. parse_mtext_paragraphs
split into a _ex variant; layout_mtext skips the blank-edge trim when
emitting glyph boxes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 13:14:35 +03:00
Hakan Seven
db6e8873f2 chore: bump version to 0.4.5
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-29 23:42:42 +03:00
Hakan Seven
0602ae82f8 chore: bump version to 0.4.4
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-29 15:17:20 +03:00
Hakan Seven
269e21cbfb release: v0.4.3
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-28 22:46:05 +03:00
Hakan Seven
ded1b7b158 chore(release): bump to 0.4.2
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-27 14:19:05 +03:00
Hakan Seven
b2d9660221 chore(release): bump to 0.4.1
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-26 22:48:30 +03:00
Hakan Seven
05ea31aa2a feat(commandline): autocomplete suggestions + inventory-based registry
Type-as-you-go suggestion popup above the input that filters known
command names by substring (so `LEADER` surfaces both LEADER and
MLEADER). Up / Down navigates the list, Enter dispatches the
highlighted entry, clicking a row dispatches directly. Esc on a
non-empty input clears the buffer instead of escalating to
command-cancel.

The name corpus comes from `inventory::submit!` blocks placed next
to each `CadCommand` impl rather than a hand-maintained static list.
Adding a new interactive command means dropping one `inventory::submit!`
line in its own module file — the autocomplete picks it up at the
next compile. 98 submissions seeded across 60 module files;
`command::all_registered_command_names()` flattens them at runtime.

One-shot dispatch arms in `app/commands.rs` (NEW, OPEN, SAVE, UNDO,
…) don't have a `CadCommand` impl and are therefore absent from
autocomplete by design.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-26 22:45:54 +03:00
Hakan Seven
163725ca22 chore(deps): bump to latest stable versions
Bumps bytemuck 1.14->1.25, glam 0.27->0.33, rfd 0.15->0.17,
windows-sys 0.59->0.61, ureq 2->3. ureq 3 changed the agent API
and feature flags, so update_check.rs switches to Agent::config_builder
and body_mut().read_to_string(), and the feature toggles from tls
to rustls.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-23 22:21:30 +03:00
Hakan Seven
ecdb0cd0a0 chore(release): bump to 0.4.0
Fix repo URLs to canonical HakanSeven12/OpenCADStudio casing.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-23 17:32:29 +03:00
Hakan Seven
ef1f9a08d6 chore: rename H7CAD to Open CAD Studio
Joining the OpenAEC Foundation (open-aec.com). Crate/struct become
OpenCADStudio, user-facing strings use the spaced "Open CAD Studio"
form, repo URLs point to HakanSeven12/open-cad-studio. Logo (window
icon + assets/logo.svg) redrawn with OCS initials. Drop examples/
binaries — unused.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-23 17:16:15 +03:00
Hakan
0231d5cbfc chore(release): bump to 0.3.8
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-23 10:40:55 +03:00
Hakan
2790182067 fix(dependencies): update acadrust source to track main branch for recent fixes 2026-05-22 15:25:43 +03:00
Hakan
8e6491d4a8 fix(wipeout): use real clip vertices, correct image-pixel→WCS mapping
acadrust's DWG reader read the wipeout/raster-image clip boundary
points only to advance the bit cursor and then discarded them, so every
wipeout fell back to `Wipeout::new()`'s default placeholder rectangle
(`-0.5..0.5`). For files that store the real polygon mask in clip
vertices (anteen.dwg's `DIMBLOCK` style: u_vector ≈ 643k, size = (1, 1),
clip polygon ~0.0016×0.0033 in pixel space), the wipeout rendered at the
full image bbox — hundreds of thousands of units wide — instead of the
intended ~1000×2000 mask.

Pinned to the new `fix/wipeout-clip-vertices` acadrust branch (carries
the upstream parser fix). On the H7CAD side, the polygon mapping now
follows the DXF convention:

  x_off = (clip.x + size.x/2) × u_vec
  y_off = (size.y/2 − clip.y) × v_vec      (image-Y points down)

…in `wipeout_boundary_2d` (fill), `Wipeout::to_truck` (border line),
and `Wipeout::grips` (vertex handles) so all three stay in sync. The
fill path also explicitly closes the polygon loop — without it the GPU
`in_polygon` ray-cast skipped the v(n-1)→v(0) edge and the solid mask
bled far past the boundary.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 14:14:22 +03:00
Hakan Seven
c98e9ebd76 chore(release): bump to 0.3.7
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 06:57:15 +03:00
Hakan
ff31a07213 chore(release): bump to 0.3.6
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-21 16:25:00 +03:00
Hakan Seven
9527509ea2 chore(release): drop flatpak, add macOS .dmg, hide Windows console
- .github/workflows/release.yml: remove the build-flatpak job; matrix-
  add macOS (arm64 + x86_64) that builds H7CAD.app by hand, renders
  .icns from assets/logo.svg via librsvg + iconutil, and packages a
  UDZO .dmg. AppImage path updated to packaging/H7CAD.desktop.
- packaging/H7CAD.desktop: moved out of flatpak/ so the AppImage job
  doesn't depend on a Flatpak layout.
- packaging/Info.plist: macOS bundle template; __VERSION__ swapped
  for the release tag at build time.
- flatpak/: deleted (manifests, metainfo, desktop, builder cache).
- src/main.rs: `#![cfg_attr(all(windows, not(debug_assertions)),
  windows_subsystem = "windows")]` so the Windows GUI binary no
  longer spawns a console window alongside it (debug builds keep
  the console for log output).
- README: add macOS install section, document Gatekeeper / SmartScreen
  on first launch since the binaries are unsigned.

Bump to 0.3.5.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-20 21:13:02 +03:00
Hakan Seven
820bc3c692 chore: bump to 0.3.4 and patch acadrust to fix/hatch-boundary-handle-cap
The acadrust fix from https://github.com/hakanaktt/acadrust/pull/27
unblocks files with corrupt hatch boundary-handle counts (anteen.dwg
went from >100 s "stuck" to ~0.7 s release). Until the PR lands on
upstream/main, [patch.crates-io] points at the fork branch carrying
that commit; the comment in Cargo.toml notes the revert.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-20 07:02:44 +03:00
Hakan Seven
0aa026155a chore: bump to 0.3.3
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-19 13:45:56 +03:00
Hakan Seven
e84ae87bc5 chore: release v0.3.2 2026-05-17 20:19:39 +03:00
Hakan Seven
a0412534ae chore: release v0.3.1 2026-05-17 19:35:37 +03:00