Commit Graph
2646 Commits
Author SHA1 Message Date
BFlat 4fbed6a4e0 Merge pull request #1520 from storytold/dependabot/github_actions/actions-db49d30d5d
ci(deps): bump storytold/craft-common-actions/.github/workflows/windows-arm64.yml from 8bb4e5ab95443171104ad88113fe1ef9b0e5ce3f to fa5ef18780cf5e7d5d3b8de068de56cffc83cac5 in the actions group
2026-10-30 00:27:33 +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
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
BFlat 3e16119710 Merge pull request #1507 from Silvertree2010/fix/h3859-export-size-label-rounds-the-sca
Keep full precision in export size labels so they parse back
2026-10-30 00:19:59 +07:00
BFlat 4ed9981504 Merge pull request #1539 from Silvertree2010/fix/h3971-css-variable-export-leaves-carri
Neutralise CR and form feed in CSS variable export strings
2026-10-30 00:17:28 +07:00
BFlat ae0deb44b2 Merge pull request #1545 from Silvertree2010/fix/h3982-node-set-silently-turns-off-isma
Reject non-boolean values for node.set flag properties
2026-10-30 00:15:01 +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
BFlat 40c9e56876 Merge pull request #1530 from Silvertree2010/fix/1514-bug-report-figcraft-a-translucen
Fix double alpha when binding a translucent variable to an empty fill
2026-10-30 00:10:19 +07:00
BFlat a82adf4657 Merge pull request #1542 from Silvertree2010/fix/1513-bug-report-figcraft-a-variable-n
Resolve stored variable ids by exact id, not by variable name
2026-10-30 00:07:48 +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
BFlat cfec7c28cd Merge pull request #1499 from samhyun/fix/web-control-input
M8: the browser applies input sent over its control channel
2026-10-30 00:03:43 +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 a0fb4c3992 Merge main into #1546 2026-10-29 23:25:32 +07:00
bflatastic 187d091f7b Merge main into #1507 2026-10-29 23:23:12 +07:00
bflatastic 49f6e92758 Merge main into #1539 2026-10-29 23:23:07 +07:00
bflatastic 42844f13c6 Merge main into #1545 2026-10-29 23:23:04 +07:00
bflatastic 463045d2fa Merge main into #1530 2026-10-29 23:23:01 +07:00
bflatastic 59f000ee59 Merge main into #1542 2026-10-29 23:22:57 +07:00
bflatastic d3f382e9c6 Merge main into #1499 2026-10-29 23:22:53 +07:00
bflatastic d92ec78d7b Merge main into #1521 2026-10-29 23:22:45 +07:00
bflatastic 29d1c2b4d9 #1521: Cargo.lock keeps the craft-libs sources of craft-keymap, craft-menu and craft-quit 2026-10-29 23:22:26 +07:00
BFlat f702105ed0 M4: a letter and its combining marks shape with one font (#1478) (#1532)
* M4: a letter and its combining marks shape with one font (#1478)

* M4: the stacked-mark test checks positions only in fonts whose anchors stack them (#1478)

* M4: the cluster face rule is tested with stand-in faces, so it runs without system fonts (#1478)

* M4: the #1478 tests use stand-in faces only, so they run everywhere
2026-10-29 22:25:40 +07:00
BFlat 3af5d8a534 M9: comment.list reports the names each message mentions (#1415) (#1534)
Every message (the first and each reply) gets `mentions`: {name, known,
you} for each @mention, by the rule the thread view highlights with
(figcraft_doc::mentions, now shared with mention_ranges). Names resolve
against the file's people and you; unknown names are kept with
known: false; a@b.com mentions nobody.
2026-10-29 22:07:06 +07:00
Carbocode a3af72eca9 M1: sync main and leave ROADMAP unchanged in the feature PR 2026-10-29 15:43:01 +01:00
Carbocode 4f67fd2b7c M2: keep the shared roadmap out of the auto layout fix 2026-10-29 15:41:58 +01:00
BFlat 96eed15993 M8: mask groups draw over their own area, nested layers share one memory budget (#1061) (#1535)
A mask group's pixmaps cover only where its mask or content can paint within the view, rounded out to whole pixels, drawing the same pixels (a 40x40 mask on a 3000x2000 view: 96 MB -> 61.5 kB). Isolated layers share a 2 GiB per-thread budget; a layer past it is left out with a warning.
2026-10-29 21:33:46 +07:00
Carbocode f781abe5f5 M2: preserve masks and sizing when adding auto layout to groups 2026-10-29 15:22:29 +01:00
samhyunandClaude Fable 5.1 3f896453b6 M8: a test for stacked background blurs drawn in bands; the eight-band wording
From the review of #1496: three background blurs stacked on each other across the band
boundaries draw the same in bands as in one piece (within anti-aliasing), so the bands'
overlap, the reach of the largest blur, is enough, as it is for the desktop's parallel bands;
pinned by a test. The docs and the `MAX_BANDS` comment no longer put the longest frame at "an
eighth of the render": a frame draws at least a band, a part of the render rather than the
whole, and the numbers measured for #1496 are cited instead.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-29 23:08:12 +09:00
BFlat 0d9c2c3f73 M3: components that would contain themselves are refused, and loops in files are repaired (#1084) (#1540)
* M2: components can't contain their own instances (#1084)

Edits that would make a component hold an instance of itself, directly, through other components or through another variant of its set, are refused with the loop named. Files holding such a loop open with one instance per loop detached and a note; a rebuild never expands an instance inside a copy of itself, so a loop merged in a live session stops growing.

* M2: a variant may hold a sibling variant's instance; only true loops are refused (#1084)

Each variant counts as its own component: refusals and open-time repairs apply only to a component leading back to itself through instances (an instance-swap value included), so files with nested sibling variants open unchanged. sync_instance_depth is split into match_layers and copy_layers.
2026-10-29 21:05:32 +07:00
Carbocode 38607aa706 M8: use Carbocode public GitHub profile name in contributor credits 2026-10-29 15:04:12 +01:00
Carbocode ec96cae46a M2: add auto layout from groups and convert them in place 2026-10-29 14:57:08 +01:00
NetterSilverandClaude Haiku 5.5 0876f6dbc9 Reject non-boolean values for node.set flag properties
Found while testing crates/engine/src/cmd/props.rs:614 (also :708, :717, :718, :826 and :1007)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-29 14:51:04 +01:00
samhyunandClaude Fable 5.1 6d8b0e68f0 M8: the browser draws a zoom's full render a band at a time
Once a zoom had paused, the browser drew its full render in one frame. On a heavy page that
frame took seconds, and no input was handled meanwhile: the wheel steps and drags that came
were seen only when it was over.

The renderer's `Retained::begin` hands a full render back as `Steps`, drawn `band_h` rows at a
time with the same `render_band` and `put_band` the desktop's parallel bands use (bands overlap
by what background blurs read and keep their own rows; a blur reaching past a band makes the
bands taller rather than one piece), and `finish` keeps the image as a full render. A render
that is reused or patched is done at once, as before.

The browser's `Inline` worker refines through `Renders::refine_for`, which draws at least a
band a frame, more while they fit in `STEP_MS` (24 ms), and asks for the next frame while bands
remain, so input is handled between them; a view has at most eight bands, so on a page whose
render takes seconds the longest frame is about an eighth of it. A render drawn for the very
request is done once drawn. A pan or an edit meanwhile at the same zoom keeps the render going
and is patched in once it is drawn; a pan too far to patch or an edit the patch can't take draws
it again in steps, the image just drawn showing till then (`Refined::Shown`); a zoom, another
page or file, another size or other render options drop the render for one of the new view,
and what its bands took stands as the measure the next zoom's preview and wait go by. A render
in steps counts as one render (glass keeps the shapes a later render asks for again). The
desktop, with its render thread, is unchanged.

Measured in Chrome on two synthetic pages (20 images and 60 shadowed rectangles, with and
without two background-blur panels) whose full render takes 3.6–4.0 s at a deep zoom: the
longest frame while that render runs went from 3.7–4.0 s to 0.9–1.4 s (blur) and 0.69–0.80 s
(no blur); the bands together take longer than one render (the refined image comes after
6.7–8.1 s and 5.3–5.5 s instead of 3.8–4.1 s), each band rendering its overlap again and
repeating some per-band work, shadows mostly. The zoom steps are as before.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-29 22:37:35 +09: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
Carbocode dd65d7f4d2 Refresh local craft-libs lockfile entries 2026-10-29 14:19:04 +01:00
NetterSilverandClaude Opus 5.5 33ddb44016 Resolve stored variable ids by exact id, not by variable name
Fixes #1513

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 14:11:48 +01: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
Carbocode 563d530fdf M1: merge main and resolve corner smoothing roadmap conflict 2026-10-29 13:52:36 +01: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
NetterSilverandClaude Haiku 5.5 4d47c350c1 Neutralise CR and form feed in CSS variable export strings
Found while testing crates/engine/src/cmd/variables_io.rs:~92 (css_safe, used by css for String values and mode names)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-29 13:30:36 +01: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