Commit Graph
735 Commits
Author SHA1 Message Date
Carbocode f781abe5f5 M2: preserve masks and sizing when adding auto layout to groups 2026-10-29 15:22:29 +01:00
Carbocode ec96cae46a M2: add auto layout from groups and convert them in place 2026-10-29 14:57:08 +01:00
BFlat 3108d5bee7 M8: edit.duplicate returns an id map with map: true (#995) (#1528)
With map: true, edit.duplicate also returns map: each original layer's id, descendants included (nested frames, groups, instances and their sublayers), paired with its copy's id, so a batch can edit inside a copy through a step reference instead of inspecting it. Without map the result is unchanged.
2026-10-29 20:34:30 +07:00
BFlat 436cfa1b96 M9: the replay log is bounded in bytes by default (#1069) (#1524)
The batches a session keeps for apps that reconnect were bounded only by count on a desktop host
and a private figcraft-server (`max_log_bytes` defaulted to usize::MAX). It now defaults to
64 MiB, and figcraft-server takes it from a new `max_log_mb` setting (default 64; open to the
public, also at most a quarter of `max_file_mb` as before). An app behind the trimmed log catches
up with a snapshot, as it already did past the count limits. The protocol is unchanged.

Nine 8 MiB renames with default limits: all 75.5 MB kept before, 58.7 MB after.

Fixes #1069
2026-10-29 20:02:46 +07:00
BFlat 714bbfcdaa M8: MCP and control calls name the document they act on (#998) (#1533)
Tools that act on a document, and the control methods engine.execute,
document.inspect, node.get and ui.render, take an optional `document`
(an open file's id from doc.list / document.inspect, or its path). The
call acts on that file and the tab in front stays in front, so an
attached agent keeps editing its own file when the user switches tabs.
2026-10-29 19:47:41 +07:00
BFlat b2421885d0 M9: sibling placement in live sessions by binary search (#1065) (#1523)
Every replica placed a created, moved or reordered layer by counting each sibling that sorts
before it, so a batch of many layers under one parent took quadratic time, on the server's
single hub thread too. `Replica::slot` now binary-searches the `(key, id)` order on each side of
the layer's old place (a position change has already given it its new key). The order is
unchanged, ties and fractional positions included.

20,000 creations and 10,000 moves under two parents: 20.05 s before, 0.33 s after (debug build).

Fixes #1065
2026-10-29 19:32:30 +07:00
BFlat 72b4269383 M8: an AI agent attached over MCP comments under its own name (#1414) (#1529)
Every command an MCP client runs acts as the client's name from initialize (clientInfo.title, else .name) with ' (agent)' after it, or 'AI agent' without one, carried to the app as engine.execute {agent}. Its messages, reactions and read state are its own, and its messages are marked (agent: true in the file and comment.list, an Agent label in the thread). The user's name and comments made in the app are unchanged; in live sessions the name and marker travel with the thread.
2026-10-29 19:15:19 +07:00
BFlat 3efb2699b6 M3: the instance-swap menus have a search field that filters as you type (#1338) (#1527) 2026-10-29 19:00:15 +07:00
BFlat 08173cc51e M9: a refused batch's fixes in linear time (#1063) (#1522)
The server's fixes for a refused batch walked every deleted layer's whole subtree again and
compared each document-level fix with all the earlier ones, so a batch deleting a deep chain took
quadratic time on the hub thread. Each subtree walk now stops at a layer already restored, and
document-level fixes are looked up and sent once per target. The fixes are unchanged.

A refused batch deleting a 20,000-deep chain plus 40,000 comment puts: 27.2 s before, 0.14 s after
(debug build).

Fixes #1063
2026-10-29 18:44:03 +07:00
BFlat d4e6ad5d81 M12: the connector tool previews the connector it will make, ends snapping to attach points (#1387) (#1526) 2026-10-29 18:29:48 +07:00
BFlat e32f8f2e07 M8: large images on the canvas draw from a smaller copy (#1483) (#1518)
* M8: large images on the canvas draw from a smaller copy (#1483)

An image shown smaller than its pixels draws on the canvas from a copy scaled down to 4096 or 8192 px on its longer side, cached beside the image in the same budget. Two 16000 x 10000 images (640 MB each) evicted each other on every frame that drew both; as copies they take 80 MB together zoomed out. Moving one over the other: about 2.1 s a frame before, 11 ms at fit and 15 ms at 30% after. Exports, thumbnails and views at 100% and closer draw from the image itself. Tests in large_image_tests; timings in large_image_bench_tests (ignored).

* M8: drop the ignored large-image benchmark; its numbers are in the PR (#1483)
2026-10-29 18:14:18 +07:00
BFlat 0971d096db M8: the progressive JPEG check guards file thumbnails too (#1517)
The header check from #1491 moves to figcraft_format::jpeg so the format crate and the renderer share it, and decode_thumbnail now refuses a progressive JPEG that samples a component more finely than its first (zune-jpeg 0.5.15 asserts on it; in the browser a panic aborts the page). A crafted file's thumbnail on the home screen and in recent files shows no picture instead of crashing. Regression test through decode_thumbnail and archive_preview.
2026-10-29 17:42:53 +07:00
BFlat a492cca415 M6: .fig import resolves library text styles linked by asset key and orders restated override rows by level (#1234) (#1515)
Style links that name a library style by its asset key and version resolve to the file's copy of the style, as variable links already did. The linked text style beats the copies of its values below the row that links it; rows above that one still win. Override rows that restate a nested level (overrideLevel) apply at that level instead of in wire order.
2026-10-29 17:28:55 +07:00
BFlat 07681afebe M6: .fig import keeps the file's saved line breaks while the text is unedited (#1236) (#1519)
* M6: .fig import keeps the file's saved line breaks while the text and its box are unedited (#1236)

The line breaker already keeps trailing spaces and the last glyph's letter spacing out of the fit test and doesn't round box widths; imported text wrapped a word early or mid-word because local fonts measure slightly differently from the file's. The import keeps the saved line starts (derivedTextData) on the text with the box width and a stable key of its layout content; layout follows them while both match and no line overflows its box by more than 3% (+1 px).

* M6: local check that imported text wraps at the line breaks its file saved (#1236)

Runs only when FIGCRAFT_FIG_SAMPLES names a folder of .fig files: each fixed-width text with saved breaks wraps there once imported, or falls back by the overflow slack; prints the counts.
2026-10-29 17:04:29 +07:00
BFlat 6ef899cdbb M7: download a missing free font from the Missing fonts window (#754) (#1510)
A missing family the suite's font store has (Google Fonts, Noto) gets a
Download button. The first one asks the user to allow downloading fonts,
then craft-libs' craft-font-store installs pinned, checksum-verified files
into the Craft apps' shared font folder on a thread of its own. The font
scan reads that folder; once installed the text fits the real font.

font.download / font.downloads drive the store as its agent: refused while
downloading is off, never able to turn it on. Desktop only.
2026-10-29 16:41:31 +07:00
BFlat 3d5185c2ab M0.9: web wasm back under the 24 MiB gate (#1472) (#1511)
The browser build's wasm was 25,982,540 bytes, past the gate raised for 0.12.1. It is now
23,915,213 bytes (22.8 MiB), 1.2 MiB under the restored 24 MiB gate:

- Catalog rows keep their plural forms behind a reference: Text is two words, not room for
  four strings, across ~52,000 baked-in rows (-454 KB).
- The browser build compiles with wasm SIMD (apps/figcraft-web/.cargo/config.toml, wasm-opt
  --enable-simd), so egui's glyph rasterizer leaves out its scalar SIMD fallback (-1.6 MB).
  The plugin workspace is built from the repository root and stays without SIMD.
- Revert the gate raise (cb227c97); the hosting guide names the WebAssembly SIMD requirement.
2026-10-29 16:14:40 +07:00
BFlat 1df9190d0c M3: shadows of images with transparent pixels follow their alpha (#1289) (#1509)
* M3: shadows of images with transparent pixels follow their alpha (#1289)

A drop shadow on an image fill was hidden behind the layer's whole box, so a
transparent PNG's shadow only showed outside its bounding box. Fills that
paint their own alpha (patterns; images with transparent pixels or that leave
part of the box empty) now cast and hide drop shadows, and shade inner
shadows, by the layer's pixels, like groups. Opaque pictures keep their
outline. Each image is scanned for transparency once. Canvas, PNG, SVG and PDF.

* M3: the image shadow tests import their names explicitly (#1289)
2026-10-29 15:43:08 +07:00
BFlat 7ba22fb2b6 M1: Crop image from the Object menu, the right-click menu and the image fill row (#1464) (#1501)
* M1: Crop image from the Object menu, the right-click menu and the image fill row (#1464)

* M1: crop mode shows the image dimmed outside the layer and heavier crop marks (#1464)

* M1: the handle overlay draws gradients and crops in their own helpers (#1464)
2026-10-29 15:07:21 +07:00
BFlat 7c9184b023 docs: rows from the round-4 community PRs (#858, #1409, #1397, #1389, #1143, #1427, #1421) (#1504) 2026-10-29 14:48:37 +07:00
BFlat fe7b4bac63 Merge pull request #1143 from Guillergood/feat/penpot-import-export
M6: import and export Penpot 2.x files offline
2026-10-29 14:20:14 +07:00
BFlat cabf8641fb Merge pull request #1409 from avhn/feat/1386-batch-continue
M0.9: let batches continue after failed steps (#1386)
2026-10-29 14:04:46 +07:00
bflatastic 0a6642747a Merge main into #1143
file.open and file.export docs: main's (reload, export options) plus the Penpot format.
2026-10-29 13:51:11 +07:00
bflatastic e89def2068 Merge main into #1409 2026-10-29 13:46:42 +07:00
bflatastic c87be091ac Merge main into #1421
apply_order takes #1458's numbering; a $var wrapper ranks 7, after boundVariables.
2026-10-29 13:46:39 +07:00
BFlat c2c720087c Merge pull request #1408 from avhn/feat/996-node-find
M0.9: find layer ids without changing the selection (#996)
2026-10-29 13:41:43 +07:00
BFlat 3be354d227 Merge pull request #1461 from MortenHusted/fix/open-file-reload
M1: opening a file that is already open says when it changed on disk, and can read it again (#997)
2026-10-29 13:41:21 +07:00
BFlat f3e7db0b2a Merge pull request #1460 from MortenHusted/fix/unknown-params
M0.9: commands, MCP tools and batch steps refuse names they don't take (#1413)
2026-10-29 13:40:58 +07:00
bflatastic 08ac26299e Merge main into #1143 2026-10-29 13:39:41 +07:00
bflatastic d4aae905a2 Merge main into #1409 2026-10-29 13:39:30 +07:00
BFlat 8dc3ab5703 Merge pull request #669 from yelintong/feat/flutter-codegen
M7: Flutter code generation
2026-10-29 13:37:49 +07:00
BFlat 299c1d5f59 Merge pull request #1458 from MortenHusted/fix/layout-key-order
M2: auto layout settings in one call don't depend on how their keys are spelled
2026-10-29 13:37:32 +07:00
BFlat 611ff941f0 Merge pull request #634 from Skyfuller1303/feat/fig-vector-region-fills
M4: preserve vector region fills across .fig import and native rendering
2026-10-29 13:35:07 +07:00
BFlat 1497d8ddc4 Merge pull request #1210 from yelintong/feat/nav-toolbar
ui: rebuild the toolbar pill on a 32 pt grid, without the Resources button
2026-10-29 13:34:02 +07:00
bflatastic 1e22268602 Merge main into #1143 2026-10-29 12:44:42 +07:00
bflatastic 789fa33444 Merge main into #634 2026-10-29 12:25:06 +07:00
bflatastic fc6ea73154 Merge main into #1421
# Conflicts:
#	crates/engine/src/cmd/props.rs
#	docs/roadmap.md
2026-10-29 12:24:32 +07:00
bflatastic c6c11471db Merge main into #1408
# Conflicts:
#	crates/engine/src/cmd/edit.rs
#	docs/roadmap.md
2026-10-29 12:23:48 +07:00
bflatastic c5ba6dd2e8 Merge main into #1409
# Conflicts:
#	crates/engine/src/session/undo.rs
#	docs/roadmap.md
2026-10-29 12:23:11 +07:00
bflatastic d1e96ea706 Merge main into #1461 2026-10-29 12:22:30 +07:00
bflatastic ee12a51045 Merge main into #1458 2026-10-29 12:22:29 +07:00
bflatastic a51e815073 Merge main into #1460 2026-10-29 12:22:28 +07:00
bflatastic a81efe5466 Merge main into #669 2026-10-29 11:52:03 +07:00
bflatastic 9f5178f53a Merge main into #1421
# Conflicts:
#	crates/engine/src/cmd/props.rs
#	crates/engine/src/selection/selection_colors.rs
#	docs/roadmap.md
2026-10-29 11:50:45 +07:00
bflatastic 8d69b3ce8f #1210: revision rows, and drop the Arabic catalog's Resources key 2026-10-29 11:44:05 +07:00
bflatastic 9b3683036c Merge main into #1210 2026-10-29 11:43:04 +07:00
bflatastic 49a41cddd4 Merge main into #1408
# Conflicts:
#	docs/roadmap.md
2026-10-29 11:40:48 +07:00
bflatastic 1505681a54 Merge main into #1407 2026-10-29 11:39:50 +07:00
BFlat f90a7c5e22 Merge pull request #1419 from avhn/fix/1410-batch-undo-rollback
M8: keep undo entries after a failed batch undoes an earlier edit (#1410)
2026-10-29 11:38:24 +07:00
bflatastic 56196eac5a Merge main into #1409
# Conflicts:
#	ROADMAP.md
#	crates/engine/src/session/undo.rs
#	docs/roadmap.md
2026-10-29 11:27:45 +07:00
bflatastic f154011299 Merge main into #1461 2026-10-29 11:19:05 +07:00