Commit Graph
803 Commits
Author SHA1 Message Date
BFlat 019058ffd5 M1: a recovery copy made during a version preview holds the file, not the version shown (#1588)
Desktop recovery copies saved DocState::doc, which is the version shown while a version (or a live text preview) is previewed, so a crash during a preview brought the old version back as the unsaved file. What a recovery copy holds is now one shared helper, branches::recovery_copy: the document itself (document_itself(), the same document the unsaved-changes check compares), its history and its branches. The desktop copies and the browser's (#1580) both use it.
2026-10-30 08:21:47 +07:00
BFlat 8ee8ba6ce7 M6: FigJam .jam files open, as boards (#1342) (#1586)
* M6: FigJam .jam files open like .fig files (#1342)

A .jam is the same archive as a .fig (its canvas header reads fig-jam.), which the .fig reader already took; File > Open and its filter, drag and drop, file.import and the command line now take .jam too, and the home screen shows its thumbnail. FigJam layers come in as the .fig reader makes them (stickies and shapes with text as frames with their generated layers, other FigJam layers as frames or vectors with a note, unknown types left out with a note). Tests use a synthetic fig-jam. canvas and a .jam made from our own export.

* M12: a FigJam .jam file opens as a board (#1342)

The .fig reader marks a canvas with FigJam's fig-jam. header as FileKind::Board, so a .jam opens with the board toolbar, the dot grid and the board panels and saves as a board; a .fig stays a design file, and importing a .jam into an open file leaves its kind alone. Its objects stay ordinary layers (frames and vectors with the existing import notes). Builds on the .jam opening branch (#1586).
2026-10-30 08:03:56 +07:00
BFlat c382241660 M8: the Actions palette offers only commands that run from it (#1574) (#1582)
A search offered engine commands that need parameters the palette can't give, such as image.place (Place image, needing data or path), which failed with Invalid parameters and sat above the menu's Place image... row with the same label. A search now leaves out a command no menu lists when its params doc names a parameter without ? (figcraft_engine::cmd::needs_params, worked out once per command), and a row no menu item gives whose label reads like a menu item's. Place image runs the menu item, which opens the file dialog.
2026-10-30 07:48:00 +07:00
BFlat e7ae0f4426 M9: share links can comment: a comment access level beside edit and view (#1525) (#1576)
Someone who joins with a comment link (or its join code) sees the file live and adds, replies to, reacts to and resolves comment threads, but can't change the design: their app refuses other edits and the server accepts a comment link's batch only when every change in it touches comment threads. Sharing online makes a comment link and code beside the edit and view ones; the Share popover offers Can edit, Can comment and Can view, and the commenter's toolbar shows a Can comment badge with Move, Hand and Comment.

Backward compatible: clients announce the comments word; one that doesn't is welcomed with a comment link as a viewer and gets comment links listed as view links, a level this build doesn't know reads as view, and an older server that can't make a comment link leaves the share without one.
2026-10-30 07:29:40 +07:00
BFlat a09821f942 M1: Preferences > Scroll wheel zoom (#1390) (#1584)
With pref.scrollWheelZoom on, a mouse wheel zooms the canvas about the pointer and Cmd/Ctrl+wheel scrolls; Shift+wheel still scrolls sideways, and trackpads, pinches and touch screens are unchanged. A wheel is told from a trackpad by the device macOS reports, elsewhere by line versus pixel steps.
2026-10-30 07:12:46 +07:00
BFlat bc6dad0c2f M9: comment.list lists only the threads that mention a name (#1415) (#1585)
comment.list takes mentions (a name, any case): only threads where a message, the first or a reply, @mentions it, by the same parser the thread view highlights with and each message's mentions reports; combined with the other filters.
2026-10-30 06:56:33 +07:00
BFlat 974ab39503 M8: keep unsaved files when a panic stops the browser build (#1123) (#1580)
wasm32 can't catch a panic, so the command and frame guards do nothing in the browser and a panic ended the page with its unsaved changes. The page now follows its files with unsaved changes after every frame; its panic hook writes them to local storage as .figcraft copies (as many as fit) and says on the page that it stopped. The next page opens them again as unsaved files: file.recover also takes the copy as base64 data. The recovery-copy helpers move from the desktop app into figcraft_engine::branches so both share them.
2026-10-30 06:36:33 +07:00
BFlat cc3052de5e M8: cap the input of boolean operations (#1104) (#1581)
Each sweep takes at most 250 000 segments and 2 million possible crossings (pairs of segments whose bounds overlap, counted in O(n log n)), and a fold at most 4 million segments swept over its steps; past them the operation is refused with PathOpsError::TooComplex before it runs. A boolean group past the caps draws without its result, with a warning once, and the refusal is cached; vector.flatten refuses it instead of dropping it.
2026-10-30 06:03:35 +07:00
BFlat be7a2ecd3c M0.9: parse figcraft-cli arguments with clap, following RFC-0012 (#1396) (#1570)
clap derive types replace the hand-written parser: typed values, usage
errors (exit 2) before any work, help from the same definitions.

Syntax changes: a repeated option is a usage error (was: last wins; the
automation roots still repeat); a value starting with `-` needs `=`; a
positional starting with `-` needs `--`; `--o` and the `version`
subcommand are gone (`--version` stays); `<sub> --help` prints that
subcommand's help; usage errors are clap's text; `--format` is checked
before the file is opened.
2026-10-30 05:41:26 +07:00
BFlat 8811a23b6f M7: selection and hover outlines follow rounded corners (#1506) (#1573) 2026-10-30 05:07:43 +07:00
BFlat 7d76b0c673 M3: component properties keep their order on rename; Make slot asks for the name (#1536, #1537) (#1565)
Properties were listed by name, so a rename moved one. Components now keep prop_order (the names as they were made; a rename keeps the place) and every listing follows it. Make slot opens a name field under the frame's Slot row; Enter makes the slot, Escape cancels, a taken name keeps the field open.
2026-10-30 04:49:00 +07:00
BFlat 3c1718bf86 M9: publish to a server from the browser (Share > Online and Publish to server in the web build, #917) (#1567)
The web transport implements LiveLink::publish and the hosting and sharing background requests over the page's WebSocket. Managing connections run as exchanges (exchange.rs) in the browser client's driver; the requests and what their answers mean are shared with the desktop transport (requests.rs). The Share popover offers online sharing in the browser (no local network), and Publish to server opens there. Fixes #917.
2026-10-30 04:32:48 +07:00
BFlat 704fb0b717 M4: use the fonts installed on this computer in the browser (Local Font Access, #1051) (#1568)
Where the browser lists them (window.queryLocalFonts, Chromium), the font menu offers Use fonts installed on this computer; the fonts join the font database by name and each style's bytes are read only when text uses it, then auto-sizing text refits. Rust only (js-sys/web-sys). Fixes #1051.
2026-10-30 04:14:33 +07:00
BFlat d890de92c4 M8: SVG import reads color() and color-mix() colours (#1550) (#1566)
The SVG parser reads neither, so fills came in black and strokes were dropped without a note. They are resolved before parsing: color(srgb|display-p3 ...) converted to the document's profile, color-mix(in srgb|oklab|oklch, ...) evaluated as CSS Color 5 defines it. Other spaces are approximated with a note; unreadable calls become a mid grey with a note. Bounded length, nesting and count.
2026-10-30 04:01:07 +07:00
BFlat aa727500a4 M1: keep settings next to the executable in portable mode (#1320) (#1558)
The settings folder comes from craft-settings' rules: FIGCRAFT_CONFIG_DIR,
a `portable` file next to the executable (config/ beside it), then the
platform folder every earlier version used. The Windows portable zip ships
the marker, and a portable folder without preferences starts with a copy
of the platform folder's.
2026-10-30 03:35:12 +07:00
BFlat 05f811105c M1: start on other graphics when the window's first ones fail (#965, #1438) (#1557)
Direct3D 12 compiles with FXC and no device compiles wgpu's indirect-call
validation shaders, the two causes of "Parent device is lost" at start.
When the graphics still fail before the first frame, the app starts again
with the next of a fixed list of attempts (Windows: Vulkan, OpenGL; Linux
and FreeBSD: OpenGL; then lower requirements on the power-saving GPU), and
the last failure's message names what was tried.
2026-10-30 03:04:11 +07:00
bflatastic 1c8b937f08 Merge main into #1548 2026-10-30 02:04:39 +07:00
BFlat 132abcc672 M8: show in the app where an attached AI agent is working (#1416) (#1556)
Session::execute_as records the agent's presence: its name, the file, and the innermost layers its last edit changed or the selection it set, for 8 seconds after its last command. The app shows it as an avatar in the people row and an outline with a name tag on the canvas, in its own colour. Display only: no undo step, never saved, never synced to a live session.
2026-10-30 02:03:27 +07:00
bflatastic da3c8903ce Merge main into #1548 2026-10-30 01:45:39 +07:00
BFlat 42e1086a31 M5: drag a manual overlay into place on the canvas (#405) (#1555)
While the interaction editor has an Open overlay action with Manual position open, the overlay frame shows dimmed and outlined where it opens, from the top-left of the layer that opens it. Dragging it sets the action's offset through proto.action.set in one gesture: the X/Y fields follow live and the drag is one undo step.
2026-10-30 01:44:17 +07:00
bflatastic a9d197f17e Merge main into #1548 2026-10-30 01:29:43 +07:00
BFlat e0abd55d69 M9: one clear, persistent display name, renamed live in sessions (#1380) (#1554)
* M9: one name for comments and live sessions, shown in the Join dialog, kept in the browser, renamed live (#1380)

* M9: a reconnecting session's reset is its own helper (#1380)
2026-10-30 01:27:52 +07:00
bflatastic fef5898616 Merge main into #1548 2026-10-30 01:14:55 +07:00
BFlat 0a83cd9bdb Merge pull request #1516 from AganzeFelicite/fix/vector-marquee-anywhere-1508
M4: a drag anywhere in vector edit mode draws a marquee (#1508)
2026-10-30 01:12:34 +07:00
BFlat 3ac8467c54 Merge pull request #1547 from liwaichung-source/main
board grid settings: dots, lines, graph paper or none
2026-10-30 01:01:35 +07:00
bflatastic d7269c63d5 Merge main into #1516 2026-10-30 00:56:23 +07:00
bflatastic 719b78fbd9 Merge main into #1548 2026-10-30 00:54:38 +07:00
BFlat af2df345bc M9: the Join dialog shows a join until its file is ready, with Cancel and Try again (#1381) (#1553) 2026-10-30 00:51:46 +07:00
bflatastic 4ec382ea86 Merge main into #1547 2026-10-30 00:32:08 +07:00
bflatastic d60d973459 Merge main into #1516 2026-10-30 00:32:07 +07:00
bflatastic ffbb33973c Merge main into #1548 2026-10-30 00:31:50 +07:00
bflatastic 84f1419fbb Merge main into #1544 2026-10-30 00:26:55 +07:00
BFlat b85f38f30c Merge pull request #1521 from Carbocode/feat/corner-smoothing-scrub
M1: add a draggable corner smoothing icon
2026-10-30 00:24:22 +07:00
BFlat 8d884b005a Merge pull request #1496 from samhyun/perf/web-band-render
M8: the browser draws a zoom's full render a band at a time
2026-10-30 00:23:01 +07:00
bflatastic 1917ab80a8 Merge main into #1544 2026-10-30 00:22:26 +07:00
BFlat f6ccef0c5d M9: a per-address budget for server admin requests, and join codes found by hash (#1075) (#1552)
* M9: a per-address budget for server admin requests, and join codes found by hash (#1075)

* M9: the server tests share one snapshot and address helper (#1075)
2026-10-30 00:20:57 +07:00
bflatastic 1562b4bcd3 Merge main into #1548 2026-10-30 00:19:46 +07:00
BFlat 2f7d22e84a Merge pull request #1546 from Carbocode/feat/group-auto-layout-button
M2: add auto layout from groups in the sidebar and convert them in place
2026-10-30 00:12:35 +07:00
bflatastic 44a7c3c16c Merge main into #1521 2026-10-30 00:11:56 +07:00
bflatastic 9d86403f3a #1547: drop the board grid entry from the right-click menu 2026-10-30 00:06:50 +07:00
BFlat a51a60650d Merge pull request #1498 from ahmed-226/feat/guide-snapping
M1: guides snap to layer edges and centres when dragged
2026-10-30 00:05:17 +07:00
bflatastic 864acc0425 Merge main into #1547 2026-10-30 00:03:13 +07:00
bflatastic 86ab39b5cc Merge main into #1516 2026-10-29 23:58:44 +07:00
BFlat 2e3d9b6f07 M8: SVG pattern tiles drawn once per scale, within the layer budget (#1080) (#1551) 2026-10-29 23:57:49 +07:00
bflatastic c13c8d5e6a Merge main into #1498 2026-10-29 23:28:32 +07:00
bflatastic 890116d55e Merge main into #1496 2026-10-29 23:25:44 +07:00
bflatastic f2b1b8eadd Merge main into #1544 2026-10-29 23:25:35 +07:00
bflatastic a0fb4c3992 Merge main into #1546 2026-10-29 23:25:32 +07:00
bflatastic d92ec78d7b Merge main into #1521 2026-10-29 23:22:45 +07:00
Filip StrajnarandClaude Opus 5.5 411bce2f81 M4: Thai, Lao, Khmer and Burmese lines break between words (#1219)
These scripts write no spaces between words, so a paragraph was one word
that only broke where it overflowed, mid-word (พัฒนาซอ|ฟต์แวร์).
breaks::word_breaks finds the word starts inside each run of them with
ICU4X's line segmenter (icu_segmenter 2.3, matching the icu_* crates in
the lock), and break_lines may break there when the next glyph starts a
new cluster. Where a run meets other text the UAX #14 subset decides as
before; a word wider than its box keeps #1400's emergency break.

Desktop uses the segmenter's dictionaries; the browser uses its LSTM
models (about 0.39 MB of wasm instead of 1.86 MB, which the 24 MiB web
gate can't take). ICU4X breaks between stray marks are filtered through
safe_emergency_break, so junk input never splits a cluster.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LvG6DyK6i9Nvvsp3tp77UP
2026-10-29 16:44:14 +01:00