M12: session restore: windows and tabs come back as they were left

The interface keeps a saved session with the preferences, written whenever
it changes (at once, then at most once a second; nothing while idle): each
window's place, size, maximized or full-screen state and screen, its panels,
its tabs in order with the one in front, and per tab the saved file or your
online file (server and id, never a token), the page and the view.

At the next start the windows and tabs open again (`session.restore`): a
window off every screen moves onto one, files that are gone are skipped
with one message, online files are joined again as their owner and take
their place when they arrive, and a file or invite link from the command
line opens in front. Unsaved documents stay the recovery copies' job.

A mark written before restoring and cleared once the windows have settled
keeps a crash while restoring from repeating: the next run starts without
it and the home screen offers Restore last session. Preferences ▸ Reopen
windows and tabs from last time (`pref.restoreSession`) and `--fresh`
start without it. `window.list` reports each window's rectangle and state;
`ui.inspect` reports the kept session.

The saved-state reader takes junk, cut-off, huge and wrongly typed input
without failing; tests cover the round trip, order and front tab, missing
files, an online file through a scripted link, off-screen rectangles,
the crash guard, the preference, a command-line file and several windows.
This commit is contained in:
bflatastic
2026-10-13 13:38:00 +07:00
parent e56856f401
commit 264aa2a703
33 changed files with 2105 additions and 76 deletions
+6
View File
@@ -133,6 +133,12 @@ live sessions (`collab.*`: without a key on a server open to the public, with `c
`collab.manageFile` for the owner token and `collab.report`) and use plugin directories
(`plugin.directory.*`); the one-shot `run` can't (no network link).
The desktop app's own command line is `figcraft [--control PORT] [--fresh] [files…]
[figcraft://join?…]`: files and an invite link open in front of the windows and tabs from last
time, which open again by themselves (Preferences ▸ Reopen windows and tabs from last time);
`--fresh` starts without them once, leaving the preference as it is (`session.restore` still
brings them back in that run).
### `plugin publish <folder> --server ws://host:port/[?key=KEY]`
Publishes a plugin folder (`figcraft-plugin.json`, the module its `main` names, an optional `assets/`
+26 -3
View File
@@ -241,9 +241,12 @@ for menus, the Actions palette and `engine.execute`.
### `window.list {}`
Every window: `[{id, main, title, files, active, focused}]` (`files` are its tabs' names, `active`
the one it shows, `focused` the window requests go to). `ui.inspect` reports it as `windows`, plus
`window` (the window it ran in).
Every window: `[{id, main, title, files, active, focused, rect, maximized, fullscreen, monitor}]`
(`files` are its tabs' names, `active` the one it shows, `focused` the window requests go to;
`rect` is `[x, y, width, height]` in screen points, its outer position and inner size while it is
neither maximized nor full screen, so a maximized window reports the place it goes back to;
`monitor` is the screen showing most of it, `[x, y, width, height]`, or `null` when none is known).
`ui.inspect` reports it as `windows`, plus `window` (the window it ran in).
### `window.focus {id}`
@@ -257,6 +260,26 @@ closing while others are open takes over one of them, and closing the last windo
Close the app (every window, without asking about unsaved changes).
### Session restore
The desktop app keeps its windows and tabs with the preferences as they change and opens them
again at the next start (see [ui-parity.md](ui-parity.md)); `figcraft --fresh` starts without
them. `ui.inspect` reports it as `session`:
- `saved`: the session kept now, `{windows: [{rect, maximized, fullscreen, monitor, tabs: [{path}
| {server, file}, page, view: [cx, cy, zoom]], front, leftTab, rightTab, leftCollapsed,
panelWidths}]}`, the main window first. Tabs are saved files and your online files (their
server and id, never a token); documents never saved aren't in it.
- `restore`: the preference (`pref.restoreSession {on?}`).
- `offered`: this run started without the last run's session (the preference, `--fresh`, or the
last run never got through restoring), and `session.restore` brings it back.
- `joining`: restored online files still on their way from their servers.
- `monitors`: the screens the app knows, `[[x, y, width, height]]`.
`engine.execute {command: "session.restore", params: {session?}}` restores the session on offer
(else the one kept), or the saved session given: it returns `{windows, opened, joining, missing}`
and the windows are placed at the main window's next frame (`window.list` shows them).
## Example session (shell)
```sh
+9 -3
View File
@@ -1,6 +1,6 @@
# Where FigCraft falls short of Figma
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-13 · **Change:** minor (`.fig` export: instance sizes, variables with modes, shared styles, variable-width strokes; sharing with a join code; text box sizes measured against documents re-saved by other software; live sessions per document; .fig export checked by opening written files in other software; experimental .fig export; keyboard shortcut parity suite and bindings; Simplified Chinese draft catalog; Latin American Spanish overlay; prototyping tail: gamepad triggers, widgets in prototypes, mode lookups; plugin directory on figcraft-server; Japanese and Korean draft catalogs and CJK UI fonts; plugin widgets and the plugin panel tail; French, German and Brazilian Portuguese draft catalogs; cursor chat and spotlight in live sessions; layers and assets panels behaviour suite and fixes; vector multi-edit and edit tail; dev resources links; extended collections tail; branch version history and finer list merges; comments and version history behaviour suite and fixes; canvas navigation, guides and grids behaviour suite and fixes; `.fig` import: editable vector networks, more layer kinds, variable prototype actions; `.fig` import, best effort: gap 1 down to its tail; Windows QA pass: everyday workflows on Windows 11, eight fixes incl. unsaved work kept after a crash or a forced quit; Display P3: gamut warning and soft-proof (true P3 blocked upstream); several windows; localization layer with a draft Spanish catalog; hosting figcraft-server: wss in the desktop app, server releases, deployment guide; plugin panels and settings; canvas fixes: boolean hit testing on the result, group drags, frame outlines and slices; code connect; stretch and scatter brushes, pen pressure; text on a path and pattern fills; team libraries on the server and swap library; branches: create, update from main, review and merge; animated GIF fills and TIFF images; Open recent, outlines for the selection and mask outlines: menu breadth 100%; extended collections, variables import/export, gradient stop and variant bindings: gap 14 down to its tail) · **Target:** Figma Design (desktop app 126.10.7)
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-13 · **Change:** minor (session restore; `.fig` export: instance sizes, variables with modes, shared styles, variable-width strokes; sharing with a join code; text box sizes measured against documents re-saved by other software; live sessions per document; .fig export checked by opening written files in other software; experimental .fig export; keyboard shortcut parity suite and bindings; Simplified Chinese draft catalog; Latin American Spanish overlay; prototyping tail: gamepad triggers, widgets in prototypes, mode lookups; plugin directory on figcraft-server; Japanese and Korean draft catalogs and CJK UI fonts; plugin widgets and the plugin panel tail; French, German and Brazilian Portuguese draft catalogs; cursor chat and spotlight in live sessions; layers and assets panels behaviour suite and fixes; vector multi-edit and edit tail; dev resources links; extended collections tail; branch version history and finer list merges; comments and version history behaviour suite and fixes; canvas navigation, guides and grids behaviour suite and fixes; `.fig` import: editable vector networks, more layer kinds, variable prototype actions; `.fig` import, best effort: gap 1 down to its tail; Windows QA pass: everyday workflows on Windows 11, eight fixes incl. unsaved work kept after a crash or a forced quit; Display P3: gamut warning and soft-proof (true P3 blocked upstream); several windows; localization layer with a draft Spanish catalog; hosting figcraft-server: wss in the desktop app, server releases, deployment guide; plugin panels and settings; canvas fixes: boolean hit testing on the result, group drags, frame outlines and slices; code connect; stretch and scatter brushes, pen pressure; text on a path and pattern fills; team libraries on the server and swap library; branches: create, update from main, review and merge; animated GIF fills and TIFF images; Open recent, outlines for the selection and mask outlines: menu breadth 100%; extended collections, variables import/export, gradient stop and variant bindings: gap 14 down to its tail) · **Target:** Figma Design (desktop app 126.10.7)
Every known shortfall against Figma, one entry each, ranked by how much it stops a Figma user from
doing real work in FigCraft. Agents: pick work from the top unless the owner says otherwise. The
@@ -357,9 +357,14 @@ No alpha blockers: the alpha gate in [`roadmap.md`](roadmap.md#alpha-gate) passe
dragged off the strip; each window has its own tabs, panels and canvas and draws only when it
needs to; closing one asks about unsaved changes; `window.new`, `window.list`, `window.focus` and
`window` on any control request.
- **Landed (2026-10-13):** session restore: every window's place, size, state, screen, panels and
tabs are kept with the preferences as they change and come back at the next start (off-screen
windows move onto a screen; `session.restore`, `pref.restoreSession`, `--fresh`).
- **Missing:** wide-gamut colour on the canvas (egui draws sRGB, so P3 colours outside sRGB clip on
screen; exports keep them); a screen-reader tree in windows other than the main one (eframe 0.36
gives only the main window one); window positions restored at the next start.
screen; exports keep them). A screen-reader tree in windows other than the main one is blocked
upstream (eframe 0.36 gives only the main window an accessibility adapter): nothing to do here
until it adapts every window; meanwhile files stay tabs of the main window while a screen reader
runs.
- **Estimate:** 4–8 h.
### 19. AI features
@@ -394,6 +399,7 @@ No alpha blockers: the alpha gate in [`roadmap.md`](roadmap.md#alpha-gate) passe
| Date | Change | Summary |
|---|---|---|
| 2026-10-13 | minor | Gap 18: window places are restored at the next start (session restore: windows, tabs, pages, views and panels come back as they were left); what is left is wide-gamut colour on screen and the screen-reader tree in other windows, both blocked upstream; estimate and ranking unchanged |
| 2026-10-13 | minor | Gap 1: the experimental `.fig` export writes instance sizes (resized, filling an auto layout, scaled), variables with modes and bindings, shared styles and variable-width strokes, and the import reads them back. Checked by opening written files in other software: resized and scaled instances keep their size and lay their layers out for it, variables with their modes and colour bindings resolve there (a frame set to another mode shows that mode's colours, also inside instances), colour, text, effect and grid styles are listed, and variable-width strokes that are the same on both sides of the path draw with their width; number, string and boolean bindings and bindings on effects, layout guides and gradient stops come across as the values they give but did not show as bound there (their entries now also name the layer field they set, not yet checked there), and strokes wider on one side of the path are written as filled outlines, no longer editable strokes there (the stroke itself is kept as plugin data and our own import puts it back; not yet checked there). Hours and the ranking unchanged |
| 2026-10-12 | minor | Gap 2: your online files landed (the app records the files it put on a server with their owner tokens, Home ▸ Online lists them and opens them again as their owner, with sharing, rename, removal and forget from the list; one request per server tells which are still there; tabs mark files in a live session). What is left is unchanged: accounts, teams and per-person permissions, shared comments and versions. Hours unchanged |
| 2026-10-12 | minor | Gap 2: sharing with a join code (Share ▸ Online or Local network, one Start sharing button, a short code to give others, one join field for a code or a link; the server names links with codes and limits wrong ones) added to the landed list; usability, so the estimate and ranking are unchanged |
+3 -2
View File
@@ -1,6 +1,6 @@
# Hardware and platform parity
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-11 · **Change:** minor (Windows QA pass; Display P3: gamut warning and soft-proof (true P3 blocked upstream); several windows; pen pressure for the Pencil and brushes on Windows and from browser styluses) · **Target:** Figma Design (desktop app 126.10.7)
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-13 · **Change:** minor (window places restored at the next start; Windows QA pass; Display P3: gamut warning and soft-proof (true P3 blocked upstream); several windows; pen pressure for the Pencil and brushes on Windows and from browser styluses) · **Target:** Figma Design (desktop app 126.10.7)
How FigCraft uses hardware and which platforms it runs on, against Figma. Figma's desktop app is
Electron with a GPU helper process; its canvas renders on the GPU (WebGL, with WebGPU rolling out
@@ -18,7 +18,7 @@ since 2025). FigCraft renders the canvas on the CPU and presents it through wgpu
| Wide-gamut display (Display P3) | yes, on capable displays | colours stored and exported in P3; the screen shows sRGB: eframe/egui-wgpu 0.36 configure an 8-bit sRGB surface with no colour space option, although wgpu 30 can present Display P3 or extended sRGB on Metal, DX12, Vulkan and WebGPU (see gaps #18). The colour picker warns about colours outside sRGB and View ▸ Soft-proof sRGB stripes them on the canvas | 2–5 |
| Trackpad pinch zoom and two-finger pan | yes | yes (egui zoom delta, smooth scroll) | — |
| Pen tablet pressure (pencil, Figma Draw brushes) | yes (forum reports of regressions in 2025) | Windows pens (winit pointer input) and browser styluses that send touch events with a force (an Apple Pencil in Safari); the Pencil records it as the stroke's width profile. A mouse, macOS and Linux tablets and pens sending only pointer events in a browser report none: constant width | 1–3 |
| Several windows / multi-monitor | yes (a window per file; presenter in its own window) | desktop: File ▸ New window, a tab's Open in new window or a tab dragged off the strip; each window has its own tabs, panels and canvas, draws only when it needs to and asks about unsaved changes when it closes. Only the main window has a screen-reader tree (eframe 0.36), so files stay tabs while a screen reader runs; positions aren't restored at the next start; the presenter stays inside its window; one window in the browser | 1–2 |
| Several windows / multi-monitor | yes (a window per file; presenter in its own window) | desktop: File ▸ New window, a tab's Open in new window or a tab dragged off the strip; each window has its own tabs, panels and canvas, draws only when it needs to and asks about unsaved changes when it closes. Only the main window has a screen-reader tree (eframe 0.36), so files stay tabs while a screen reader runs (blocked upstream); each window's place, size, state and screen come back at the next start, and one whose screen is gone moves onto a screen there is; the presenter stays inside its window; one window in the browser | 1–2 |
| Screen readers | partial | AccessKit tree on desktop (names, roles, states), never tested with a real screen reader; none in the browser | 4–8 + human QA |
| Keyboard layouts (non-US) | yes | keymap uses logical keys; not checked on AZERTY/QWERTZ/JIS | 1–2 |
@@ -50,6 +50,7 @@ Nothing has been timed against Figma on the same document (needs `.fig` import).
| Date | Change | Summary |
|---|---|---|
| 2026-10-13 | minor | Several windows: places, sizes, maximized and full-screen states and screens are kept with the preferences and restored at the next start (a window off every screen moves onto one); numbers unchanged |
| 2026-10-11 | minor | Windows QA pass (gap 8): everyday workflows on Windows 11 through the desktop app and MCP; fixed: unsaved changes lost when the app was killed or crashed (recovery copies every few seconds, reopened at the next start), Ctrl+arrows/Backspace/Delete acting on the whole line in text (now by word; Ctrl+Home/End to the text's ends), scrubbed fields snapping back on release, typing on a field Tab reached, Escape not closing dialogs, skewed or vanishing linear gradients, hints cut off at the panel edge, the window-close question in English in the Spanish interface. Percentages and hours unchanged |
| 2026-10-11 | minor | Display P3 honest minimum (gap 18): the colour picker of a Display P3 file warns when a colour is outside sRGB (Outside sRGB, with what the canvas and exports do), and View ▸ Soft-proof sRGB (`view.proofSrgb`) stripes the canvas pixels sRGB can't show. Why the canvas still shows sRGB: wgpu 30 can present Display P3 or extended-range sRGB surfaces (Metal, DX12, Vulkan, WebGPU canvases), but eframe/egui-wgpu 0.36 configure an 8-bit sRGB surface with no option for the format or colour space, and egui's renderer writes sRGB-encoded UI colours; showing P3 needs those two upstream (or a patched egui-wgpu). Hardware 13–27 h → 12–26 h; gap 18 6–12 h → 5–11 h; percentages, feature breadth (~79%) and ready for real work (~47%) unchanged at this rounding; full parity ~363–697 h → ~362–696 h |
| 2026-10-11 | minor | Several windows (gap 18): File ▸ New window, a tab's Open in new window or a tab dragged off the tab strip opens files in another window with its own tabs, panels and canvas, sharing the files, preferences, libraries and clipboard; each window draws only when it needs to (idle: ~0% CPU), closing one closes its files after asking about unsaved changes (the main window too, which takes over another window instead of quitting; the last window quits), and the control channel and MCP open, list, focus and capture windows (`window.new`, `window.list`, `window.focus`, `window` on any request); the screen-reader tree covers the main window only (eframe 0.36), so with a screen reader running files stay tabs; one window in the browser. Hardware 55% → 60%, 13–27 h → 10–21 h; gap 18 6–12 h → 4–8 h (P3 on screen left); feature breadth (~79%) and ready for real work (~47%) unchanged at this rounding; full parity ~363–697 h → ~360–691 h |
+12
View File
@@ -922,6 +922,18 @@ opens one (a new file, the file at `path`, or open file `index` moved out of its
focus a window before working on its files, and pass its id to `screenshot {window}` to see it.
Headless (one session, no windows) and in the browser the two commands do nothing.
**Session restore.** The desktop app opens the windows and tabs it was left with at the next
start. `run_command` with `session.restore {session?}` does it on demand: without `session` it
restores the last run's session when this run started without it (else the one kept with the
preferences); with one, `{windows: [{tabs: [{path} | {server, file}, page?, view?: [cx, cy,
zoom]], front?, rect?, maximized?, fullscreen?}]}`, it opens those tabs in that order with their
page and view. It returns `{windows, opened, joining (your online files on their way from their
servers), missing (the names of files that are gone)}`; a file that is open already is used as it
is. Headless there are no windows and no preferences file, so pass `session`: the tabs of every
window open in the one session, in order, and the first window's front tab is the active document.
`pref.restoreSession {on?}` turns reopening at start on or off (on by default). Attached,
`inspect_ui` reports the kept session as `session.saved`.
### Live sessions
People (and agents) edit one file together and see each other's cursors, selections and
+4 -2
View File
@@ -1,6 +1,6 @@
# UI and interaction parity
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-13 · **Change:** minor (home screen: Templates tab, first-run templates and Getting started tips; number fields: scrub rates, arrow steps, arithmetic with brackets, relative edits of mixed values; outline mode's hidden layers and object bounds; Hide when publishing; cursors per tool and modifier; panel widths; dark pages for files made in the dark theme; drag threshold and double-clicks into text in groups; rotation origin on Alt+R and placing with Enter: no documented shortcut missing; keyboard shortcut parity suite and bindings; cursor chat and spotlight in live sessions; layers and assets panels behaviour suite and fixes; vector multi-edit and the vector edit tail; canvas navigation, guides and grids behaviour suite and fixes; shapes and vector behaviour suite and fixes; paint and effects behaviour suite and fixes; frames, groups, sections and masks behaviour suite and fixes; layers panel keyboard: F2 rename, Shift+F10 context menu, F8 box selection; selection and transform behaviour suite and fixes; Display P3: gamut warning and soft-proof (true P3 blocked upstream); several windows; boolean hit testing on the result, group drags, frame outlines and slices; outlines for the selection, mask outlines; arc fields, live boolean editing, shape builder on strokes, one-sided widths) · **Target:** Figma Design UI3 (desktop app 126.10.7)
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-13 · **Change:** minor (session restore: windows and tabs come back as they were left; home screen: Templates tab, first-run templates and Getting started tips; number fields: scrub rates, arrow steps, arithmetic with brackets, relative edits of mixed values; outline mode's hidden layers and object bounds; Hide when publishing; cursors per tool and modifier; panel widths; dark pages for files made in the dark theme; drag threshold and double-clicks into text in groups; rotation origin on Alt+R and placing with Enter: no documented shortcut missing; keyboard shortcut parity suite and bindings; cursor chat and spotlight in live sessions; layers and assets panels behaviour suite and fixes; vector multi-edit and the vector edit tail; canvas navigation, guides and grids behaviour suite and fixes; shapes and vector behaviour suite and fixes; paint and effects behaviour suite and fixes; frames, groups, sections and masks behaviour suite and fixes; layers panel keyboard: F2 rename, Shift+F10 context menu, F8 box selection; selection and transform behaviour suite and fixes; Display P3: gamut warning and soft-proof (true P3 blocked upstream); several windows; boolean hit testing on the result, group drags, frame outlines and slices; outlines for the selection, mask outlines; arc fields, live boolean editing, shape builder on strokes, one-sided widths) · **Target:** Figma Design UI3 (desktop app 126.10.7)
Fine canvas control is what Figma users feel first: handles, snapping, nudging, modifier keys,
drag behaviour, numeric precision. This checklist covers the tools, gestures and panels. Status:
@@ -24,7 +24,8 @@ interaction feel not yet compared.
| Home screen: Recents, Online and Templates | done (ours) | The sidebar switches between the three (`ui.set {homeSection}`). Online: your online files (see the collaboration checklist). Recents: new file, open, join with a code, open and recent files, a Getting started card (six tips with their shortcuts from the keymap; its close button is remembered in the preferences and Help ▸ Getting started brings it back) and, while there are no recent files, four templates to start from. Templates: the eight starter templates as cards (thumbnail rendered from the document, cached per theme; name, description, kind and size), a search field and a kind filter, an empty state; Tab reaches every card and Enter opens it; cards and tabs are named for screen readers. A first run opens here. No Community files or drafts folder |
| Main menu from the logo | done | generated from `catalog.rs`; popups sized to content |
| Keyboard shortcuts panel | done | docked, tabbed by group like the documentation, searchable, per-platform keycaps; held keys, gestures and presentation keys listed beside the bindings; a label too long for its column ends with "…" and shows in full on hover |
| Several windows | partial | File ▸ New window, Open in new window on a tab, a tab dragged off the strip; screen-reader tree in the main window only; positions not restored |
| Several windows | partial | File ▸ New window, Open in new window on a tab, a tab dragged off the strip; each window comes back at the next start where it was, with its size, state, panels and tabs (session restore, next row). A screen-reader tree in windows other than the main one is blocked upstream: eframe 0.36 gives only the main window an accessibility adapter, so while a screen reader runs files stay tabs of the main window (restored ones too) |
| Session restore | done (ours) | The app comes back the way it was left. Kept with the preferences, written whenever it changes (at once, then at most once a second, never while nothing changes; a crash or a forced quit has it too): each window's place, size, maximized or full-screen state and screen, its side panels' tabs and widths, its tabs in order with the one in front, and per tab the saved file's path or, for one of your online files, its server and id (never a token), the page shown and the view (one view per file, not per page). At the next start the windows and tabs open again; a window whose screen is gone or that no screen shows enough of to grab moves onto a screen (its own if it is still there, else the nearest) and is never larger than it; files that are gone are skipped with one message ("2 files couldn't be reopened") and stay in Open recent; an online file is joined again as its owner and takes its place among the tabs when it arrives (one whose server can't be reached is skipped with a message saying so, and stays under Home ▸ Online); a file or invite link the app was started with opens in addition, in front. Documents never saved aren't part of it: unsaved work comes back from the recovery copies after a crash, and a normal quit keeps none. Preferences ▸ Reopen windows and tabs from last time (`pref.restoreSession`, on by default) and the `--fresh` flag start without it. If the last run never got through restoring (a mark written before and cleared once the windows have settled), this run starts on the home screen without restoring, and the home screen offers Restore last session (`session.restore`) instead. A first run is still the home screen. Holding Shift at start isn't read (the flag is the way); the browser keeps no preferences, so nothing is restored there |
| Multiplayer avatars, Share button | missing | waits for multiplayer |
| Blend mode menus: the layer's (Design panel) and each paint's (colour picker) | done | Pass through and Normal are distinct (Normal isolates a group's or frame's children); paints have no pass-through; plus darker drawn exactly on the canvas |
@@ -164,6 +165,7 @@ in the table. `crates/ui-egui/src/shortcut_keys_tests.rs` drives the keys a look
| Date | Change | Summary |
|---|---|---|
| 2026-10-13 | minor | Session restore: the windows and tabs open when the app was left open again at the next start: each window's place, size, maximized or full-screen state, screen, panels and tabs in order with the one in front; per tab the file (or your online file, joined again as its owner), its page and view. Written with the preferences as it changes; windows off every screen move onto one; files that are gone get one message; a crash during restoring starts the next run without it and offers it on the home screen; Preferences ▸ Reopen windows and tabs from last time, `--fresh`, `session.restore`, `pref.restoreSession`; `window.list` reports each window's rectangle and state. Several windows: positions are restored; the screen-reader tree in other windows stays blocked upstream |
| 2026-10-13 | minor | Home screen: a Templates tab (eight starter templates as cards with thumbnails, search and a kind filter; click or Enter opens a new document) replaces the Community placeholder, the Drafts placeholder is removed, Recents offers four templates while there are no recent files and shows a Getting started card (closable; Help ▸ Getting started brings it back), File ▸ New from template…, and a first run opens on the home screen |
| 2026-10-12 | minor | Everyday editing partials: number fields (scrub a step a point, ×10 with Shift, ×0.1 with Alt, on past the screen edge where the platform reports it; arrow keys by the nudge preferences, opacity and rotation by 1 and 10; brackets and units in arithmetic; `50%` relative outside percentage fields; Tab commits and moves on; an untouched field commits nothing; relative edits and arrow keys on Mixed go to each layer in one undo step) done; outline mode's Include hidden layers and Include object bounds, drawn and clickable, done; Hide when publishing from the Assets panel done (the name's leading `.`); cursors per tool and modifier done (a table in the engine, drawn rotate, pen, eyedropper and comment cursors, not-allowed on refused edits; guides and handles keep their cursors); resizable panels done (limits, double-click reset, kept per window and in the preferences, the canvas keeps its room in a small window); a file or page made in the dark theme has a #1E1E1E page (the light theme and sessions without an interface: #F5F5F5) and text drawn on a dark page is white; Enter on a text selects all of it (test added). Menu items: View ▸ Outlines ▸ Include hidden layers / Include object bounds, View ▸ Panels ▸ Reset panel widths, Libraries ▸ Hide when publishing |
| 2026-10-12 | minor | Drag threshold and double-clicks: the second press of a double-click began a move or resize that was never finished, so double-clicking text inside a group often didn't start editing (from the middle of the text) or dragged and resized it when the hand moved a pixel or two; a move or resize now starts only after 3 px of travel on screen and a double-click drops the press's gesture first |