Commit Graph
11 Commits
Author SHA1 Message Date
BFlat ecb3656c69 M1: open recent, outlines for the selection, mask outlines (#115)
The last three catalogued menu items got commands: File > Open recent (recent files kept in preferences, capped, missing files greyed and dropped when picked, Clear recent), outlines for the selected layers only, and mask outlines. Menu breadth 100%.
2026-10-11 11:26:57 +07:00
BFlat 07fa4d92ed M9: standalone collaboration server with share links and permissions (#112)
figcraft-server hosts many files over the same hub the app uses for sessions, persists each as a checksummed snapshot plus an append-only log (synced before replies, compacted, damaged files skipped and reported) so restarts lose nothing confirmed, and gives per-file share links with edit or view access (hashed 128-bit tokens, revocable). The app can publish a file to a server and join server-hosted files; view-only tabs refuse edits. Protocol version 2.
2026-10-11 10:19:03 +07:00
BFlatandClaude Opus 5.5 c49a72ea88 M8: accessibility: screen reader names, keyboard navigation mode (#96)
* M8: accessibility: screen reader names, keyboard navigation mode

- Screen readers: the custom-painted controls report a role, name, value and
  state to AccessKit (number and text fields, dropdowns, segmented and toggle
  buttons, tools with their keys, layer rows as tree items, pages, tabs, menu
  items, the canvas describing the selection), from the shared widget helpers
  and a `Tip` trait for ad-hoc icon buttons. Regions are named containers.
- Keyboard navigation: F6 / Shift+F6 (view.nextRegion / view.previousRegion)
  cycle the toolbar, layers, canvas and properties; Tab / Shift+Tab move within
  a region and wrap; Enter or Space activate; arrows move along the toolbar and
  through the layer rows; menus and flyouts opened from the keyboard take it and
  give it back; Escape returns to the canvas. A focus ring (new `focus` token)
  shows until the next pointer press. Tab on the canvas selects the next layer
  again instead of moving egui's focus to the tab strip; Enter that starts a
  field edit no longer ends it.
- Reduced motion: pref.reduceMotion and the system setting (Windows
  UISettings, macOS, GNOME, prefers-reduced-motion) turn egui's animations off.
- Contrast: light secondary and accent text meet WCAG AA.
- ui.inspect reports focus {region, keyboard, control} and reduceMotion;
  ui.set {focusRegion}.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* M8: parity report command count after merging main

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* M8: accessibility: regression test against nested egui context locks

A debug build's temporary logging called the context inside a context closure and hung; the shipped code never does. Document the rule in a11y.rs and run every accessibility path with the AccessKit tree on, so a nested call fails the test (debug builds panic after 10 s) instead of hanging.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 23:02:50 +07:00
BFlatandClaude Opus 5.5 94aab893b0 M7: keyboard shortcut parity (#88)
One keymap (figcraft_engine::keymap) now holds every default shortcut,
grouped like the public shortcut reference, with macOS and Windows/Linux
keys where they differ and canvas / text-editing contexts. The menus,
canvas, control channel, MCP key tool and Keyboard shortcuts panel all
resolve keys there; the catalog keeps only the menu tree.

- Fixed: Cmd/Ctrl+K made a link on the canvas (now Actions; link only
  while typing), Shift+1 and Ctrl+Shift+? never matched (key names are
  normalised), mask / bring to front / send to back / tidy up / layout
  grids on Windows and Linux, distribute on macOS, outlines (Shift+Cmd+O),
  pixel grid (Cmd+'), paint bucket B in vector edit mode.
- Added: Cmd/Ctrl+/, + and - zoom, Cmd/Ctrl+0, hold Z zoom tool
  (view.zoomAt), two quick digits for exact opacity (object.opacityKeys),
  Alt+Shift+U/S/I/E booleans, Alt+/ and Shift+/ remove fill/stroke, pixel
  preview, Shift+E / Shift+D / Shift+Cmd+\ panel keys, Ctrl+Tab between
  files (doc.nextTab / doc.previousTab), Shift+I, Shift+Space preview,
  Home/End frames, Ctrl+C pick colour on macOS.
- Keyboard shortcuts panel: docked at the bottom, a tab per group, search,
  keycaps per platform; tooltips show the platform's keys.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 18:15:16 +07:00
BFlatandClaude Opus 5.5 df2309f5b9 M1: measuring, scale tool handles and selection depth (#77)
Measuring (Alt/Option): distances from the selection to the hovered layer,
its parent (over the selection itself or empty space) and ruler guides;
Cmd+Alt for nested layers; containment both ways, overlaps between matching
edges, gaps with dashed extension lines; rotated layers and several selected
layers by their bounds; the measured box outlined. Alt while dragging shows
live distances to the neighbours (or the parent's edges); Shift+Alt reads out
an auto layout frame's padding and gaps. Labels are placed so they never
overlap each other or the size label and stay the same size at every zoom.
Commands: measure.distances, measure.padding.

Scale tool (K) canvas handles: one factor about the Scale panel's anchor
(tool.scaleAnchor, shared by the panel and the canvas; the opposite handle when
the anchor is on the side being dragged), Alt from the centre, flips past the
pivot, rotated layers and lines along their own axes, one undo step per drag,
a live factor in the size label and the pivot marked. scale_node now also
scales min/max sizes, layout grids, guides, fixed grid tracks, tiled images,
paragraph indent and run letter spacing.

Selection: Cmd/Ctrl-marquee selects nested layers, Shift-marquee toggles,
the context menu's Select layer lists every layer under the click
(select.layersAt), outlines are purple for every layer inside components and
instances, hover outlines show with the Scale tool too. Fixed marquees
selecting layers that only overlapped the marquee on one axis.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 14:04:17 +07:00
BFlatandClaude Opus 5.5 50517a6431 M7: comments polish (#74)
Pins follow their layers (to other pages too) and stay where they were
when the layer is deleted, re-pinned to the nearest surviving parent;
your pins drag onto another frame; crowded pins cluster when zoomed out
and a click zooms them apart; Shift+C shows or hides them.

Threads: edit and delete your own messages (marked edited), emoji
reactions, @mentions with a picker of the names used in the file (your
name from Preferences), read/unread state per name, and Copy link
(figcraft://comment/<id>; pasting it or comment.open goes to the page,
zooms to the frame and opens the thread).

Comments panel: search (text, names, frame), filters (open, resolved,
yours, unread), sort by date or page, each thread's frame and page,
Up/Down to step through threads. The presenter shows the presented
frame's comments (Comments button or Shift+C) to read and reply.

New commands: comment.react, comment.markRead, comment.open,
comment.next, comment.zoom, comment.link, comment.people,
pref.userName; comment.list gains filter/sort/query/frame, comment.move
re-pins. Old files load unchanged (the first message stays on the
comment; missing read state counts as read).

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 13:36:42 +07:00
BFlatandClaude Opus 5.5 6d7b30508b M1: 2x pixel preview (#68)
Pixel preview takes a resolution: `view.pixelPreview {scale: 1|2}` turns it on at 1x (one rendered
pixel per page pixel) or 2x (two, as on a high-density display); the canvas renders at that
resolution from a whole-pixel origin and magnifies it with hard edges once zoomed past it. The zoom
menu offers "Pixel preview 1x" and "2x" and now shows the on/off state of every view toggle.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 11:43:54 +07:00
BFlatandClaude Opus 5.5 476cdd95f1 M4: shape builder tool (Shift+M): merge or remove the regions of overlapping shapes (#39)
The selected shapes' outlines split the canvas into regions, computed as the faces of their
arrangement with linesweeper (curves kept, per-shape fill rules, holes and islands handled) and
cached per document version and selection.

- Engine: shapeBuilder.regions / merge / remove / mode commands, ToolId::ShapeBuilder and
  tool.shapeBuilder (catalog: Tools > Shape builder, Shift+M). Merge makes one vector from the
  picked regions styled like the top-most shape over the first; every shape covering a picked
  region loses that area (becomes a vector, or is deleted when nothing is left). One gesture or
  command is one undo step. Session::tool_key routes Enter (finish) and vector edit keys.
- Pathops: faces() (arrangement faces with their covering inputs) and union_faces().
- UI: region edges on the canvas, hovered/collected regions hatched (danger colour to remove),
  no transform box while building, a toolbar pill with Merge/Remove modes, a hint and Done; shared
  pill/tool-cell/divider/Done helpers; original merge/remove icons drawn in code.
- Tests: pathops faces; engine regions, merge, remove, curves, groups, rotation, pointer
  click/drag/Alt, modes, Escape/Enter, cache, junk parameters and degenerate geometry.
- Docs: ROADMAP, README, docs/mcp.md, docs/control-protocol.md, docs/parity.md.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 05:55:12 +07:00
BFlatandClaude Opus 5.5 360b6df206 M4: local libraries: publish, enable, place and apply, updates with overrides kept (#32)
- Publish (`library.publish {description?, include?, exclude?}`, Libraries > Publish library…):
  the file's components, component sets and styles (by default all but names starting with `.` or
  `_`, or what the last publish offered) and every component and style they use go into a snapshot
  with a manifest (library id, version, per-asset version stamps). An asset keeps the version it
  last changed in; publishing without changes is refused.
- .figcraft: `library/manifest.json`, `library/document.json` (the snapshot) and
  `library/images/<sha256>` for images only the library still uses. Older files and readers are
  unaffected (extra members); a damaged library is skipped and reported when the author's file
  opens. Files using a library read only these members (size-limited), never unpublished edits.
- Version history: the library entries are written and read alongside the versions (a library
  survives saving with versions and reopening); restoring a version keeps what the file published.
- Enable: `library.add {path}` / `library.remove {id}` / `library.list {assets?}`; the document
  keeps its enabled libraries (id, name, path, last seen version) in its data. The session caches
  each library file and reads it again when it changes on disk; in the browser these commands
  return a clear error (no file system).
- Use: `library.place {library, component, x?, y?}` / `library.import` copy the component (with
  the components and styles it uses) into a hidden library store (a page-like root outside the
  page list) as read-only main components and place an instance; instances behave like any other
  (overrides, properties, variants, swap, reset, detach). `library.applyStyle` copies a style in as
  a linked remote style. Editing the copies or library styles is refused; Go to main component
  names the library. Importing a file's pages brings its library copies along (shared with copies
  the document already has).
- Updates: `library.updates` and `library.acceptUpdates {ids?}` re-import changed copies in place
  (layer ids kept, so instance overrides survive, also when layers are added); unused copies are
  dropped when a library is removed or updated.
- Assets panel: each enabled library's components (thumbnails, search, click or drag to place,
  shared with the local tile code) and styles (click to apply, paint swatches), collapsible per
  library; "Library updates available" banner with Update; a libraries view (book button,
  Libraries menu) to publish this file (choose assets, description) and add or remove library
  files. Local styles in the panels list only this file's styles.
- Tests: manifest round trip and versions, add/place/update keeping overrides (incl. a structural
  update), variants/swap/undo, library styles and importing pages, missing/corrupt/truncated/
  oversized/never-published files; format tests for damaged and oversized members.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 05:24:46 +07:00
Brandon ThomasandClaude Opus 5.5 b36fd771ab M0.9: MCP server + figcraft-cli, PDF export, web app, release/CI packaging, vector edit mode, workspace lint cleanup
- crates/mcp: JSON-RPC MCP server (18 tools, resources, prompts), headless and attached backends, end-to-end agent tests
- apps/figcraft-cli: info/export/convert/render/run/commands/mcp/perf
- crates/pdf: vector PDF export via krilla with embedded text; file.exportFramesPdf
- apps/figcraft-web + packaging/{macos,windows,linux,freebsd,web} + release/ci workflows
- engine vectoredit: edit points/handles/bend/add/delete-heal; canvas overlay and edit strip

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 13:31:53 -04:00
Brandon ThomasandClaude Opus 5.5 56a312ba5f M0.5: layout (auto layout + constraints), format, svg, engine (commands, history, tools, components, styles, variables)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 12:40:18 -04:00