Commit graph

4 commits

Author SHA1 Message Date
7aeeae717f feat(editor): wires carry their type — animated flow + canvas depth
A 2026-feel pass on the visual language. Three structural
moves that change how the editor reads at a glance.

1. Wires now carry the colour of the data they transport.

   Every edge leaving the inputs endpoint takes the
   declared input's type accent — blue for text, orange
   for bytes, purple for json, green for file, amber for
   number. The operator can trace "this is the document
   path, this is the prompt" by following colour, no
   labels needed. Edges leaving step outputs stay neutral
   (we don't have module manifests to look up the output
   type yet — once the hub exposes them, this lookup
   grows).

   Hover / selection still wins the colour treatment so
   the "I'm pointing at this one" signal isn't lost in
   the type palette.

2. Edges entering a currently-running step animate.

   New AnimationController on the canvas loops a 0..1
   phase at 1.5 s when ANY step is running, stopped
   otherwise (no idle cost). EdgePainter takes the phase
   and renders animated edges as marching dashes in the
   wire's accent colour over a 35%-alpha base — the
   operator literally sees data moving along the wire in
   the direction of flow while a step executes. When the
   step completes, the animation stops, the wire returns
   to a static stroke. Run a flow with a slow step and
   the canvas comes alive.

3. Canvas gets depth.

   - Background is now a subtle top-left → bottom-right
     gradient between surfaceContainer and surface,
     giving the working area a "lit centre, recessed
     corners" cue instead of one flat dark page.
   - Node cards swap their Material widget for an
     AnimatedContainer with two-layer shadows: a sharp
     short-blur shadow gives the card a real footprint,
     a soft long-blur shadow casts depth onto the canvas
     behind. Selected nodes get a third accent-coloured
     halo so selection state reads from across the canvas.
   - 180 ms ease-out-cubic transitions on the
     AnimatedContainer mean hover-into-select and
     run-status-changes morph smoothly instead of
     snapping.

Edge stroke widths bumped slightly (2.1 / 2.8 from 2.0 /
2.6) so the typed wires read at a confident weight against
the new gradient backdrop.

Version 0.6.0 -> 0.7.0 — visible visual language change.

Signed-off-by: flemming-it <sf@flemming.it>
2026-06-01 17:45:27 +02:00
5c59f3a554 fix(editor): draft line reaches cursor + ports react on hover
Two operator-visible fixes from the 0.5.2 review:

(1) Draft line stopped short of the cursor. EdgePainter
shortens every segment endpoint by portRadius to dock at
port-dot perimeters — but the DRAFT segment's `to` is the
cursor itself, not a port. Result: while dragging a
connection, the live line ended 6 px short of where the
operator's mouse actually was. Felt like the cable
wouldn't reach.

EdgeSegment gains `shortenFrom` / `shortenTo` flags
(default true). The draft segment passes `shortenTo:
false`, so the line tip tracks the cursor exactly. From-
side stays shortened because the FROM is still a real
port dot.

(2) Ports had no hover affordance — mouse-over was
invisible. Operators couldn't tell ahead of time that a
port was interactive.

Adds `_hoveredPort` state on the canvas, updated via the
existing MouseRegion's onEnter / onExit. Port dot now has
three focus levels:

  resting → 12 px, 1.8 px border, no glow
  hover   → 15 px, 2.2 px border, soft accent glow
  drop-target (drag is over it) → 18 px, 2.5 px border,
            stronger glow

The hover state pre-shadows the drop-target state —
operators see "yes, this port is grabbable / droppable"
before they commit to dragging. When the drag does start,
the drop-target halo is the same family of treatment,
just stronger, so the visual progression reads as one
continuous interaction.

Signed-off-by: flemming-it <sf@flemming.it>
2026-06-01 17:13:14 +02:00
9afb51a4b5 fix(editor): port docks elegantly — line terminates at perimeter
Stefan's "the connections to the round ports look
unelegant" feedback was about three concrete things:

(1) The bezier endpoint sat at the port dot's GEOMETRIC
CENTRE. The dot was rendered ON TOP, so the line visually
disappeared into the centre of the dot — looked like a
thread being eaten by a bead.

(2) A separate arrow-head triangle was drawn on top of the
dot, doubling the visual terminator and making the
endpoint look "noisy".

(3) The dots were hollow rings the same colour as the
line, so the boundary between line and dot blurred
visually. They didn't read as connectors.

Fix:

 - EdgeSegment now carries `fromSide` + `toSide`
   (left / right) so the painter knows which way to
   shorten each endpoint. The bezier ends `portRadius` px
   short of the centre — exactly on the dot's outer
   perimeter, on the side facing the line. The line now
   "docks" cleanly at the rim.

 - The end-cap triangle arrow is gone. The dot itself is
   the visual terminator; an arrow on top was redundant.

 - Port dot redesigned as a connector-socket: outer ring
   defines the footprint, inner 4-px surface-coloured pin
   appears when connected. The result reads as "an active
   socket with a plug seated in it" rather than "a hollow
   circle next to a card edge". Empty ports stay surface-
   filled rings — unambiguous empty-slot signal.

 - Bezier handle length floor raised from 40 to 60 px so
   vertical detours (e.g. inputs-endpoint → step far below)
   curve gracefully out of the start before dropping
   instead of kinking near the origin.

 - Stroke width nudged from 1.8 to 2.0 px for the normal
   accent so the line carries the right visual weight
   against the new docked-at-perimeter port treatment.

Visual: lines now look like cables seated into sockets,
not strings vanishing under beads.

Signed-off-by: flemming-it <sf@flemming.it>
2026-06-01 17:03:01 +02:00
870cbc29f7 feat(editor): three-tab WYSIWYG editor — graph / text / run
Full rewrite of the editor surface, layered on top of the
FlowGraph foundation. One in-memory flow drives three tabs
that the operator can flip between freely:

 - Graph: a drag-and-drop canvas. Nodes are step cards with
   port dots on their left (one per `with:` field) and a
   combined output port on the right. Pinned inputs and
   outputs pseudo-nodes sit at the left and right edges so
   every flow has a visually obvious source and sink. Pan +
   zoom via InteractiveViewer; drag a node by its body to
   reposition it (positions persisted to a sidecar JSON file
   under ~/.fai/data/flows/.layout/<name>.json — kept OUT of
   the YAML so `fai run` stays byte-stable).
 - Text: the existing YAML CodeField with expands:true so
   line 1 anchors at the top edge. YAML-aware syntax
   highlighting picks up the theme's primary / secondary /
   tertiary palette for keys / strings / numbers.
 - Run: an inputs form (text fields + file-pick), a Start
   button that calls the host's FlowRunDriver, a live step
   list driven by the driver's event stream (matches the
   `fai run` CLI rendering — ◻ pending, · running, ✔ done +
   duration, ✗ failed, ⏸ awaiting approval), and the typed
   outputs once the run resolves.

Source of truth = the YAML text. Graph edits emit fresh YAML
into the shared CodeController; text edits re-parse the
graph on a 350 ms debounce. Layout sidecar persists drag
positions only.

New public API (lib/fai_studio_flow_editor.dart):

  FlowEditorPage(
    initialFlowName: ...,
    locale: ...,
    runDriver: FlowRunDriver?,        // NEW — host bridge
    availableCapabilities: List<String>, // NEW — for the
                                          // capability picker
                                          // dialog when adding
                                          // a step
  )

The host (Studio) implements FlowRunDriver to bridge the
hub's gRPC SDK into the editor's event vocabulary. The
StepStarted/Completed/Failed/AwaitingApproval events are
shared verbatim with the CLI's run_progress renderer so
both surfaces speak the same visual language.

Files in this commit:
 - lib/src/editor_controller.dart       — shared state +
   debounced reparse loop
 - lib/src/run_driver.dart              — host bridge
   interface + event types
 - lib/src/widgets/flow_canvas.dart     — pan / zoom / drag /
   port-to-port connection drawing
 - lib/src/widgets/flow_node.dart       — node card primitive
   (module / approval / inputs / outputs variants)
 - lib/src/widgets/edge_painter.dart    — single CustomPainter
   for every edge + draft drag line, cubic bezier with
   arrow-head caps
 - lib/src/widgets/properties_panel.dart — right-side editor
   when a step is selected (rename id, change capability, add
   / remove / rename with-fields, delete step)
 - lib/src/widgets/capability_picker.dart — searchable list
   dialog used by Add-step
 - lib/src/widgets/run_tab.dart         — inputs form +
   live step progress + outputs renderer
 - lib/src/flow_editor_page.dart        — host scaffolding,
   toolbar, file list, three-tab body, keyboard shortcuts
 - lib/src/l10n.dart                    — EN + DE strings for
   every new label
 - lib/fai_studio_flow_editor.dart      — exports the new
   public types (FlowRunDriver, FlowRunEvent variants,
   FlowOutputValue variants)

flutter analyze: 0 issues. flutter test: 7/7 green.

Signed-off-by: flemming-it <sf@flemming.it>
2026-06-01 00:48:35 +02:00