Commit Graph
946 Commits
Author SHA1 Message Date
BFlat 1ea19482d3 M1: the Frame tool's Phone presets have the iPhone 17 family (#1691) (#1720)
iPhone 17, 17 Pro, 17 Pro Max and Air, at the sizes the prototype device list uses; a test keeps presets named like a device at its size.
2026-10-31 06:13:47 +07:00
BFlat 477b83560b Merge pull request #1721 from WiktorKluczny/perf/fallback-fonts-one-face
M8: text reads only the fallback fonts it draws with
2026-10-31 05:51:19 +07:00
BFlat f0ceb46dcb M8: Show in folder works in the Flatpak build and selects the file on Linux (#1701) (#1711)
* M8: Show in folder works in the Flatpak build and selects the file on Linux (#1701)

* M8: Show in folder's fallback path is tested on Linux
2026-10-31 05:44:29 +07:00
bflatastic 71a625896b Merge main into #1721 2026-10-31 05:31:25 +07:00
BFlat 87e42a14f2 M4: a dashed line starts and ends with a half-length dash (#1718) 2026-10-31 05:28:15 +07:00
BFlat 71323ee780 M8: search fields in the left panels keep their text in the middle (#1703) (#1709) 2026-10-31 05:10:48 +07:00
BFlat b462a48346 M12: a connector's path can be reshaped by dragging its path handles (#1710) (#1717) 2026-10-31 04:53:36 +07:00
BFlat 4bcfd5247f M12: boards have 16 more shapes, in grid pickers (#1705)
* M12: boards have 16 more shapes, in grid pickers

* M12: a board shape's id and name sit in one table
2026-10-31 04:27:12 +07:00
BFlat 2d784c363d M3: library analytics count insertions and show them over time (#1704)
Gap 10: a file counts the library instances it places, creates, pastes or duplicates and reports them like its detaches. The server counts what a file's totals grow past their highest in the current week and keeps a year of weeks (actions.json). library.usage {days} and Show usage give insertions and detachments over the past 30 days, 90 days or year. New variants are appended; an older server refuses them and Show usage says so.
2026-10-31 04:13:14 +07:00
BFlat 12d36a9913 M4: a stroke's Custom style takes a dash pattern as a comma-separated list (#1681) (#1712) 2026-10-31 03:56:43 +07:00
BFlat 437d052396 M8: a control request can set its own timeout, up to 10 minutes (#1696) (#1706)
A request line can carry timeoutMs beside id and method, capped at 600,000 ms; without it the wait stays 60 s and older apps ignore the field. figcraft-cli mcp --attach PORT --timeout SECONDS sends it with every request and reads the answers that much longer. A timeout's message says how long the request waited.
2026-10-31 03:41:56 +07:00
BFlat fd8d49fc95 M11: a widget opens its plugin's panel (plugin API 5) (#1684)
* M11: a widget opens its plugin's panel (plugin API 5)

Gap 6: a widget callback's ui_show opens the plugin's panel and keeps the module loaded; the panel's callbacks get the widget's id and state and redraw it in the same undo step. Older plugins' ui_show from a widget still opens nothing. The Counter example sets its count from a panel.

* M11: open_panel takes its opener as one value
2026-10-31 03:24:32 +07:00
BFlat 9dafa22a20 M8: the Menu key opens the context menu; stale parity rows on reorder rings and shortcut counts corrected (#1677) 2026-10-31 03:07:14 +07:00
BFlat 760aece238 M5: an Open link action can open in place of the prototype, with Open in new tab off (#1685) 2026-10-31 02:37:54 +07:00
BFlat bbd1188c81 M3: a collection of this file can be extended (#1679)
Gap 14: variable.extendCollection and Extend collection on a collection's row in the Variables editor. Extensions follow edits of the collection they extend at once (normalising keeps them in step whenever variables change), extensions extend again, and a loop of extensions from a hostile file comes apart into plain collections.
2026-10-31 02:21:53 +07:00
BFlat f152ca995f Merge pull request #1697 from saimskywalker/issue-1095-roots-refuse-network
M8: commands confined to automation roots reach no server (#1095)
2026-10-31 02:10:56 +07:00
BFlat b377c70a8c M4: the eyedropper with Cmd/Ctrl+Shift makes a colour style or variable (#1674)
* M4: the eyedropper with Cmd/Ctrl+Shift makes a colour style or variable of what it picks

* M4: the Create from color window's collection picker is its own function
2026-10-31 02:09:08 +07:00
BFlat 54a0c6954b M9: a live session's welcome sends the document compressed to clients that read it (#1665) (#1693) 2026-10-31 01:51:12 +07:00
saimskywalker e6059b3543 M8: confined library checks say they were refused (#1095)
library.check refused nothing while automation roots confined it: it
counted libraries it never asked about and remembered them as yours. It
now refuses before remembering any. library.updates and library.list
answered a refused check with the team library cached earlier, as if the
server had nothing newer; the refusal now reaches them instead of
falling back like an offline server. The MCP and control protocol docs
say that a root on a network share still reaches that file server.
2026-10-31 02:43:50 +08:00
BFlat b6499a295c M8: a control request that times out says whether it was applied (#1673) (#1692)
The UI starts a request through its gate (a new Running state) just before running it and never runs one the transport already cancelled. At the timeout the reply says it was dropped and not applied, or that it is still running and will take effect; a reply that just made it is delivered. Only screenshots and input blame the window.
2026-10-31 01:37:09 +07:00
BFlat 9f4d1ce75b M12: board votes say who voted for what, and earlier votes' results are kept (#1666)
* M12: an ended vote's results say who voted for each object

* M12: a board keeps earlier votes' results, listed in Results and deleted one at a time

* M12: the vote Results popover is drawn by small helpers, and its stepper, rows and Clear are tested
2026-10-31 01:19:03 +07:00
saimskywalker ef4c0aacfd M8: commands confined to automation roots reach no server (#1095)
The roots confined files only: a confined agent could still publish the
open document to any server, host it on the network or join a session.
The engine reaches the network only through the live link, which now
refuses a call made while the roots confine it (hosting, joining,
publishing, sharing, team libraries, plugin directories), and skips the
background team library checks. The MCP and control protocol docs say so.
2026-10-31 02:05:29 +08:00
BFlat e97961ba66 M12: stamps stick to the objects they land on, which are highlighted first (#1671)
* M12: stamps stick to the objects they land on

A stamp sticks to the topmost object under its centre (BoardItem::Stamp gains an optional on, left out when empty so older files open with stamps on nothing) and the board's normalize pass carries it when that object moves or turns, once when both move together. A stamp dragged onto another object sticks to that one, off everything to nothing; one whose object is deleted stays where it is. Gap 24.

* M12: the object a stamp will stick to is highlighted

While the stamp tool is over an object, or a stamp is dragged over one, the object it will stick to is outlined with the canvas's hover outline (Overlay::stamp_target, found by the same stamp_target as board.stamp and settle_stamps). A drag no longer drops what it moves into the auto layout of a sticky, shape with text or table: board objects take no drops; a stamp already inside its sticky moves with it once. Builds on #1671. Gap 24.
2026-10-31 00:25:38 +07:00
bflatastic 497e2d020f Merge main into #1678 2026-10-30 23:51:41 +07:00
BFlat 958b9b8c44 Merge pull request #1676 from nine-codes/claude/sharp-feynman-me8n1o
M10: Bosnian catalog covers main's new paste strings
2026-10-30 23:46:50 +07:00
BFlat 170b9f9066 Merge pull request #1675 from MarekSpodBiedry/issue-1664
Live join: a large Welcome still downloading is not given up on at the idle timeout (#1664)
2026-10-30 23:44:38 +07:00
Patrick Wozniak d015436b13 M9: team links the list no longer hands out are removed at startup; a team link is made before the list changes 2026-10-30 17:39:36 +01:00
BFlat be6a7af25f M3: team library analytics count detached instances (#1668)
* M3: team library analytics count detached instances

Detaching an instance of a library component counts it in the file (libraries.detached, saved with it, capped). The background library check reports the counts after its fetch (ReportDetached); the server keeps them per file beside the file's usage report in usage.json (same caps) and answers Detached with them. Show usage and library.usage list detaches per component and per file (detached, detachesKnown). The new request and reply variants are appended, so every older library message keeps its bytes; an older server refuses the new requests, which the app ignores. Gap 10.

* M3: the detach test waits for the instance count too (the two arrive in separate reports)
2026-10-30 23:29:18 +07:00
Claude 3f867cc4fc Merge main into the Bosnian catalog follow-up
Main merged #1652 (the Bosnian catalog) and added more strings; ROADMAP keeps main's rows with the count updated, and bs.toml translates the two new strings (a pasted table's size limit, connector labels without a snapshot), so it covers all 1,906 UI strings.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013Tayw8nmxoLLmKv13jK93z
2026-10-30 16:18:27 +00:00
Patrick Wozniak 2d23f95673 M9: Home ▸ Online shows the server's team list, and its files open by links without a secret (desktop and browser) 2026-10-30 17:10:12 +01:00
BFlat b3ca228a75 M5: skipping the Open link notice by command is saved at once (#1667)
proto.linkNotice from the Actions palette, the control channel or MCP changed the preference in memory only until the app next saved its preferences. It now sets Session::prefs_unsaved, which the app saves at the end of the frame like installed plugins and live-session tokens; the notice's own Don't show this again goes the same way. Gap 15.
2026-10-30 23:05:57 +07:00
BFlat 7e9d6ce8c5 M12: line ends, dashes, weight and any colour on a board connector's bar (#1596) (#1632)
The bar over a selected connector adds start and end point menus with every line end, a line style menu (solid or dashed, weights 1 to 6) and a colour wheel opening the colour picker, beside the board colours and line type; every control names itself on hover. UI only, through board.setStyle and the stroke's dashes and weight.
2026-10-30 22:50:20 +07:00
MarekSpodBiedry 0ebe626062 Live join: a large Welcome still downloading is not given up on at the idle timeout (#1664) 2026-10-30 16:38:36 +01:00
Claude 34cd65a711 M10: Bosnian catalog covers main's new paste strings
Four strings main added since the last merge (pasted design layers and
their missing images, image fills and shared styles not in the file) get
Bosnian translations, so the catalog covers all 1,905 UI strings again;
the counts in ROADMAP.md and the localization parity doc follow.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013Tayw8nmxoLLmKv13jK93z
2026-10-30 15:34:04 +00:00
BFlat 4f5a25cc82 M12: spreadsheet cells paste onto a board as a table (#1663) 2026-10-30 22:32:44 +07:00
BFlat ddda495a6f M6: a long frame name stays on one line in the Export button and Dev Mode's header (#1650) (#1661) 2026-10-30 22:12:49 +07:00
BFlat db725dc73f M8: the Design panel and the selection overlays stop going over a large selection every frame (#1571) (#1660) 2026-10-30 21:58:41 +07:00
BFlat 9b1812432f M6: plugin panels show images (#1639)
* M6: plugin panels show images

An image control in a plugin panel carries a picture as base64 (at most 256 KB; panel specs up to 1 MB), drawn at its size up to a field's width and named by its label, which shows instead when the picture can't be decoded or is over 4,096 px on a side. Images can't be clicked or be command parameters. Panel and form captions no longer wrap.

* Render worker: in_flight counts the watchdog's late preview

The watchdog that previews a render running past PREVIEW_AFTER_MS could pass its still-rendering check, lose the race to the full render, and then hand over its preview and wake the UI after Worker::in_flight had gone false. An idle test that had settled then saw a 0 ns repaint whose cause egui reports a frame late (CI on #1639: 'asked for a repaint in 0ns: [app/files.rs:211]', the autosave tick of the previous frame). The watchdog now marks itself busy from before that check until it has handed over and woken (or skipped), and in_flight counts it; the full render's done markers are SeqCst so the watchdog sees a finished render before in_flight can read idle.

* Docs: drop a status item the merge listed twice
2026-10-30 21:26:15 +07:00
BFlat 838d368712 M6: .fig connector labels without a saved snapshot are kept, centred on their line (#1659)
* M6: .fig connector labels without a saved snapshot are kept, centred on their line

A connector with its own label text but no saved snapshot imports as a frame holding its line (a vector with the connector's stroke and ends) and the label as text centred on the line's middle by length, in the connector's fill paints or black; its background isn't known and is left out, as the import report says. The connector branch of layer_filtered moves into connector_layer. Gap 1.

* Docs: drop a status item the merge listed twice
2026-10-30 21:10:04 +07:00
BFlat 27920c5e26 M8: a drag moving many layers normalises only what sits around them, not each layer's bindings, sizing, text and instance checks (#1571) (#1656) 2026-10-30 20:53:03 +07:00
bflatastic 5adcf3cf83 Merge main into #1657 2026-10-30 20:19:47 +07:00
bflatastic f20e474d7e Merge main into #1652 2026-10-30 20:06:28 +07:00
bflatastic ed6a078854 Merge main into #1657 2026-10-30 20:05:52 +07:00
bflatastic cd95894f84 Merge main into #1652 2026-10-30 19:50:13 +07:00
bflatastic a55854955d Merge main into #1651 2026-10-30 19:49:02 +07:00
bflatastic 6b35fd80cf Merge main into #1657 2026-10-30 19:48:25 +07:00
BFlat 01b07af55a M6: a pasted image the clipboard doesn't carry shows as missing and is named (#1648)
* M6: a pasted image the clipboard doesn't carry shows as missing and is named (#1646)

The placeholder an import stores for an image it lacks is now striped, not flat grey; the fill keeps the image's name; .fig and paste give a fixed, translated note per image; edit.pasteDesignLayers returns missingImages, the paste's message names those layers, and a paste with notes opens the import report.

* M6: the missing-image placeholder's stripes stay clean when scaled, and a .fig gives one note (#1646)
2026-10-30 19:34:24 +07:00
BFlat 4965620d77 M6: pasted layers keep the colours of their shared paint styles (#1647)
* M6: pasted layers keep the colours of their shared paint styles (#1638)

A clipboard links a style by the guid it has in its library, which it doesn't hold, and by its library asset, whose copy it does hold. Mapper::resource_id now takes a guid only when the file holds a node by it, else the asset, so .fig import and paste agree; a link to a style that really isn't there keeps the layer's stored colours, with a note.

* M6: Swedish catalog: keep both new import notes after the merge
2026-10-30 18:54:24 +07:00
BFlat dd2a9fd013 Docs: one copy of each row and status item, and a check that keeps it so (#1658)
* Docs: one copy of each row and status item, and a check that keeps it so

Merge resolutions that kept both sides had left progress-doc rows (the .fig row four times, co-editing, live cursors, Windows, M0.9) and status-line items (302 in all) twice or more. The rows are merged keeping every distinct fact, the newest wording winning (#1649's connector routing included); repeated status items are removed, the first kept. cargo xtask docs, run by ci, fails on a repeated table row or status item.

* Docs: remove the status items the merge of main brought back

Merging main into #1658 rebuilt the status lines from main's copies, which still listed items twice: ROADMAP 2, docs/roadmap.md 5, docs/gaps.md 43 and docs/target-app-parity.md 190, whose unclosed parenthesis also came back and hid them from cargo xtask docs. They are removed again, the first copy kept, and the parenthesis closed; every distinct item is still present against main.
2026-10-30 18:36:00 +07:00
Wiktor KlucznyandClaude Opus 5.5 6acbd91347 M8: text reads only the fallback fonts it draws with
The first text laid out asked the font database for its fallback faces
(the fonts a run's missing characters are drawn with), and each of the 29
fallback families went through `find`, which reads every face of a family.
On Linux with Noto Sans CJK that is all seven 16–20 MB files, twice (SC and
KR name the faces of the same collections, and the bytes were shared only
within one family); Hiragino Sans is ten files on macOS. Each text laid out
afterwards repeated the 29 lookups under the font database's write lock.

- `fallbacks_for` reads, per family, the face nearest the run's style and
  only when it is nearer than the faces read already (`fallback_face`,
  `nearer_pending`); a face that can't be read gives way to the next one.
  Used by name, a family still reads all its faces (`find`).
- Faces of one file share its bytes across families (`file_bytes`, kept
  while the file keeps its length).
- The fallback faces are worked out once per style until fonts change
  (`FallbackLists`, by generation), not for every text laid out.
- Choosing a face by name before it is read counts a slant mismatch, italic
  or oblique, as `best` does: DejaVu Sans names its slanted faces Oblique,
  and a regular run's fallback stays Book.

Measured on Linux with Noto Sans CJK, DejaVu Sans and Inter installed: the
first text laid out read 41 font files (265 MiB, kept in memory) and parsed
41 faces; now 3 files (20 MiB) and 4 faces, 6 and 8 with a bold run too,
150–190 ms less file reading. The fallback lookups per text laid out took
about 45 µs and now 0.2 µs (lookup logic timed alone). The faces drawn are
the same except between two equally near the run's style.

Tests: fontdb_fallback_tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GmygZSTYRL3cVw7cJWMG3B
2026-10-30 12:24:57 +01:00