1.1.0 + 1.2.0: GUI hot-reload, when-block polish, walk-back of the unified chip - #37
Merged
Conversation
cushycush
force-pushed
the
gui-trigger-hot-reload
branch
from
May 9, 2026 06:11
3e54d2c to
f1731ab
Compare
Three fixes that landed together because they're all about the editor catching up with what the file says. The library hot-reload watcher only reloaded the open editor when this workflow's chord (or its when-condition) changed. Anything else, hand- edits to the .kdl, a save from the Library page, a chord rebind that also rewrote the file body, sat in the canvas as stale state until you flipped pages or reopened the workflow. The fix is to compare the file's mtime instead of the chord triple. store::list_with_mtimes walks workflows once and surfaces the .kdl mtime alongside each Workflow; library.rs adds a disk_mtime field to the QML summary; WorkflowPage adopts the first snapshot without reloading and only re-issues wfCtrl.load when the mtime changes against an idle saveState. Mid-save (saving / saved / dirty / error) we still adopt the new mtime so the post-save tail event from our own write doesn't re-render the canvas over what we just authored. Conditional cards now route their primary value through the same top-bar TextField every other step uses. Editing the window name (or file path, or env name) for a `when` block no longer requires opening the inspector's condition section, and the read-only "window=X, 1 yes / 1 else" string that used to overflow that pill is gone, the canvas already paints both branches as wires so the textual recap was duplicate noise. _mutateAction picks the right cond field by kind and preserves negate + env's optional `equals=` so a primary edit doesn't blow either away. Wire labels for the false branch read "else" instead of "no", which matches the data model (else_steps) and the user-facing language for the feature. Inspector's section heading flips from "FALSE BRANCH" to "ELSE BRANCH" for the same reason. The stale comment claiming the canvas didn't render else cards was already wrong, replaced with one that describes what's actually happening.
Two related polish passes on the conditional card.
Wire labels read "true" instead of "yes" so the canvas matches the
language people use about a when block ("this branch runs when the
condition is true / else this one"). Color stays green for the true
side and red for the else side so a glance at the wire still tells
you which path you're tracing. Internal _branchSide keys keep their
yes/no values so I didn't have to chase every callsite that branches
on them.
The conditional card now grows two stub buttons in its body: "+ true"
and "+ else", side by side, each opening the same step-kind menu the
inspector uses. Add an else step from the canvas without leaving the
canvas, mirroring the existing "+ inner step" affordance on repeat
containers. The inspector's else-branch list editor stays as the
authoritative long-form view, but discovery doesn't depend on it
anymore. Buttons render half-width so they read as peers, with the +
glyph tinted to match the wire color (Theme.ok for true, Theme.err
for else) so the visual identity carries over from the wire to the
button.
addElseStepRequested is a new canvas signal that hops through
_addElseStep on WorkflowPage, the same path the inspector already
uses, so the data model touches one code path regardless of where
the click came from.
The + (12px) and the "true"/"else" label (9px) hugged the top of the Row by default, so the glyph floated above the text instead of reading as a single chip. Same fix the open-import button already uses: anchor each Text's verticalCenter to the Row's. Row's height ends up driven by the larger glyph and the smaller label centers within it.
Today's "open a terminal, then type into it" takes three cards: Shell, WaitWindow, ActivateWindow. The footgun is title/class collision — five foot windows means the matcher silently lands on the wrong one. Workaround is --title=wflow-spawn, which trades one brittleness for another. Captured the design for a Spawn variant that runs the command, captures the PID, polls until a window with that PID maps, and exposes it as the focus target for following steps. Hyprland and Sway take pid: selectors directly; KWin needs kdotool; wdotool gains an await-window-pid primitive so the engine isn't doing per-compositor probing.
The rail's up/down arrows and the inspector's preceded-by / followed-by pickers all funnel into _moveStep, which was splicing into _stepsAtCrumb (the raw KDL step list) using indices from root.actions (the shaped list the canvas and rail render). Notes get filtered out of the shaped list and conditional inners get surfaced as siblings, so a shaped index can sit past the end of the raw list whenever the workflow has either. The bounds check caught the overrun and silently early-returned, which read as "the buttons just don't do anything." Translate shaped → raw via _topIdx before the splice, and reject moves whose endpoints aren't top-level (inner-conditional cards aren't reorderable through this path; they belong to a parent's steps / else_steps array, not the top-level sequence). Selection update stays in shaped space because the shaped list recomputes from the new workflow and the moved card lands at shaped index `to` regardless of how the raw indices shifted underneath it.
The unified-chip pass routed the canvas card hero through StepChip so the editor and the library would read as one product. Side by side they do, but the canvas needs the kind glyph more than the library does: you scan a 2D field of cards by silhouette, and a 12px category-color dot doesn't carry that work the way a 22px icon does. Swapped the canvas card hero and the drag-preview ghost back to GradientPill (36px pill, icon on the left, value on the right). Library cards keep StepChip — the trail-pill language was designed for those and the user actually likes that surface as it sits today. StepListRail and StepPalette are still on StepChip; the user didn't flag those, so I'm leaving the rail height + the toolbar 3-letter-code chips alone unless that comes up.
Same call as the canvas card: the palette wants the kind glyph as the primary identity, not a category dot plus an abbreviation. "clk" / "fcs" / "ntf" reads as cargo-cult brevity when there's plenty of room for the icon plus a hover-revealed label, which is how this rail looked before the unified-chip pass. Restored to its pre-share state: 56px collapsed / 200px expanded, CategoryIcon at 24px on the left, friendly label fading in on hover. The hover latch (held expanded across inter-chip gaps) goes with the StepChip shape and isn't needed here, the per-chip hover-fill is fast enough on its own.
Last surface on StepChip in the editor was the steps-list rail. Same reasoning as the canvas and the toolbar, the icon is the primary identity for navigating these rows. Restored to its pre-share form: 44px rows, status badge on the left (number collapses to ✓ / ✗ / · once a step has run), CategoryIcon at 22px beside it, two-line title + value stack to the right. The Row geometry that came with the chip layout (badge / chip / arrow column) goes with it. That's all three editor surfaces (canvas, palette, rail) walked back; the unified-chip primitive only carries the library trail pills now, which is the surface it was originally designed for.
cushycush
force-pushed
the
gui-trigger-hot-reload
branch
from
May 9, 2026 06:44
f1731ab to
e425a82
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two releases worth of work that accumulated on this branch while v1.0.3 sat on main. Easier to land them together than carve a separate v1.1.0 PR after the fact.
v1.1.0
Library and editor stay in sync with the workflows folder. The daemon already watched
~/.config/wflow/workflows/; the GUI loaded once at startup and went stale. EachLibraryControllernow starts its ownnotifywatcher, refreshes its summary on FS events, and the editor reloads when its open workflow's chord changes (only its chord, not every save in the library, so typing into one workflow doesn't force a rebuild of another tab's editor).Inline unbind on the editor's pinned trigger card. Previously the only way to clear an editor-bound chord was to click the card, wait for the chord-capture dialog, click "Clear binding" inside it. There's now a small × on the card itself with an "Unbind chord" tooltip.
A shared
StepChipprimitive routed the canvas card hero, step list rail, drag preview, and left toolbar through one chip language. Walked back in v1.2.0 (see below); library trail pills keep it.Two wire-routing fixes: row-wrap diagonals now exit source-bottom and enter target-top instead of looping back across the source row, and the marching-ants dash animation pauses while the canvas is panning or hidden so a stationary canvas costs nothing.
v1.2.0
Editor hot-reload for full workflow content. v1.1.0 wired the watcher in but the editor only reloaded on chord changes; hand-edits to the file body sat as stale state until you flipped pages.
WorkflowSummarynow carriesdisk_mtime(filesystem mtime, not the in-filemodifiedfield, which hand-edits don't bump on their own), the editor diffs that against its last-seen value, and reissueswfCtrl.loadwhen the file changed. FS events fired during mid-save states silently update the cached mtime so the post-save tail event from our own write doesn't re-render the canvas over what you just authored.Else branches show up on the canvas, not just in the inspector. Two side-by-side buttons on the conditional card body, + true and + else, each opening the same step-kind menu the inspector uses. Wire labels read true / else instead of yes / no; the inspector's section heading flips from FALSE BRANCH to ELSE BRANCH to match. The data model (
else_steps) was already there; the canvas catches up so you don't have to leave it to grow the branch.Conditional steps' primary value is editable from the top bar like every other step. Edit the window name, file path, or env name without opening the inspector's condition section. The redundant "1 yes / 1 else" tag that used to render in the value pill is gone since the canvas paints both branches as wires.
The rail's up/down arrows and the inspector's preceded-by / followed-by pickers were silently broken on any workflow with notes or conditionals.
_moveStepspliced into the raw KDL step list using indices from the shaped actions list, which can sit past the end of the raw list once notes are filtered or conditional inners expand as siblings. The bounds check caught the overrun and returned, which read as "the buttons just don't do anything." Now translates shaped to raw through_topIdxand rejects moves on inner-conditional cards.Walked back the unified
StepChipacross the editor. The chip language fits the library's trail pills; the editor reads better with the kind glyph carrying card identity at a glance. Reverted the canvas card hero, the drag-preview ghost, the toolbar (back to 56 / 200 icon-and-label rows, no three-letter codes), and the rail (back to 44px status badge + icon + title/value). Library trail pills keepStepChipsince that's the surface it was designed for.What's not in this PR
README.mdandexamples/dev-setup.kdlworking-tree edits aren't included; they were dirty before this branch and are personal customizations, not release content.examples/ship-prep.kdlis a new example I'm still iterating on.