Commit Graph
1063 Commits
Author SHA1 Message Date
BFlat 5b39d5deaa Merge pull request #2018 from TrevorBrown-dev/fix/ui-script-fallbacks-2014
M10: the UI takes a system face for Ethiopic, the Indic scripts and the other scripts its fonts lack (#2014)
2026-11-07 10:14:14 +08:00
BFlat 5140a59c2e Merge pull request #2009 from ashokram-si/feat/side-buttons-pan-1758
feat(ui): mouse buttons 4 and 5 pan the canvas like the middle button (#1758)
2026-11-07 10:12:52 +08:00
BFlat 8ea82be66b Merge pull request #2047 from StrajnarFilip/claude/fix-1906-minimised-control
M8: a minimised window under Wayland answers control requests (#1906)
2026-11-07 10:09:09 +08:00
BFlat 6d8146d9b3 Merge pull request #1996 from MMexicann/codex/docs-fig-import-architecture
M6: correct architecture guide for existing .fig support
2026-11-07 10:08:27 +08:00
BFlat 61e03c4dba Merge pull request #1991 from TrevorBrown-dev/fix/vector-rounded-fill
M8: joining the ends of a path broken open closes its fill loop through the new segment (#1951)
2026-11-07 10:01:58 +08:00
bflatastic 1c57967484 Merge main into #2018 2026-11-07 09:00:16 +07:00
BFlat 47b5979ef0 Merge pull request #2012 from TrevorBrown-dev/feat/text-direction-1830
M4: a paragraph's base direction can be forced: Text ▸ Text direction ▸ Left to right / Right to left (#1830)
2026-11-07 09:58:59 +08:00
bflatastic 3b1fc77ba1 Merge main into #2018 2026-11-07 08:57:17 +07:00
bflatastic 79d6335c90 Merge main into #2047 2026-11-07 08:54:47 +07:00
BFlat 3a1b698ed4 Merge pull request #2055 from aleksei-suholita/fix/effect-binding-checks
M3: a layer binds an effect's field only when its effect has it, and a bound glass light angle turns round
2026-11-07 09:53:26 +08:00
bflatastic 5f417b201b Merge main into #2009 2026-11-07 08:49:46 +07:00
BFlat 5762212ced Merge pull request #2006 from JonRC/fix/jpeg-quality-srgb-icc
M6: JPG exports take a quality and embed the sRGB profile (#2004)
2026-11-07 09:47:15 +08:00
Trevor BrownandClaude Fable 5.1 aae6f55592 Merge upstream/main into fix/ui-script-fallbacks-2014
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-06 20:44:15 -05:00
bflatastic 7e9a853da6 Merge main into #2047 2026-11-07 08:43:16 +07:00
bflatastic 468cab6b2b Merge main into #2055 2026-11-07 08:40:31 +07:00
Trevor BrownandClaude Fable 5.1 171fcd2d8b Merge upstream/main into fix/vector-rounded-fill
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-06 20:40:23 -05:00
Trevor BrownandClaude Fable 5.1 5a63c08a78 Merge upstream/main into feat/text-direction-1830
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-06 20:40:21 -05:00
Trevor BrownandClaude Fable 5.1 f66b51c7f7 Merge upstream/main into fix/ui-script-fallbacks-2014
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-06 20:40:19 -05:00
BFlat 401db4beb0 Merge pull request #2046 from StrajnarFilip/claude/fix-2026-merge-layout-conflicts
M9: one auto layout edit on each side of a branch is one conflict (#2026)
2026-11-07 09:39:12 +08:00
BFlat 83054f771d Merge pull request #1971 from TrevorBrown-dev/fix/connector-end-gap
Boards: connectors attached to a side start 4 pt outside the border, as FigJam's do (#1916)
2026-11-07 09:37:24 +08:00
BFlat 97b16702d5 Merge pull request #1900 from Hamza0101/fix/text-layer-name-follows-characters
M4, #1747: a text layer's name follows the characters typed into it
2026-11-07 09:34:20 +08:00
BFlat 9664afe673 Merge pull request #1213 from Salah1St/feat/web-fonts
M7: FIGCRAFT_WEB_FONTS embeds more craft-fonts families in the web build
2026-11-07 09:33:06 +08:00
bflatastic 9a6cc3e546 Merge main into #2047 2026-11-07 08:30:28 +07:00
bflatastic 642d847329 Merge main into #2055 2026-11-07 08:28:47 +07:00
bflatastic 7214854ed5 Merge main into #2046 2026-11-07 08:26:08 +07:00
BFlat 8cbac00bea Merge pull request #2024 from TrevorBrown-dev/feat/boolean-button-icons-2003
M1: the boolean operation buttons carry original icons (#2003)
2026-11-07 09:24:44 +08:00
bflatastic 4e5f0f8c04 Merge main into #1900 2026-11-07 08:18:31 +07:00
bflatastic 00fa951fe9 Releasing: name the web size gate without its number 2026-11-07 08:18:04 +07:00
BFlat 754b709610 Merge pull request #2060 from Luis-0508/ci/release-contributor-refresh
Release: refresh contributor credits for each release (#2059)
2026-11-07 09:17:55 +08:00
bflatastic 7c3a3b2703 Merge main into #2055 2026-11-07 08:07:48 +07:00
BFlat 09e04e7176 Merge pull request #2037 from denisg0mes/go-to-library-main
M3: Go to main component opens the library file of a library component
2026-11-07 09:06:17 +08:00
bflatastic 9ffe6b07e4 Merge main into #2046 2026-11-07 08:02:46 +07:00
bflatastic 7e316c2cf1 Merge main into #2047 2026-11-07 08:01:58 +07:00
bflatastic b73c51c978 Merge main into #2024 2026-11-07 07:58:09 +07:00
bflatastic ae4d0c912e Merge main into #2055 2026-11-07 07:55:49 +07:00
BFlat 43565b5bf6 Merge pull request #2052 from StrajnarFilip/claude/lan-share-read-only
M9: share a file on the local network read-only, with a view-only code
2026-11-07 08:50:25 +08:00
Luis 4cacc96631 Release: refresh contributor credits for each release (#2059)
About > Contributors still showed an old snapshot, because nothing
regenerated contributors/contributors.json before a release. Opt in to
the shared refresh from craft-common-actions: a read-only credits job
regenerates the snapshot for the release commit, and the shared release
workflow installs it before every source build. The snapshot is not
committed back.
2026-11-07 00:27:48 +01:00
Oleksii Sukholita 3d41394bfc M3: glass's docs say which centre splay bends away from and where a shape gets no core
Splay bends away from the centre of the layer's bounds, as the reference
tool's does: on a ring or an L that centre lies outside the shape, so an
inner edge bends towards the hole. Checked side by side on a ring and an
L at Splay 0% and 100%. The module doc still said splay 0 bends along the
edge's normal; it bends towards the core since #1889.

`MAX_SHAPE_PX` now says it is 4M px on the desktop and 1M on the web, and
that a bigger shape gets no core, so a large glass text or vector can bend
differently once zoomed into, in a 2× export, or on the web.

Docs only.
2026-11-06 20:29:14 +01:00
Oleksii Sukholita 104aa3deb1 M3: a glass's bound light angle turns round past ±180 instead of stopping
`Glass::set_bound` clamped a bound light angle to ±180, so a variable of
270 drew the light from 180, a quarter turn off, while a typed 270 draws
from -90. A bound angle now turns round into -180–180 (270 is -90, -0 is
0), the same direction the angle draws in.
2026-11-06 19:39:12 +01:00
Oleksii Sukholita 5bdedc3930 M3: a layer binds an effect's field only when its effect has it
`variable.bind` on a layer checked only the variable's type against the
field's scope, so `effects/0/refraction` on a drop shadow, or a binding on
an effect the layer doesn't have (`effects/9/radius`), was kept and did
nothing. An effect style already refuses both. The layer now uses the same
check: effect `i` must exist and have the field, and the field's type
comes from that effect. A binding an older file has on such a field still
does nothing, and still unbinds.
2026-11-06 19:38:52 +01:00
Filip StrajnarandClaude Opus 5.5 b779e46d47 M9: a local view-only share's url is the view URL, not the edit URL
The previous fix made a local share's `link` follow the code shown, but its
top-level `url`, the session's WebSocket URL, still carried the edit token:
`collab.join {link: url}` from a view-only share joined with edit access and
the edit reached the host. The link layer now hands over the view way in as a
link and its URL (`SessionInfo::view`, a `WayIn`, in place of `view_link`), and
`collab.peers` gives a local share's `link` and `url` from the way in for the
code shown (`Live::invite`). Online shares are unchanged.

Regression test: `code_tests::a_local_view_share_s_link_and_url_only_let_people_look`
joins through the `link` and then the `url` over loopback; both are welcomed as
viewers whose edits never reach the host.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LvG6E2VLhC9d5v8VSsf4ng
2026-11-06 19:12:40 +01:00
Filip StrajnarandClaude Opus 5.5 a05201e21f M9: a local view-only share's link is the view link, not the edit link
`collab.share {via: "local", access: "view"}` showed the view-only code but
gave the session's own invite link as `link`, and that link edits: whoever
joined through it could change the host's file. A local share's `link`, top
level and in `sessions`, is now the one that goes with the code shown, and it
follows `collab.share {access}`. Online shares keep the owner's own link there,
as before.

Regression test: `code_tests::a_local_view_share_s_link_only_lets_people_look`
joins through that link over loopback and is welcomed as a viewer whose edit
never reaches the host.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LvG6E2VLhC9d5v8VSsf4ng
2026-11-06 18:45:44 +01:00
Filip Strajnar a2be6632eb M9: share a file on the local network read-only, with a view-only code
The session the app hosts for a local network share now has two secrets:
the edit code and a view-only code (same address and port, a 44-bit secret
of its own). Whoever joins with the view code is welcomed as a viewer: they
see every change and presence, the app makes the file read-only for them,
and the session refuses their batches, as a server does for view links.

Share > Local network offers Can edit / Can view before sharing starts (the
edit code then never shows) and while sharing. collab.share {via: "local",
access: "view"} does the same; share in collab.peers lists both codes and
links. There is still no comment code on the local network.

Next::Stop boxes its event: SessionInfo grew past clippy's
large_enum_variant threshold, and it only ever carries a status or an end.

Tests: loopback_tests::a_view_token_lets_people_look_and_not_edit,
code_tests::a_local_view_code_lets_people_look_and_not_edit,
live_share_tests::a_local_share_can_start_for_looking_only, and the local
share tests that asserted edit-only codes. Docs: collab-protocol.md,
collaboration-parity.md.
2026-11-06 17:03:21 +01:00
Filip StrajnarandClaude Opus 5.5 853e8c6cc4 M8: a minimised window under Wayland answers control requests (#1906)
Under Wayland an app can't tell that its window is minimised (no `minimized`, no `occluded`),
and the compositor stops asking it to draw. eframe keeps running the app's logic for a window
whose redraw is overdue, but `control::background` still left every request for "the window's
frame", which never came: with the window minimised on GNOME or KDE Plasma each control-channel
or attached-MCP request waited and timed out after 60 s ("it was not applied").

`control::background` now treats a window that drew no frame for `NOT_DRAWING_AFTER` (0.2 s)
while a request waited for it as hidden: requests that act on the app's state are answered from
the logic passes, as they are for a window the platform reports minimised. `FigApp::control_waits`
keeps, per window, its pass count and the time the wait began; a frame drawn since starts the
wait again, and a pass is asked for 0.2 s later while a request waits. Screenshots and `ui.input`
still wait for a drawn frame. Measured on GNOME Wayland with the window minimised by its own
button: 0.54 s a request (before: 13.7 s for one, then 60 s timeouts).

Test: `idle_tests::a_window_that_stopped_drawing_answers_from_its_logic_passes`. Docs:
control-protocol.md, mcp.md, hardware-parity.md, target-app-parity.md, ROADMAP.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LvG6E2LxvJ6MuFmiLA6Zqm
2026-11-06 12:27:59 +01:00
Filip StrajnarandClaude Opus 5.5 fb55872450 M9: one auto layout edit on each side of a branch is one conflict (#2026)
A padding changed on both sides of a branch gave a conflict for every size and place auto
layout worked out from it: the component's, each instance's and their hugging parents' width
and height, each instance's layout, and every child's position (10 in a file with one instance,
138 with 15). The merge was refused until each had a side, yet the merged file laid itself out
again from the padding whatever they got. A `layout` conflict also took all auto layout fields
together, so a gap changed only on the branch was lost when main won the padding.

`merge::plan` now leaves out properties both sides changed to values both files work out for
themselves (`Plan::derived`): a hugging auto layout frame's or a filling child's size, text
sizing to its characters, an auto layout child's place (when both sides turn and scale it the
same way), and a value a layer in an instance has as its main's layer has it. Merging keeps the
file merged into's own value and normalising lays it out from the merged inputs.

`layout` and `childLayout` merge field by field: a field changed on one side (or the same way on
both) merges, and each field changed both ways is a conflict of its own (`Key::Field`,
`<id>/layout.padding`), written whole from the merged fields and each picked side's value. The
review shows it as "auto layout padding" with both sides' values ("8, 8, 8, 8").

Tests: `branch_tests::one_conflicting_auto_layout_edit_is_one_conflict` (the issue's file: one
conflict, either side laid out as if set directly), `auto_layout_fields_changed_one_way_survive_a_conflict`
(merge and update from main), `sizes_auto_layout_works_out_never_conflict`; the merge fuzz test
leaves worked-out values out of what each side must show. Docs: collaboration-parity.md, mcp.md,
ROADMAP.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LvG6E2LxvJ6MuFmiLA6Zqm
2026-11-06 12:17:11 +01:00
Denis GomesandClaude Opus 5.5 76af4e3f43 M3: Go to main component opens the library file of a library component
On an instance of a library component the command refused with "open
that file to edit it". The help center describes it opening the file that
holds the main ("Edit main components"), so it now does: the linked
library file opens in a tab, or its open tab comes to the front, on the
main's page with the main selected and zoomed to.

The library keeps the file's layer ids, so the copy's id map
(ImportedComponent::ids) leads from the local copy back to the exact
layer: a nested instance reaches its own main and a variant that variant.

The new tab takes the canvas size of the tab it came from. A tab still at
the default 1200x800 is refitted to the whole page on its first frame,
which would replace the zoom to the main.

A main deleted from the library file since it was published leaves the
file open with a note. A moved library file, a team library on a server
and a path off this computer are refused before anything opens; the last
uses the same check that guards library reads.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 02:21:20 -05:00
ashokram-si 30a1db7363 Merge remote-tracking branch 'origin/main' into feat/side-buttons-pan-1758
# Conflicts:
#	contributors/people.toml
#	docs/ui-parity.md
2026-11-06 09:44:15 +05:30
Trevor BrownandClaude Fable 5.1 2d4e1ce4e8 Merge upstream/main into feat/boolean-button-icons-2003
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-05 17:38:32 -05:00
Trevor BrownandClaude Fable 5.1 023762b7c6 Merge upstream/main into fix/vector-rounded-fill
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-05 17:38:30 -05:00
Trevor BrownandClaude Fable 5.1 ee033de32e Merge upstream/main into fix/ui-script-fallbacks-2014
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-05 17:38:30 -05:00