Commit Graph
553 Commits
Author SHA1 Message Date
bflatastic 3334ec6c16 Batch r2-1 review: vector_up in smaller helpers (SonarCloud cognitive complexity) 2026-10-24 10:31:10 +07:00
bflatastic bd80829a27 Batch r2-1 review: a paint keeps its own opacity through unbind and rebind
color_alpha is the part of a solid paint's opacity that is its typed colour's alpha, not a flag:
binding a colour variable takes only that part out, unbinding puts the variable's alpha back in,
and REST import records it. A 50% paint bound to a 50% variable stays at 25% bound or not.
2026-10-24 10:30:49 +07:00
bflatastic 489da09905 Merge #740: engine: fill rules as vector.fillRule and vector.reverseLoop (@yelintong) 2026-10-24 09:23:50 +07:00
bflatastic 0a99f0fb69 Merge #1032: M8: save-format tests keep their temp folders apart (@MortenHusted) 2026-10-24 09:23:24 +07:00
bflatastic 75c1586011 Merge #1153: Match widget data check depth to serde_json's recursion limit (@Silvertree2010)
# Conflicts:
#	crates/engine/src/plugins.rs
2026-10-24 09:22:12 +07:00
bflatastic 70536a6265 Merge #948: Keep a solid paint's own opacity when binding a colour variable (@Silvertree2010) 2026-10-24 09:21:42 +07:00
bflatastic dc0ce6c176 Merge #1181: Refuse text.loadFont path for plugins (@Silvertree2010) 2026-10-24 09:18:13 +07:00
bflatastic 2a20a4de0a Merge #1190: Refuse non-local library paths in the library Cache (@Silvertree2010) 2026-10-24 09:18:10 +07:00
bflatastic e3c9d3f644 Merge #1191: Deny library.publishToServer to plugins (@Silvertree2010) 2026-10-24 09:18:07 +07:00
bflatastic f3782e6bc4 Merge #1023: fix(engine): show the Pen's Shift 45° step in its preview line (#970) (@vxMacDev) 2026-10-24 09:17:11 +07:00
bflatastic eada8b0ff3 Merge #1042: M3: style links given in a call apply after its values (@MortenHusted)
# Conflicts:
#	crates/engine/src/cmd/props.rs
2026-10-24 09:16:54 +07:00
bflatastic 90e5e03b23 Merge #1160: M0.9: figcraft-cli export names files as the app's export does (#1154) (@switch87) 2026-10-24 09:16:12 +07:00
bflatastic 15321a56ff Merge #1198: fill/stroke props: accept 'none' and null as no paint (@lileeei)
# Conflicts:
#	ROADMAP.md
2026-10-24 09:16:04 +07:00
bflatastic 6063d3e9a9 Merge #1189: M4: vector edit transform box around points of several layers (@marcoarnulfo)
# Conflicts:
#	docs/target-app-parity.md
#	docs/ui-parity.md
2026-10-24 09:15:11 +07:00
bflatastic 8eb5624460 Merge #986: fix: = zooms in, matching - zooming out (#973) (@Ridzzz0Alam) 2026-10-24 09:13:43 +07:00
bflatastic f31199d4ca Merge #1018: M1: a selected unfilled shape drags from inside its box (#910) (@muamerETS) 2026-10-24 09:13:38 +07:00
bflatastic 370faa52da Merge #1033: M3: a variant switch takes the new variant's resizing unless the instance set its own (@MortenHusted) 2026-10-24 09:13:33 +07:00
bflatastic 98040b48a5 Merge #1037: M3: a variable mode set on a layer inside an instance is an override (@MortenHusted) 2026-10-24 09:13:23 +07:00
bflatastic 83f840f802 Merge #1043: M3: a swapped nested instance keeps its outer main's overrides (@MortenHusted) 2026-10-24 09:13:18 +07:00
bflatastic 2053098e8e Merge #1200: The colour picker's eyedropper applies the colour to the paint the picker edits (Reported in storytold/vectorcraft#3342) (@marcoarnulfo)
# Conflicts:
#	crates/engine/src/tools.rs
2026-10-24 09:12:42 +07:00
BFlat 8167f13a6a M12: Boards: a collaborative whiteboard file kind (#1229)
Board files (File > New board) with sticky notes, shapes with text, connectors that follow what they join (straight or elbow, arrowheads, labels), marker, highlighter and eraser, and stamps; a board toolbar and a contextual bar; the Design panel hidden on boards, Prototype and Dev Mode refused there. Boards are ordinary FigCraft files built from ordinary layers, so saving, undo, export, MCP and live sessions work unchanged. File tabs, recent files and Open files show a pen nib for design files and a note for boards (original icons drawn in code).
2026-10-24 04:18:55 +07:00
BFlat 17ed21d128 M6: Dev Mode tail: imports in layer trees, compare with versions, an inspect-only canvas (#538)
Import lines for connected components inside generated layer trees; Compare changes against any saved version; a Dev Mode behaviour suite with an inspect-only canvas (menus, shortcuts, paste and Revert to saved refuse design edits; a drag under way is dropped on entering), Changed in the ready list, statuses only on top-level frames and sections; read-only plugins' panels from the Inspect tab.
2026-10-24 02:56:55 +07:00
aiongg 6ba0223636 Tests: the paragraph indent test loads system fonts and skips only without glyphs (#1227) 2026-10-23 13:50:42 -04:00
aiongg fc7a744519 CI: one test binary per crate, nextest, line tables only (#1208)
* Dev profile: line tables for workspace crates, no debug info for dependencies

* Tests: one integration-test binary per crate with several test files

* xtask ci: nextest, doctests, tests without examples, --keep-going; add xtask test
2026-10-23 13:01:12 -04:00
Marco Arnulfo 2a6e460a7b Let the box of another layer's points win over a region of the active one
With points selected only on another edited layer, a press inside the
combined box over an unselected filled region of the active layer picked
the region instead of dragging the box. Other layers' selections now count
in the same priority check; a press on an already selected region still
drags the regions.
2026-10-23 10:17:56 +02:00
Marco Arnulfo 410c1f10e2 The colour picker's eyedropper applies the colour to the paint the picker edits (Reported in storytold/vectorcraft#3342) 2026-10-23 04:08:48 +02:00
NetterSilverandClaude Haiku 5.5 b57c67782f Deny library.publishToServer to plugins
Fixes #1055

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 23:54:59 +02:00
NetterSilverandClaude Haiku 5.5 b3e65c89f9 Refuse non-local library paths in the library Cache
Fixes #1056

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 23:46:52 +02:00
Marco Arnulfo 1f2a8104bf M4: vector edit transform box around points of several layers
With points selected in more than one edited layer the transform box now
wraps them all, in the page's axes since the layers can be turned
differently. Its corners and edges scale them, outside a corner rotates
them and inside drags them; each layer's points are mapped in its own
coordinates and the whole drag is one undo step. A click inside clears
every layer's points.
2026-10-22 23:37:49 +02:00
NetterSilverandClaude Haiku 5.5 b8741162cd Refuse text.loadFont path for plugins
Fixes #1071

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 22:57:58 +02:00
Gert Pellin eb07717783 M0.9: trim mixed edge spaces and dots, document the name limits (#1154)
Review: " . .name. . " kept inner dots at the edges; trim spaces and dots
in one pass. docs/cli.md and safe_file_name's comment give the 100 and
200 character limits.
2026-10-22 21:43:52 +02:00
Gert Pellin ca30791fd7 M0.9: figcraft-cli export names files as the app's export does (#1154)
export into a folder replaced every character outside letters, digits,
'-', '_', space and '.' with '_', so a frame called
"Homepage - desktop (live + verbeteringen)" became
"Homepage - desktop _live _ verbeteringen_.png". The app's
file.exportLayers keeps those names and only replaces what file systems
refuse. The CLI now uses the engine's safe_file_name, and docs/cli.md
says which characters are replaced.

Also adds my own entry to contributors/people.toml.
2026-10-22 21:22:20 +02:00
NetterSilverandClaude Haiku 5.5 67ae35b155 Match widget data check depth to serde_json's recursion limit
Fixes #1118

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 21:11:15 +02:00
lileeei 2437a65d1b M1: fill/stroke props accept "none" and null (#1036)
node.create, node.set and the other prop appliers map fill/stroke
"none" (either case) and null to an empty fills/strokes list, as
fills: [] already did (undocumented), so an outline-only shape is one
call - agents write "none" for no paint. KEYS and docs/mcp.md
document it; the error names the accepted forms. fill_none_tests
covers create, set, undo, text and the error.
2026-10-22 23:04:57 +08:00
MortenHusted f1c206509f M3: files from before the modes override keep the modes set inside their instances
A file or library saved before "modes" was an override group has a mode
chosen on a layer inside an instance without its marker, so the next
rebuild or library import still put the main's mode back.

Copies follow their main layer's modes when the main changes them, so a
layer inside an instance on other modes chose them itself.
mark_layer_modes marks those when a file opens and when a published
library is read from a file or a server. Layers on their main's modes
and top-level instances stay unmarked.
2026-10-22 13:41:56 +02:00
MortenHusted 6394e96005 M3: a variable mode set on a layer inside an instance is an override
A variable mode chosen on a layer inside an instance (the icon inside a
Close button, recoloured through an icon colour collection) wasn't an
override group. A full rebuild of the instance starts each layer over
from its main and carries only override groups, so the mode fell back
to the main's. Library import always rebuilds, as do main edits such as
a new auto layout direction, so a modal's recoloured close icon came
into other files in its default colour.

"modes" is now an override group: setting a mode inside an instance
records it, rebuilds carry it, rebasing a nested instance finds it, the
component panel lists it, and resetting it brings back the main's mode.
A top-level instance's own modes stay its own and record no override,
like its resizing.
2026-10-22 13:41:56 +02:00
MortenHusted c141dee771 M3: a swapped nested instance keeps its outer main's overrides
A Button main's override on its icon instance's glyph (a red fill) was
lost when an instance swapped the icon: the outer rebuild re-copies the
glyph from the main's layer with no overrides of its own, so the nested
rebuild matched it by name and carried nothing. Before that rebuild, each
old layer of the swapped instance now takes the overrides held along the
source chain it had before this rebuild, through layers inside instances
in the mains that place the swapped instance. Geometry, slot content and
groups the layer overrides itself are left out. Matched by name, the
values carry onto the new main's layer as the instance's own: inherited
at the swap, frozen after, and back to the icon main's value on reset.
An icon main's own overrides stay with it.
2026-10-22 11:26:04 +02:00
MortenHusted 24a5855cab M3: style links given in a call apply after its values
apply_order gave fillStyle, strokeStyle, effectStyle, gridStyle and
textStyle the rank of plain values, so the JSON map's byte order decided:
fills, strokes, effects, grids, layoutGrids and variationSettings sort
after their link and overrode it (node.set then unlinked the style;
node.create kept a link its values contradicted). Style links now apply
after the values and x/y, just before boundVariables. A deviation set in a
later call still unlinks.
2026-10-22 11:11:59 +02:00
MortenHusted 0449edf645 M8: save-format tests keep their temp folders apart
SaveFiles named each test's folder after the process id and the
clock in nanoseconds. The tests run in parallel and the macOS clock
counts microseconds, so two of them often got the same folder and one
failed with AlreadyExists (14 of 30 runs here). A counter now keeps
the names apart.
2026-10-22 09:37:35 +02:00
MortenHusted 8ee0218d19 M3: a variant switch takes the new variant's resizing unless the instance set its own
Switching an instance to another variant copied the old root's sizing
and min/max back over the new variant's on the rebuild, so an instance
switched from a hugging variant to a fixed-width one whose children
fill kept hugging at the old width. The next edit then turned those
children Fixed, as a child can't fill an axis its parent hugs.

Resizing still equal to the old variant's was never the instance's own,
so on a sibling-variant switch it now follows the new variant; sizing or
min/max the instance set itself stays.
2026-10-22 09:33:12 +02:00
vxMacDev 3d41302f23 fix(engine): show the Pen's Shift 45° step in its preview line (#970)
A Shift-click with the Pen already put the next point at a 45° step
from the last one, but the line drawn to the pointer while moving
ignored Shift and followed the pointer, so holding Shift looked like it
did nothing. The line now ends where the click will put the point. Both
use one helper, at_45_degrees.
2026-10-21 19:47:01 -05:00
Muamer MustaficandCursor 84b48bc797 M1: the drag-from-inside fallback tests the selection's turned box (#910)
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-22 00:19:13 +02:00
Muamer MustaficandCursor 795567f016 M1: a selected unfilled shape drags from inside its box (#910)
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-21 23:37:09 +02:00
Ridzzz0Alam f619dca716 M1: = zooms in as - zooms out (#973)
Plain `-` zoomed out but plain `=` (the `+` key without Shift) did nothing,
so a canvas zoomed out with `-` couldn't be zoomed back in the same way;
held down, `-` reaches the 2% floor and `=` leaves you there. Ctrl+Shift+=
zoomed in while Ctrl+Shift+- did nothing either.

Found with a trace of the input on GNOME Wayland: Ctrl+wheel, Ctrl+=,
Ctrl+-, Ctrl+Shift+= and `-` all reach the canvas and zoom; `=` and
Ctrl+Shift+- arrive too but no binding takes them.

`view.zoomIn` gains `=` and `view.zoomOut` gains `Shift+Cmd+-`, pinned in
the shortcut parity table; neither key was bound elsewhere and the menus
still show Ctrl/Cmd and `+`/`-`. A keymap test checks each zoom-in key
has its zoom-out twin on both platforms.
2026-10-21 17:41:30 +02:00
BFlat 123e46550f Merge pull request #909 from RiceDee/fix/component-set-name
#903 follow-up: name new component sets from the variant path, not the first property
2026-10-21 16:31:04 +07:00
BFlat bb532a5790 Merge pull request #908 from RiceDee/feat/903-variants-discoverability
#903: Combine as variants in the context menu and Design panel; Add variant on a lone component
2026-10-21 16:01:25 +07:00
BFlat f143260c3a Merge pull request #935 from YarilaFox/fix/saved-document-title
M7: show the chosen filename for saved documents
2026-10-21 15:47:09 +07:00
NetterSilverandClaude Haiku 5.5 b788b55286 Keep a solid paint's own opacity when binding a colour variable
Fixes #923

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 20:43:51 +02:00
NetterSilverandClaude Haiku 5.5 8b198ea364 Strip default port in same_server when the address has a path
Found while testing crates/engine/src/online.rs:118

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-20 15:41:47 +00:00
YarilaFox 23463f719b M7: keep saved document titles in sync with filenames 2026-10-20 17:56:30 +05:00