Commit Graph
1127 Commits
Author SHA1 Message Date
Yarila dd980c884f M7: search known files and templates from Home 2026-10-18 01:49:21 +05:00
skylar taylor-barrick 3f5f673ebc Merge pull request #777 from skylartaylor/document-link-schemes
Open only web links and local libraries from a document
2026-10-17 14:34:58 -06:00
skylar taylor-barrick c7acd1a81d chore: clear the rustc 1.96 clippy lints that fail xtask ci
Unrelated to the security changes in this branch; `main` already failed
`clippy --workspace --all-targets -- -D warnings` without them. Eight
clippy::nonminimal_bool sites across seven files, each taking clippy's own
suggested rewrite.

Every rewrite is pure boolean algebra with the negation kept outside, so the
float comparisons and their NaN behaviour are untouched: !A && !B becomes
!(A || B), and !opt.is_some_and(f) becomes opt.is_none_or(!f). Two sites needed
explicit parentheses the suggestion omitted, where the rewritten term is the left
operand of an && and || binds looser.

designcraft cleared the same lint in bc840130; this is figcraft's equivalent.
2026-10-17 13:35:44 -06:00
skylar taylor-barrick f7188de93d Drop a needless borrow in the dev-resource link gate
clippy::needless_borrow; `url` is already a reference. Missed on review because a
workspace clippy run aborts at the first failing crate, which was figcraft-format.
2026-10-17 13:35:44 -06:00
skylar taylor-barrick 37419afe14 Open only web links and local libraries from a document
A document carries things the app acts on for whoever opens it. Three of them were
taken as given.

Prototype Open link and Dev Mode dev resources both reached the platform's opener
with any scheme. In the web build the opener is window.open, so a saved document
could run script in the app's own origin; on the desktop any scheme went to the
system's handler. Both now pass through the new engine module `doc_urls`, which
allows http, https and mailto and nothing else. It is an allow-list on purpose: a
list of known-bad schemes is outgrown by every handler a platform adds.

A figcraft:// invite link joined the session at once. The system hands the app
whatever such link was followed, which may come from a page or a message, so the
Join dialog now opens with the link filled in and the person confirms.

A library link stored in a document was loaded from wherever it pointed. Only a
path on this computer is followed now, so opening someone else's file cannot make
the app contact their server (which on Windows would also send credentials).

Tests: each change has one that fails without it, verified by reverting. The
prototype test fires through an afterDelay trigger, since no click is needed, and
keeps a positive case so a refusal cannot pass vacuously.
2026-10-17 13:19:13 -06:00
BFlat d574eaac1d Merge pull request #775 from storytold/community/batch-15
Batch 15: .fig distributed alignment (#552), REST grid tracks, macOS CJK fonts, pen Esc
2026-10-18 02:18:23 +07:00
bflatastic 154baa4467 M7: a rename selects the whole name, so typing replaces it 2026-10-18 01:49:02 +07:00
Natnael-Dev 1e7983a550 docs(evidence): record verification evidence for #767 fix 2026-10-17 21:47:40 +03:00
Natnael-Dev bc5a2b8fa7 fix(proto): delete prototype interaction without deleting component (#767)
When an interaction noodle or interaction editor was selected in the
Prototype tab, pressing Delete or Backspace (or executing edit.delete)
targeted the selected layer/component instead of deleting the prototype
connection.

- Intercept Backspace and Delete in shortcuts::key_event and run_binding
  when an interaction is selected in the Prototype tab to remove the
  interaction using proto.interaction.remove rather than deleting the layer.
- Ensure clicking on empty canvas or outside noodles/handles deselects the
  active interaction noodle/editor.
- Close the interaction editor when navigating away from the Prototype tab.
- Add regression tests in proto_editor_tests verifying interaction deletion
  with Delete/Backspace keeps the component intact, and Escape closes the
  interaction editor before deselecting the component.
2026-10-17 21:45:51 +03:00
bflatastic e25c48cd56 Merge main into batch 15
# Conflicts:
#	docs/ui-parity.md
2026-10-18 01:42:03 +07:00
BFlat 42242e3c8b M1: IME composition in text layers (#747) (#755)
- Text editing on the canvas now tells the platform it wants the IME on **every** frame of the
  edit. Before, it only did so on frames that brought input events.
- The candidate window opens at the caret. Before, it opened at the canvas corner: the desktop
  integration places it by `IMEOutput.rect`, which was the whole canvas.
- Keys that reach the editor while a composition is in progress belong to the IME. Enter, Escape,
  Backspace, arrows and shortcuts don't act on the text then, so Enter picking a candidate doesn't
  add a newline.
- New test `crates/ui-egui/src/ime_tests.rs`.
- Docs: the IME rows in `docs/ui-parity.md` and `ROADMAP.md` now say it hasn't been checked on a Mac.

Fixes #747.
2026-10-18 01:41:15 +07:00
NetterSilverandClaude Haiku 5.5 89c5d3dfe6 Keep View toggles such as Rulers in the preferences
Fixes #379

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-17 18:25:28 +00:00
bflatastic 7fd936c8ba #762: one system fallback helper for scripts and shortcut glyphs, a face added once; the glyph test skips when this machine's fonts lack some 2026-10-18 00:36:36 +07:00
bflatastic cbf6d2df41 #762: drop the progress-doc edit (the maintainer adds those) 2026-10-18 00:33:32 +07:00
bflatastic cc12b8a3ec Merge main into #762 2026-10-18 00:33:13 +07:00
bflatastic 7ee2772da8 #758: ask whether the installed fonts are indexed only while a list waits for them 2026-10-18 00:22:21 +07:00
bflatastic 694c3114e8 #758: drop the progress-doc edits (the maintainer adds those) 2026-10-18 00:22:13 +07:00
bflatastic a7352c1860 Merge main into #758 2026-10-18 00:22:03 +07:00
bflatastic 913634bec8 #385: outline modes and soft-proof stay with their file; one toggle table for the menu's check marks 2026-10-18 00:13:49 +07:00
bflatastic 4a038a5f63 Merge main into #385
# Conflicts:
#	crates/engine/src/lib.rs
2026-10-18 00:10:16 +07:00
RealtaNuaandClaude Opus 5.5 7b9ebaacbb fix(ui): fitting Intensity translations; cut values end in "…", cut labels show on hover (#256)
From review:
- ru and pt-BR "Intensity" were too long for the glass field and ended
  in "…"; they are now "Яркость" and "Brilho", which fit.
- A value too long for its field ends in "…" instead of being clipped,
  so "100000" never shows as "10".
- A label cut short shows whole on hover.
- The every-language test now checks the Intensity label fits whole in
  each catalog (it fails with the old ru translation); the panel test
  checks the label isn't cut and that the field is the 98.5 points the
  language test measures against.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-17 23:50:52 +07:00
bflatastic 76f0edce08 #766: port the engine test, a section and click-elsewhere UI case, and the control-protocol note 2026-10-17 23:44:41 +07:00
bflatastic a7da760f9c #766: drop the progress-doc edits (the maintainer adds those) 2026-10-17 23:44:41 +07:00
bflatastic f33ffb4367 #766: keep the label rename in layers::Rename like the layers panel 2026-10-17 23:43:58 +07:00
bflatastic e03c2a65f7 #766: check a label before a widget's clickable part on a double-click 2026-10-17 23:43:32 +07:00
bflatastic 43bc7a3032 Merge main into #766 2026-10-17 23:42:55 +07:00
bflatastic dc184083ef Merge fix/pen-esc-same-layer into batch 15 2026-10-17 23:31:00 +07:00
RealtaNuaandClaude Opus 5.5 1c16aeae09 fix(canvas): the Pencil previews its stroke in its own colour and weight (#256)
While drawing, the Pencil previewed its stroke in the theme's text
colour, 2 points wide: white in dark theme, so over a white shape
nothing showed until the mouse was let go. The preview now uses the
colour and weight the Pencil draws with (one constant, PENCIL_STROKE,
black at 2 pt), scaled by the zoom, at least 1 pt. It doesn't show pen
pressure or a brush, which only the finished vector has.

Refs #256 ("The 'draw' tool is not visible when you are drawing. You
can see it after you release the mouse.").

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-17 23:25:51 +07:00
RealtaNuaandClaude Opus 5.5 a672a6650f fix(ui): glass settings: label the light intensity, keep labels in their fields (#256)
The glass effect's light intensity field had no label, and "Refraction
80%" and "Dispersion 50%" ran into the edge of their fields. The field
is labelled "Intensity" in every catalog. Text labels of number fields
take their measured width instead of 7 points per character, and a
label too long for its field ends in "…" before the value, which is
clipped to its own area. This changes every text-labelled number field:
Latin labels sit a little tighter, CJK labels get their real width.

Refs #256 ("There is one parameter that is not signed in the glass
effect editing options. The inscriptions also go beyond their
borders.").

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-17 23:23:25 +07:00
bflatastic 9265d554af Merge fix/macos-cjk-fonts into batch 15 2026-10-17 23:17:38 +07:00
bflatastic c8b611a802 Merge fix/rest-grid-tracks into batch 15 2026-10-17 23:17:37 +07:00
bflatastic 1d928a189c Merge fix/552 into batch 15 2026-10-17 23:17:37 +07:00
bflatastic 03bb164b5c M4: Esc after a pen path stays on the same vector layer (#760)
Escape or Enter while the pen draws ends the path and keeps its vector in
edit mode with the pen, so the next path joins the same layer; another
Escape leaves edit mode. Entering edit mode on a layer that already is a
vector no longer records an empty undo step.
2026-10-17 23:05:03 +07:00
bflatastic 91c80a19cc M7: find macOS's downloadable CJK system fonts (#406)
Current macOS keeps PingFang and other on-demand fonts in its asset
store, which the font scan never walked, so Chinese text showed as
boxes. The scan now also walks the com_apple_MobileAsset_Font* folders
of /System/Library/AssetsV2 (and the older /System/Library/Assets) with
the same depth, size and file checks, and Hiragino Sans GB and Heiti SC
(preinstalled) join the Chinese UI faces and the text fallbacks.
Tested with a folder laid out the same way; not run on a Mac.
2026-10-17 22:53:54 +07:00
bflatastic 68b19422ad M1: REST import reads grid track sizes (#465)
gridColumnsSizing and gridRowsSizing are CSS grid-template strings: px
tracks are fixed, fr tracks fill, auto/min-content/max-content hug,
minmax(_, Nfr) fills and repeat(n, ...) expands; other tracks stay equal
(1fr). Tracks past the axis's own count are left out. Files from .fig
keep reading the tracks from their source.
2026-10-17 22:44:09 +07:00
bflatastic 9a69f79861 #552: write and read space evenly as SPACE_EVENLY_CSS
The format's SPACE_EVENLY is its older name for equal gaps without edge
space, so files keep reading it as space between; true space evenly is
SPACE_EVENLY_CSS, which the export now writes.
2026-10-17 22:39:10 +07:00
BFlat 0a01188c31 M7: translate the .fig import notes (#761)
- The import report translates an importer note when the catalog has it, but 30 notes added by the
  `.fig` import series (#626–#639) had no catalog entries, so they showed in English: connector
  labels and snapshots, grid track sizing, image filters, slots and their content, vector segment
  styles, and text on a path.
- All 30 are now in `en.toml` and in every full catalog: es, de, fr, pt-BR, ru, ja, ko, zh-Hans, cs,
  id, sv and tr (30 each). `es-419` overrides only the 3 notes about settings (configuración rather
  than Spain's ajustes), as the overlay does elsewhere. The wording follows each catalog's existing
  terms for connector, layer, frame, stroke, grid, slot and text on path. The translations are drafts,
  like the catalogs, and wait for native speakers' review.
- `every_key_in_the_code_is_in_the_english_catalog_and_no_other` now counts each importer note (the
  `warn("…")` literals in `crates/format/src/fig` and `crates/format/src/rest`) as a required key, not
  only as an allowed one. A new note that isn't in `en.toml` fails the check, and because Spanish is
  in `COMPLETE` it has to be translated there too, so the report can't fall behind again.
  `docs/translating.md` says so.
- The importers' texts are unchanged. Notes built with `format!` (layer counts, type names, field
  names) still show in English, since the report matches whole notes.
2026-10-17 22:38:10 +07:00
bflatastic 6afcfc2641 Merge main into #552 2026-10-17 22:36:20 +07:00
RealtaNua cae69a7ae8 Merge remote-tracking branch 'upstream/main' into feat/752-report-missing-fonts
# Conflicts:
#	ROADMAP.md
#	docs/file-format-parity.md
2026-10-17 22:21:25 +07:00
Filip Strajnar 6ce46b3532 M1: double-click a frame's name on the canvas to rename it (#757)
A frame's name above its top edge (or a section's pill) only selected and
dragged it; a double-click there did nothing, since the label lies outside
the frame and hits no layer. With the Move or Scale tool, a double-click on
a label now selects that frame and asks the UI (`canvas.renameLabel`) for a
field over the label with the name selected, as the layers panel and pages
list do. Enter or a click elsewhere renames it (`object.rename`, one undo
step) and Escape leaves the name as it was. Rotated labels work too.

Tests drive the canvas: a double-click on a label opens the field, typing
and Enter rename the frame without moving it, undo restores the name, and
Escape cancels on a rotated frame.
2026-10-17 17:09:51 +02:00
RealtaNuaandClaude Opus 5.5 a3c5025186 M7: missing fonts window only after a file opens; wait for the font scan (#752)
From review:
- The check ran after any file.open/openRecent/import result, so a
  pasted or dropped image, reopening a file that was already open, or
  Clear recent brought the window back. It now runs only for results
  with a `summary` (a file opened, or pages imported), and never in the
  browser.
- Text > Missing fonts... before the startup scan finished listed
  installed fonts as missing. It now says it is checking the installed
  fonts and lists them once that is done
  (`figcraft_text::installed_fonts_known`, also true when system fonts
  are opted out, where checks used to wait forever).
- ROADMAP progress log and file-format-parity status line.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-17 22:06:03 +07:00
JimKnoxxandClaude Opus 5.5 b84ee179d4 M8: draw the macOS shortcut glyphs the UI font lacks
Menus and tooltips showed boxes for ⌃ ⌥ ↵ ⌫ ⇥ ⇞ ⇟ (e.g. Present ⌥⌘↵):
egui's default face has ⌘ and ⇧ but not these. The desktop app now adds
a system face that has them after the UI fonts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 17:05:49 +02:00
BFlat c6d6433473 Docs: parity rows for the 2026-10-17 landings (#756)
Brings the progress docs up to date with what landed on 2026-10-17: community batches #727, #728, #733, #735, #736 and #753, plus #729, #745, #746 and #751. Docs only.
2026-10-17 21:56:26 +07:00
RealtaNuaandClaude Opus 5.5 825cb1e7af M7: list the fonts a file uses that aren't installed (#752)
Text in a family that isn't installed was drawn in a fallback font
without a word. Now:

- `text.missingFonts` lists the families a document names that no
  installed or built-in font provides: text layers and their styled
  ranges, text styles, and string variables bound to a font family
  (every mode, through aliases), with the number of text layers.
- The desktop app shows a Missing fonts window after the user opens a
  file that has any: once installed fonts are indexed (before that every
  one of them would count as missing) and after any import report is
  closed. Files named on the command line count. Programmatic opens and
  the browser build never open it by themselves. Text > Missing fonts...
  shows it for the file in front; Escape closes it.
- `figcraft-cli info` prints `missing font` lines (`missingFonts` with
  --json).
- file-format-parity: the row claimed REST import warnings that no code
  produced.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-17 21:49:32 +07:00
BFlat bb8b809d46 Merge pull request #753 from storytold/community/batch-14
Community batch 14: selection colors, spacing, presenter tab, Wayland controls and more (10 PRs)
2026-10-17 21:32:13 +07:00
bflatastic 5962b630a1 Merge fix/all-f6 into batch 14 2026-10-17 21:04:46 +07:00
bflatastic df66ddd3a4 Merge fix/750
# Conflicts:
#	crates/ui-egui/src/paste_image_tests.rs
2026-10-17 20:48:47 +07:00
bflatastic e39d24a32e Merge fix/749 2026-10-17 20:48:35 +07:00
bflatastic c532053396 #749: clear the shortcuts panel after the home screen draws, so it never shows for a frame 2026-10-17 20:43:37 +07:00
BFlat b8f97a5f4f M8: the control channel answers while the window is minimized (#720) (#751)
- A minimised or covered window now answers every control request that acts on the app's state
  (`engine.execute`, `document.inspect`, `node.get`, `ui.inspect`, `ui.pointer`, `ui.key`, `ui.type`,
  `ui.set`, `ui.menu.invoke`, `ui.render`, `window.list`, `window.focus`, `app.quit`), in that window's
  file, from the app's `logic` (no frame drawn). Before, only six methods were answered there.
- What only a drawn frame can answer (`ui.screenshot`, `ui.input`, `window.new`) is an error at once
  for a hidden window: `window 0 is minimised or hidden: `ui.screenshot` needs it on screen
  (`ui.render` draws the document without it)`. Before, these waited up to 60 s.
- `crates/ui-egui/src/control.rs`: the `NO_FRAME` allow-list becomes a short `NEEDS_FRAME` list;
  `drain_hidden` answers the rest and fails the frame-only ones at once.
- Docs: `docs/control-protocol.md` (hidden windows, `ui.screenshot`) and `docs/mcp.md` (attached
  mode while the window is minimised). ROADMAP progress log and revision history.

Part of #720.
2026-10-17 20:29:32 +07:00