Commit Graph
103 Commits
Author SHA1 Message Date
bflatastic f32e8c5d2d Merge #306: M1: say why when the window can't open (#261) (@Barzabel) 2026-10-15 19:55:06 +07:00
bflatastic 01463fb78e Merge #368: Variables export as a download in the browser (@mateusvillain)
# Conflicts:
#	crates/ui-egui/src/variables_panel.rs
2026-10-15 19:55:00 +07:00
bflatastic 2ea8c3f86f Merge #338: M9: remove someone from a live session (@HaSh3003) 2026-10-15 19:54:09 +07:00
bflatastic 51549f9a60 #306: say why the window can't open in the interface language
The message now comes from the UI crate (dialogs::window_failed) through
tr() and trf(), with entries in every catalog, and the app picks the
language from the preferences before the event loop starts, so the box
reads in it even though no frame was ever drawn. The commands to type stay
as written.
2026-10-15 19:36:00 +07:00
bflatastic be875da985 Merge #346: Set the native window identity to match the desktop entry (@IanHollow) 2026-10-15 19:33:07 +07:00
bflatastic 48f75c92da Merge #313: M0.9: answer control requests while the window is hidden (#269) (@AganzeFelicite) 2026-10-15 19:32:27 +07:00
bflatastic 120aa8a7a0 Merge #336: M1: keep a recovery copy until this run has its own (#187) (@Barzabel) 2026-10-15 19:32:23 +07:00
bflatastic 09ad21489b Merge #331: fix(recovery): keep the version history and branches in recovery copies (#185) (@vxMacDev) 2026-10-15 19:32:22 +07:00
bflatastic 0a2ed2fb65 Merge #303: Recovery: wait for the write in flight before an emergency save and before removing copies (#202) (@MarekSpodBiedry) 2026-10-15 19:32:20 +07:00
bflatastic 22d5f17828 Merge main and the community batch into #306
# Conflicts:
#	apps/figcraft/src/main.rs
2026-10-15 19:27:31 +07:00
bflatastic dd84097b6d #368: revoke a download's object URL after a delay
Revoking it right after the click can cancel the download in some
browsers; it now goes 40 s later on a timer.
2026-10-15 19:04:16 +07:00
bflatastic 466bf6a813 Merge main and the community batch into #368
# Conflicts:
#	apps/figcraft-web/src/web.rs
#	crates/ui-egui/src/lib.rs
2026-10-15 19:02:58 +07:00
bflatastic e100c165fb #346: FreeBSD's desktop entry matches the window class there (the binary's name) 2026-10-15 19:02:40 +07:00
bflatastic 370d9f7adc Merge main and the community batch into #346 2026-10-15 19:00:48 +07:00
bflatastic 8bcb0f78dd #338: drop the start/end feat marker comments 2026-10-15 18:37:52 +07:00
bflatastic e50bafbb75 Merge main and the community batch into #313
# Conflicts:
#	ROADMAP.md
#	apps/figcraft/src/main.rs
#	docs/roadmap.md
2026-10-15 18:37:11 +07:00
bflatastic 54f9212a2f Merge main and the community batch into #338 2026-10-15 18:35:05 +07:00
bflatastic e15242f506 Merge main, the community batch, #303 and #331 into #336
# Conflicts:
#	apps/figcraft/src/recovery.rs
#	apps/figcraft/src/recovery_tests.rs
2026-10-15 18:27:43 +07:00
bflatastic 0757800b3d Merge main, the community batch and #303 into #331
# Conflicts:
#	apps/figcraft/src/recovery.rs
#	apps/figcraft/src/recovery_tests.rs
2026-10-15 18:24:31 +07:00
bflatastic 379e4b5c55 Merge main and the community batch into #303
# Conflicts:
#	apps/figcraft/src/recovery.rs
#	apps/figcraft/src/recovery_tests.rs
2026-10-15 18:21:15 +07:00
bflatastic 69de1ee36f #253: a dialog's result goes to the file and window it was opened for; dialogs are parented to the main window 2026-10-15 18:12:35 +07:00
bflatastic 8b1613c7ee Merge main and the community batch into #253 2026-10-15 18:00:57 +07:00
bflatastic 4f12bf1e00 Merge #297 fix: recovery retry tests run on Windows 2026-10-15 18:00:10 +07:00
bflatastic 471694dc48 #297: recovery retry tests fail the copy with a folder in its place, so they also run on Windows 2026-10-15 18:00:02 +07:00
bflatastic fc7556ae7f Merge main and the community batch into #253
# Conflicts:
#	contributors/people.toml
2026-10-15 17:58:35 +07:00
bflatastic 55eaeb8709 Merge #290: M1: open .figcraft files from Finder, Open With and the Dock on macOS (@marcoarnulfo) 2026-10-15 17:54:25 +07:00
bflatastic 8ae567c06b Merge #254: fix(engine): read the documented gradient shorthand on every route (#252) (@pcastro93) 2026-10-15 17:53:00 +07:00
bflatastic 097110b359 Merge #297: Count a recovery revision as copied only after its write succeeds (@Silvertree2010)
# Conflicts:
#	contributors/people.toml
2026-10-15 17:52:15 +07:00
bflatastic d337b34380 Merge #340: M9: a compaction cut short closes the file instead of confirming lost edits (#183) (@Barzabel) 2026-10-15 15:10:38 +07:00
bflatastic 731b7e356a Merge #294: fix(desktop): Windows' first preferred language picks the UI language (#291) (@fede9234)
# Conflicts:
#	ROADMAP.md
#	docs/roadmap.md
2026-10-15 15:10:19 +07:00
bflatastic a8604adbca Merge #302: fix(server): keep each team library version in its own file (#206) (@MarekSpodBiedry) 2026-10-15 15:10:14 +07:00
Mateus Villain 3edb15c417 M1: copy and paste through the system clipboard in the browser
The web build's Services never wrote to the clipboard, so Cmd+V after
Cmd+C got the paste event with whatever text the clipboard held before
and made a text layer of it instead of pasting the copied layers.
WebServices now writes copies (text and PNG) through egui's output,
which eframe hands to the browser clipboard during the copy event.
2026-10-14 20:26:18 -03:00
Mateus Villain 01a0f4f332 M3: variables export as a download in the browser
The web build has no save dialogs, so Export… ▸ Variables JSON / CSS
custom properties returned silently. Services gains downloads() and
download(name, bytes); the browser hands the file over through a Blob
link, and the variables panel uses it where the platform saves by
downloads.
2026-10-14 20:01:53 -03:00
IanHollow 212438a6e3 Set the native window identity to match the desktop entry
Assisted-by: OpenAI Codex (GPT-6)
Signed-off-by: IanHollow <72767437+IanHollow@users.noreply.github.com>
2026-10-14 13:12:38 -07:00
Barzabel 90a4606c65 M9: a compaction cut short closes the file instead of confirming lost edits (#183) 2026-10-14 22:53:02 +03:00
HaSh3003 fa0365470e M9: remove someone from a live session
Right-click a person's avatar ▸ "Remove <name> from session", or
`collab.removePerson {client}`, when you host the session or own the file
on a server. The hub closes their connection as the end of the session for
them (close 1001: they keep their copy and don't reconnect) and bars their
address from that file while it runs, so the code or link they hold no
longer gets them in; everyone else stays connected.

Protocol addition within version 2: `Admin::RemovePeer {file, client}` on
an open hosting connection with the file's owner token (or the server
key). Older servers say they can't.

Tests: loopback (removed, can't rejoin, others stay), engine (host can,
guest can't, bad ids refused), codec round trip; the collab junk sweep
covers the new command.
2026-10-14 22:32:56 +03:00
Barzabel ac8a0a112c M1: keep a recovery copy until this run has its own (#187) 2026-10-14 22:10:49 +03:00
vxMacDev b821b6f8f4 fix(recovery): keep the version history and branches in recovery copies (#185)
Recovery copies were written with plain `save_bytes`, so a file
recovered after a crash came back without its version history and
branches, even though `file.recover` reads both. Copies now go through
`save_bytes_with_history` like a normal save, with each open branch
tab's latest edits (`branches::current`), since `sync` only puts those
in before the next command.

A copy was also only redone when the main file's revision changed, and
a file with edits only in a branch tab didn't count as changed. Both
checks now include the file's branch tabs.
2026-10-14 13:41:17 -05:00
AganzeFelicite f9b7aa03ca M0.9: answer control requests while the window is hidden
A minimised or covered main window draws no frames, and control requests
were only answered inside a frame, so every control-channel and attached
MCP call (save_file among them) timed out after 60 s while the app was out
of sight. eframe still calls the app's logic then whenever a repaint is
requested, which the control server already does for each request.

The desktop app's logic now answers, while the window is hidden, the
requests that need no frame: engine.execute, engine.commands,
document.inspect, node.get, window.list and ui.render. Screenshots, input
and the interface's own state still wait for the window, and their
timeout now says that the window has to be on screen.

Closes #269
2026-10-14 17:27:01 +02:00
Barzabel 8b8825ce68 M1: say why when the window can't open (#261)
Release builds on Windows have no console, so an eframe::run_native error
(no usable graphics adapter, a device the driver refuses) went to an unseen
standard error and the app quit silently. The error is now logged and shown
in a message box with a hint: unset WGPU_BACKEND when it is set, otherwise
update the driver or try another graphics API (OpenGL on Windows), and
where to report it. With --control the box is skipped so agents aren't
blocked.
2026-10-14 17:37:59 +03:00
MarekSpodBiedry a8a689d682 fix(server): keep each team library version in its own file (#206) 2026-10-14 16:19:01 +02:00
MarekSpodBiedry 8b961b980a Recovery: wait for the write in flight before an emergency save and before removing copies (#202) 2026-10-14 16:12:40 +02:00
NetterSilverandClaude Haiku 5.5 4193a82dfb Count a recovery revision as copied only after its write succeeds
Fixes #186

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-14 16:08:47 +02:00
fede9234 3709e7320c fix(desktop): Windows' first preferred language picks the UI language (#291)
Windows' preferred-language list is also the input-language list: a language
added for a keyboard sits in it, and taking the first entry with a catalog
turned the interface German on a Polish system (a German keyboard) while the
system and the other apps stayed Polish. Only the first preferred language now
decides; when it has no catalog the interface reads English. macOS'
AppleLanguages and gettext's `LANGUAGE` still take the first language with a
catalog. Fixes #291.

Generated with Codebuff 🤖
Co-Authored-By: Codebuff <noreply@codebuff.com>
2026-10-14 14:54:01 +02:00
Marco Arnulfo 310cb40af9 M1: open .figcraft files from Finder, Open With and the Dock on macOS (fixes #289) 2026-10-14 13:58:37 +02:00
Piettro CastroandClaude Opus 5.5 f3cd0509cb fix(engine): read the documented gradient shorthand on every route (#252)
`{"type":"linearGradient","stops":["#hex",…]}` was only expanded by the MCP
tools, so `figcraft-cli run` and the control channel's `engine.execute`
refused it ("`fills` must be paints or colours"). The expansion now lives in
the engine (`params::normalize_paint`, used by `paint_of`), so node.set,
node.create props, fill.add/set, strokes and paint styles all take it; MCP
calls the engine's copy instead of its own.

Tests: engine (every paint command, MCP-equal defaults, junk still refused),
control channel `engine.execute`, and `figcraft-cli run` end to end.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 01:02:45 -05:00
Justin John 94ce2a3611 M13: make native file dialogs asynchronous 2026-10-14 11:04:30 +05:30
bcedfeba10 M7: recent files as thumbnail cards on the home screen (#249)
The Recents section shows recent files as cards: the picture each file
carries (thumbnail.png in .figcraft and .fig, an image file itself) fitted
on its first page's colour, a divider, and a footer with the file's icon,
name and "Edited ... ago" (or "File not found"); the full path on hover.
Pictures are read off the frame's thread, only for cards in view, cached
by path and modification time, capped in bytes and pixels; missing,
damaged or oversized ones give a placeholder. They fade in, and cards
show a skeleton until their file has been looked at.

A sort menu (Alphabetical, Date created, Last modified; either order) and
a grid/list toggle sit above them. The list is a Name, Last modified and
Created table whose headers sort. View (per section) and sort are kept in
the preferences and set with ui.set {homeRecentsView, homeRecentsSort,
homeRecentsOrder}. A click selects, a double-click or Enter opens, arrow
keys move the selection; a right-click offers Open, Show in folder and
Remove from recents (file.openRecent {remove}).

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: bflatastic <bombayapirat@gmail.com>
2026-10-14 12:00:20 +07:00
8e12e5eeda fix(server): never persist a snapshot the reader refuses (#188) (#236)
Snapshots hold more than the document (recent batches, deletions), so near
the cap compaction could write one over max_file_bytes, which both readers
then refused: the file vanished on restart. Reading now allows twice the
cap, and compaction refuses a snapshot beyond that, keeping the old
snapshot and log.

Co-authored-by: Justin John <babyjjbabyjj549@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 10:31:30 +07:00
118ca7c60b fix(desktop): write preferences owner-only on Unix (#200) (#235)
state.json holds online owner tokens. The temporary file is now created
0600 (and narrowed if a crash left one behind) before anything is written,
and the rename carries that mode to state.json, so an older
world-readable file is replaced on the next save.

Co-authored-by: Justin John <babyjjbabyjj549@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 10:31:17 +07:00