Commit Graph
5 Commits
Author SHA1 Message Date
BFlatandClaude Opus 5.5 4d7a9187ff M9: live sessions: host from the app, invite links, live cursors and presence (#104)
* M9: real-time collaboration protocol (design)

docs/collab-protocol.md: WebSocket sessions with a server-ordered,
per-property last-writer-wins document sync, client-scoped ids,
fractional positions for children, ephemeral presence (cursors,
selections, follow), per-user undo, hosting from the app first and a
self-hosted server next, and the implementation plan. ROADMAP gains M9.

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

* M9: collaboration core: ids, change sets, server ordering, convergence

Step 1 of docs/collab-protocol.md, no networking:

- Client-scoped node ids: Document::set_client_id makes alloc_id hand out
  client << 32 | counter; single-user files allocate as before; the id
  counter is no longer part of document equality.
- crates/collab (layer 2): the synced object/property model (every saved
  Node field, plus document-level styles, comments, variables, images,
  dev snapshots, library data), Change batches, an O(changed) diff, strict
  and lenient apply, fractional sibling positions, snapshots.
- Server (ordering, validation, rejects with fixes) and Client (optimistic
  view, replay under remote batches, author-side repair of derived data)
  as pure state machines; binary (version byte + postcard, JSON values) and
  JSON message forms, fuzzed decoders.
- Engine: normalize as the recompute hook, collab.diff.
- Tests: round trips over random real commands, an N-client convergence
  fuzz test over delayed in-order links, junk batches.

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

* M9: fmt after merge

* M9: live sessions: host from the app, invite links, live cursors and presence

Step 2 of docs/collab-protocol.md, networking and presence half:

- crates/collab-net (layer 6): WebSocket transport (sync tungstenite, a
  reader and a writer thread per connection, no async runtime), the
  session host the app embeds (runs figcraft_collab::Server as the
  authority, carries its messages), invite links, presence throttling
  (~30 Hz, latest wins), limits (sockets, hello/idle timeouts, message
  size, rate, slow clients), keep-alive, clean close, reconnect with
  backoff; a browser stand-in until the web-sys client (step 4).
- engine: live session state (status, peers, presence, follow) and the
  collab.host/stop/join/leave/peers/follow/cursor commands; the network
  is reached only through the LiveLink the app installs.
- ui-egui: remote cursors (pointer drawn in code, name tag, gliding),
  selection outlines (once documents sync), avatars in the right panel
  with follow, the Share popover (start, invite link + URL with Copy,
  stop), File > Join live session.
- desktop app and MCP headless session install the link; xtask layers
  keeps networking crates out of L0-L5.
- Documents don't sync between apps yet (follow-up).

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

* M9: live sessions: document sync between apps

- The host's session runs figcraft_collab::Server seeded with the shared
  document; every app (the host's too, through the hub without a socket)
  is a collab Client. Guests open the host's file from the welcome as a
  new tab; leaving keeps it as a local copy.
- Engine: after each local action (a gesture once it ends; nothing during
  version or text previews) the session document is diffed into one
  Changes batch; server batches go through Client::receive with
  EngineRecompute and are installed with Session::apply_remote, which
  never touches the undo history. Batches arriving mid-gesture wait.
- Transport: Changes/Reject/Welcome reach the engine as Event::Sync;
  LiveLink::send carries batches in order; hellos are limited to 64 KiB,
  joined clients to the core's message size.
- Tests: engine sync against a real Server (ids in the client's space,
  one batch per gesture, remote edits skip undo, deferral, closing the
  file leaves), three apps over loopback converging (create, move,
  recolour, delete, rename) and a late joiner getting the server's state.
- Docs: collab-protocol, mcp, README, roadmap docs; the UI's
  "cursors only" note is gone, replaced by the per-person undo caveat.

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 02:40:59 +07:00
BFlatandClaude Opus 5.5 fe550fc14a M6: PDF print options (bleed, marks, CMYK) (#92)
PDF export gains print options, saved on PDF export settings and taken
by file.export, file.exportLayers, file.exportFramesPdf, export.add /
export.update, figcraft-cli export and the MCP export tool:

- a bleed (points or a length like 3mm / 0.125in, up to 2 in) that grows
  each page and shows what lies past the frame: its fills reach out to
  the bleed edge and its children are clipped there instead; a print
  page of one frame is trimmed to the frame's box;
- crop and bleed marks: 0.25 pt hairlines outside the bleed in
  registration colour;
- MediaBox / BleedBox / TrimBox;
- CMYK colour: fills, strokes, text, gradient stops, images and
  rasterised effects converted from sRGB with the naive, deterministic
  K = 1 - max(R, G, B) formula; DeviceCMYK without an output intent (no
  CMYK ICC profile can ship in the repository), soft masks stay RGB.

The Design panel shows a PDF row's print settings as a summary line that
opens them; the Export dialog has print options for its PDF preset.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 20:50:29 +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 d0a21d2a7b M6: REST import of prototypes and variables; export panel polish (#42)
* M6: REST import of prototypes and variables; export panel polish

REST API file JSON import now brings prototyping and variables along:
- interactions: on click/hover/press/drag, after delay, mouse enter/leave/down/up and key
  triggers; navigate, open/swap/close overlay, back, scroll to, change to, open link and set
  variable actions (lone unconditional blocks inlined); dissolve, smart animate, move, push and
  slide transitions with easing incl. custom bezier and spring; the legacy transitionNodeID
- flow starting points (and the deprecated start node), overflowDirection, scrollBehavior,
  prototypeDevice and prototype background
- the local variables response (collections, modes with the default first, values, aliases,
  scopes), passed as `variables` to file.open / file.import (object, JSON text or path), found
  next to the file (<name>.variables.json / variables.json) or embedded; boundVariables, paint
  and text style bindings and explicitVariableModes map onto the fields variable.bind uses
- file.import appends variables, flows and prototype settings with the pages
- unsupported parts (video, gamepad, conditionals, variable modes, library variables) warn

Export panel: rows with a typed or preset size (2x, 512w, 512h), suffix and all five formats
through the new export.update command; export.add steps up (1x, 2x @2x, ...); a preview;
"Export N layers" through the new file.exportLayers (one file per setting, unique safe names)
in the panel and the Export dialog; file.export takes `size`. MCP open_file/export pass the new
params.

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

* M6: Inspect tab: properties with styles and variables, redlines on hover (#41)

The Inspect tab lists the selected layer's properties for handoff:
layout (size, position from the parent, rotation, opacity, radius), auto
layout (direction, gap, padding, alignment), typography, fills, strokes
and effects, each with the style or variable it comes from. Clicking a
value copies it. With the Inspect tab open, hovering measures distances
from the selection without holding Alt.

New command inspect.properties returns the same groups for agents.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 06:17:54 +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