Player: Save to bin (whatever the viewer shows, if it has a real file
identity) and Save frame (canvas-capture the video on screen, upload
through ComfyUI's own /upload/image, no new route needed). Both add
without navigating the viewer -- an upload is a real round trip, and
the result is added to the bin, not shown as a stale finished pick.
Save/Load Project File: a real download route with Content-Disposition,
and an import route that never trusts an id in the file -- an import
always lands as its own project, never overwrites one already here.
Generate All: every scene in order, waiting for each to finish before
starting the next -- not a montage (v5 has no render/stitch stage),
N separate generations each landing on its own scene.
Both project-switching (open/newProject/importProject) and the earlier
run-reattach path shared a bug class this session kept finding: state
captured at one moment, applied at a later async moment with no check
that nothing had moved on in between. Closed it properly this time --
a generation counter every switch bumps and checks, including start()
(the page's own handlers are live before it resolves) and undo/redo
(also "a different project is open now"), and scheduleSave() captures
the object an edit actually touched instead of re-reading a variable
that can point somewhere else by the time its debounce timer fires.
Four adversarial rounds against this range, each fixed before landing.
v4's arrangement, which is the one that reads as an editor: a zone head
holds what acts on THAT zone, so the app grows a bar of its own for what
acts on the app.
* The menu bar. Brand, View and Settings, and whether ComfyUI is still on
the other end. Only menus with something real in them exist -- an empty
File menu is a promise the app does not keep.
* The prompt is written in the CONSTRUCTOR, a window. v4 called this the
Composer; that name is taken here by the element kit, and two things
called Composer in one repo is one thing nobody can search for. It is
the longest thing a person writes and the least often read, and a
permanent third of the centre column is the room the timeline needs.
The host is built at startup and outlives every opening, so a window
that opens twice does not throw away what was typed.
* The timeline replaces it, and Generate moves into its head with what
the run is doing at the far end of the same head. No bar across the
bottom: one that spans the window belongs to no region.
Four faults found on the way, three of them mine and one much older:
* THE OVERLAY ROOT WAS A STACKING CONTEXT. It documents at length that it
must never be one -- and then set `position: fixed`, which makes one on
its own. So the whole z ladder was measured inside that single element:
an open menu at z 500 painted UNDER a button at z 1. Every overlay in
the app was one positive z-index away from being buried, and the only
reason nobody had seen it is that almost nothing claims a z-index. The
root is static and zero-sized now; every layer in it is fixed already.
* Generate's hover ran `filter: brightness()`, which lightens the LABEL
along with the fill under it -- the one thing that had to stay readable
lost contrast in both themes. Only the fill moves now, and which way it
moves depends on the theme: dark's accent carries near-black text so it
goes lighter, light's carries white so it goes darker. Measured: no
gradient stop under 4.1:1, hovered or at rest.
* A fixed-height head could not shrink below the width of everything in
it, and a head now holds a title, three controls and a status. That
min-content became the centre column's, so a 768px window laid out
878px wide and scrolled sideways. It wraps now, as v4's does.
* A CSS patch of mine silently did nothing because its anchor text had
moved and I had left the assertion off that one replacement. Every
patch asserts now.
A second run replaced the first on screen with no way back. Results now
accumulate in the Assets panel across runs, and the bin owns what the
viewer shows: the session subscription drove the viewer as well, so every
progress message walked a click on an older result back to the newest.
Grid, list and icons are one collection in three shapes, sharing selection
so switching view is not a way to lose it. No <video> thumbnails, ever --
that is v4's connection-pool stall. A thumbnail that does not arrive falls
back to the glyph rather than the browser's broken-image icon.