Commit Graph
2353 Commits
Author SHA1 Message Date
BFlat 5804c0e2cc Merge pull request #1489 from ChristopherLinnett/issue/857-confirm-quit
fix(app): ask before ⌘Q quits with unsaved changes (#857)
2026-10-29 09:41:19 +07:00
BFlat 738f7c7692 Merge pull request #1470 from watchakorn-18k/fix/context-menu-frame-label
fix(ui): right-click on a frame's name label picks that frame
2026-10-29 09:37:58 +07:00
BFlat 3a86db900d Merge pull request #1424 from samhyun/fix/keepalive-ping-under-presence
M9: a ping every keep-alive interval, whatever else the client sends
2026-10-29 09:37:20 +07:00
BFlat ea2a8ea84a Merge pull request #1443 from devius/ka-new-strings
i18n(ka): Georgian for 76 strings added since the language landed
2026-10-29 09:35:42 +07:00
BFlat 84e0ea5449 Merge pull request #1393 from kler/swedish-ui-2026-10-26
i18n(sv): translate 47 new strings
2026-10-29 09:35:37 +07:00
BFlat cff1d0bf45 Merge pull request #1487 from ChristopherLinnett/issue/1096-openurl-gesture
fix(present): prototype links open only behind the notice or a viewer's click (#1096)
2026-10-29 09:30:04 +07:00
BFlat baaafc381b Merge pull request #1485 from StrajnarFilip/claude/fix-1476-guides-reopen
M1: page ruler guides survive save and reopen (#1476)
2026-10-29 09:29:31 +07:00
BFlat 95fd3c2444 Merge pull request #1482 from StrajnarFilip/claude/fix-1452-stroke-weight
M1: the stroke weight keeps room for its value beside the variable button (#1452)
2026-10-29 09:29:26 +07:00
BFlat 712074ae2d Merge pull request #1481 from StrajnarFilip/claude/fix-1085-normalize-guard
M8: normalising after a command runs under the panic guard (part of #1085)
2026-10-29 09:29:21 +07:00
BFlat f8355c0680 Merge pull request #1480 from StrajnarFilip/claude/fix-1078-linear-repair
M8: repair and library manifests check membership by set lookups (#1078)
2026-10-29 09:28:53 +07:00
bflatastic 1ed9eb6b8c Merge main into #1393 2026-10-29 09:20:18 +07:00
bflatastic 0da3a564ca Merge main into #1443 2026-10-29 09:20:09 +07:00
bflatastic dfe83f63f0 Merge main into #1470 2026-10-29 09:19:59 +07:00
Christopher Linnett 0e508fd316 fix(app): a second quit before the window draws counts once (#857)
The app's logic runs while the main window is minimised, without the
frame that acts on a close. Two quits there queued the main window's close
twice: the first let it take over another window, and the second then
quit the app over that window's unsaved changes, as answered.

- close_current queues a window's close only once.
- Test: quitting_twice_before_the_window_draws_closes_it_once.
- docs/hardware-parity.md revision history.
2026-10-29 08:50:00 +08:00
Christopher Linnett 7660877845 fix(present): nothing opens or releases behind an open link notice (#1096)
- finish(): a viewer-fired link opens directly (notice skipped) only while
  no notice shows; any other link that fires while one shows is dropped.
- finish(): raising a notice ends the press under way, so its release
  doesn't fire the prototype's mouse-up actions (a link, a navigation)
  behind the notice, which takes no input while it shows.
- The mail notice says the link opens the mail app to write a message
  (opening a mailto: link doesn't send anything).
- Tests: nothing_opens_while_a_notice_shows_with_the_notice_skipped,
  a_press_that_raised_a_notice_doesnt_release_behind_it.
- docs/prototyping-parity.md row and revision history.
2026-10-29 08:50:00 +08:00
Christopher Linnett 73398cedf1 fix(app): ask before ⌘Q quits with unsaved changes (#857)
winit's default macOS app menu ends the process through AppKit's
`terminate:` at once, so ⌘Q and Quit from the menu bar never asked about
unsaved changes (the recovery copies were all that survived).

- Install craft-libs' app menu (craft-menu, same rev as the other
  craft-libs pins; macOS only). Its Quit sends the main window a close
  request, the same path as the window's close button, so
  windows::on_close_request cancels the close and the unsaved-changes
  question asks first. Failure to install keeps winit's menu and logs it.
- windows_tests::a_quit_with_unsaved_changes_waits_for_the_answer pins
  the contract the menu relies on: a close request with unsaved changes
  sends CancelClose and asks; Don't Save then closes.
- Like the close button it closes the main window only: with several
  windows open, each quit closes one (documented).
- docs/hardware-parity.md macOS row, status line and revision history.
- Cargo.lock: craft-menu, craft-quit, craft-keymap, muda and their deps;
  cargo's own minimal resolution also moves a few windows-sys/getrandom
  edges to versions already in the lock.
2026-10-29 08:11:13 +08:00
Christopher Linnett 53f47706ec fix(present): prototype links open only behind the notice or a viewer's click (#1096)
An Open link action carries a URL from the document and fires from whatever
trigger the prototype sets, so an unattended presentation could open web links
and mail messages one after another: a mail link bypassed the leaving-the-
prototype notice entirely, and a skipped notice let any trigger open any
number of links.

- finish() routes every openable URL, mail included, through the notice.
- Skipping the notice ("Don't show this again") opens at once only a link the
  viewer's own click, press, drag or key fired, one per frame. A delay, the
  pointer passing over a layer (enter, leave, hover) and a timed mouse
  trigger that fires after the gesture is over still show the notice, which
  then offers no checkbox: it couldn't skip that notice anyway.
- The player tags each queued link with whether the viewer fired it
  (Presenter::fire_from); an OpenUrl outside an interaction defaults to not.
- The notice covers mail links (new locale string, mail wording).
- Engine prefs/command doc text follows the rule; behavior untouched there.
- present_links_tests: shared setup helpers for the link tests; new
  tests for the skip rule (delay, hover, delayed mouse-up, key, one link per
  click, checkbox only for clicked links); the scheme-filter test now clicks
  with the notice skipped so the filter alone keeps those URLs out.
- docs/prototyping-parity.md row, status line and revision history updated.
2026-10-29 08:11:13 +08:00
Filip StrajnarandClaude Opus 5.5 652bf35b19 M1: page ruler guides survive save and reopen (#1476)
A page kept its ruler guides in `NodeKind::Page`, and since frame guides
(#70) every layer also has its own `guides` field. Both are written as
`guides`, and on reading the layer's own field takes the key, so:

- a reopened page's guides landed in the layer field and were not drawn;
- saving that page wrote `guides` twice (the page kind's list, always
  written, then the layer's), and the file no longer opened ("duplicate
  field `guides`").

Every layer, pages included, now keeps its guides in the one layer field;
the key in the file is unchanged, so existing files open with their guides.
The field reads every `guides` list a layer has, so files already saved
with the key twice open again with both lists, in file order. This also
covers collab `Create` payloads from older peers.

Regressions: JSON round trips of page and frame guides, a page with two
lists, a bad list still refused (doc); save, reopen, save, reopen through
`.figcraft` and a document.json with the key twice (format). Checked in the
app over the control channel: guides drawn after two save/reopen cycles, and
a file with the key twice opens with all its guides.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LvG6Dyzof21BCrUsByhx2w
2026-10-28 22:47:24 +01:00
Filip StrajnarandClaude Opus 5.5 62c69ba7ab M8: normalising after a command runs under the panic guard (part of #1085)
Session::execute ran a command under guard::run but normalised what it
changed afterwards, outside it: a panic in normalisation escaped execute
instead of becoming EngineError::Internal with the edit rolled back. Inside
a batch it unwound through Session::grouped, which then never restored the
undo limit it had lifted or ended the group. Normalising is now the last
step of the guarded result chain, so a panic there fails the command like
one in the command itself (and a batch step fails like any other failed
step); live text previews normalise under the guard too.

The other half of #1085, restoring grouped()'s state when its closure
panics, is left alone: #1419 rewrites that function.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LvG6E2qDnjtMzfPVuEP7iH
2026-10-28 22:11:31 +01:00
Filip StrajnarandClaude Opus 5.5 8d7c094224 M1: the stroke weight keeps room for its value beside the variable button (#1452)
The stroke's position dropdown took half the row and the weight field what
was left after the per-side and Advanced buttons: about 40 pt at the
panel's default width, so the variable button sat on the weight's icon and
hid its value, and the row ran 3 pt past the panel's edge. The position
and the weight now share what the buttons leave: the panel's two columns
for layers without per-side strokes, and about 66 pt each with them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LvG6E2qDnjtMzfPVuEP7iH
2026-10-28 22:10:28 +01:00
Filip StrajnarandClaude Opus 5.5 d5ce10f0be M8: repair and library manifests check membership by set lookups (#1078)
Repair re-listed unlisted pages with a scan of the page list per page, and
reading a published library kept manifest styles, collections and variables
with a scan of the snapshot's lists per entry: a file with many pages or a
long manifest made both quadratic. Both now look ids up in a set built once.
validate() already indexed its parent/child edges and page list.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LvG6E2qDnjtMzfPVuEP7iH
2026-10-28 22:10:28 +01:00
Dylan M. TaylorandClaude 2af5e232d5 Honor CARGO_BUILD_TARGET in FreeBSD packaging for aarch64 release builds (#1475)
Resolve host-tuple to the host triple, pass --target to cargo build when
CARGO_BUILD_TARGET is set, and skip the --version smoke run for cross
builds (they cannot run on the x86_64 VM); cross builds get an ELF check
instead. Archive names carry the arch from the target triple.

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-28 15:48:52 -04:00
Brandon ThomasandClaude Opus 5.5 ef9721c5b9 Release 0.12.1
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
v0.12.1
2026-10-28 13:37:05 -04:00
Brandon ThomasandClaude Opus 5.5 cb227c9715 Web: raise the wasm size gate to 25 MiB - 512 KiB
The 0.12.0 release's Web job failed at 25,319,327 bytes against the 24 MiB (25,165,824-byte) gate. opt-level z, fat LTO and wasm-opt -Oz are already in place and extra wasm-opt passes save only ~20 KB, so the gate moves to 25,690,112 bytes, still under Cloudflare's 25 MiB per-file cap. The wasm grew ~2 MB in three days (egui 0.37, new features); bringing it back down is follow-up work.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 13:36:52 -04:00
Dylan M. Taylor 32e8fd0b29 Grant network access so update checks can reach GitHub (#1471) 2026-10-28 13:20:45 -04:00
Dylan M. Taylor fa1c6cba42 Merge pull request #1403 from dylanmtaylor/sonar/enforce-clippy-standards
Enforce Rust coding standards via Clippy
2026-10-28 12:50:16 -04:00
Brandon ThomasandClaude Opus 5.5 08204fd7c2 Release 0.12.0
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 12:18:40 -04:00
Dylan M. Taylor 94cf3f3fd5 test(text): derive wrap threshold from matching glyph metrics 2026-10-28 16:00:36 +00:00
Dylan M. Taylor 763c3a8dc4 refactor(svg): split node rendering and text setup 2026-10-28 16:00:36 +00:00
Dylan M. Taylor 8df2e4f8dc refactor(render): pass context through export helpers 2026-10-28 16:00:36 +00:00
Dylan M. Taylor 95a456f391 refactor(server): simplify storage and collaboration helpers 2026-10-28 16:00:36 +00:00
Dylan M. Taylor ffb4fc7e3e refactor(ui): simplify app and presentation handlers 2026-10-28 16:00:36 +00:00
Dylan M. Taylor 252d909427 refactor(ui): simplify widgets and dialogs 2026-10-28 16:00:36 +00:00
Dylan M. Taylor 927ceb0638 refactor(ui): simplify panels and menus 2026-10-28 16:00:36 +00:00
Dylan M. Taylor e98b97de2b refactor(engine): simplify session and test helpers 2026-10-28 16:00:36 +00:00
Dylan M. Taylor d87f9effe1 refactor(engine): simplify asset and code generation helpers 2026-10-28 16:00:36 +00:00
Dylan M. Taylor 5e16683963 refactor(engine): simplify canvas and board handlers 2026-10-28 16:00:36 +00:00
Dylan M. Taylor 23f57c8660 refactor(engine): simplify command handling for strict clippy 2026-10-28 16:00:36 +00:00
Dylan M. Taylor bafda992a7 docs: clarify crate lint placement 2026-10-28 16:00:36 +00:00
Dylan M. Taylor 4268bd859f refactor(fig): split mapping and lint test helpers 2026-10-28 16:00:36 +00:00
Dylan M. Taylor 6ebcf6b511 refactor(text): split shaping and layout finishing 2026-10-28 16:00:36 +00:00
Dylan M. Taylor c618e402fa refactor(format): replace wildcard imports 2026-10-28 16:00:36 +00:00
Dylan M. Taylor 99afdd99ab docs: document workspace lint inheritance 2026-10-28 16:00:36 +00:00
Dylan M. Taylor 8591d44909 refactor(doc): declare node property dependencies 2026-10-28 16:00:36 +00:00
Dylan M. Taylor 10bb163626 fix(xtask): apply workspace lint policy 2026-10-28 16:00:35 +00:00
Dylan M. Taylor e1a223bb1f refactor(layout): split flow layout phases 2026-10-28 16:00:35 +00:00
Dylan M. Taylor c420613efa chore(clippy): enforce strict workspace lint policy 2026-10-28 16:00:35 +00:00
watchakorn-18kandClaude Sonnet 5.5 38ab0eaa6b docs(ui): document the right-click label pick and its tests
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015wxxFg3gana4zaUKnyirTC
2026-10-28 22:27:29 +07:00
watchakorn-18kandClaude Sonnet 5.5 df6062d7fb fix(ui): right-click on a frame's name label picks that frame
The context menu looked only at what is under the pointer on the page, so a name label drawn over
its section selected the section. Copy link to selection then gave every frame in that section the
section's link. Labels now win, as they do on a press.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015wxxFg3gana4zaUKnyirTC
2026-10-28 22:14:06 +07:00
Davit MatchakhelidzeandClaude Opus 5.5 a7ea510c65 i18n(ka): მხარდაუჭერელის in "Ignore unsupported"
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YMTAbGNRxnMEzRvYnQGphF
2026-10-28 05:11:34 +04:00