Load Image listed its internal $$canvas-image-preview widget as a row in
the Inspector and the pop-out.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Run ids name other nodes in another workflow tab. The run state now says
whether the tab on screen is the one that ran, and is sent again with the
info a tab switch changes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The frontend wraps canvas.onDrawForeground again whenever its DOM widgets
mount, and the wrapper calls the highlighter's hook, which then called the
wrapper. The hook now keeps every function it replaced and goes one level
down per call, so each runs once.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Encoding each frame to PNG and posting it over the channel lagged the glass
and capped it at 30 fps. The viewer is a same-origin popup, so the glass now
draws each rendered frame into it in the same animation frame. The viewer
hands its window back through opener.postMessage after a ComfyUI reload.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Listen for the viewer once ComfyUI is set up, so a viewer left open over a reload connects fully
- A duplicated tab starts its own session instead of sharing the viewer
- Ignore requests from a viewer that is not connected
- Stop the render loop while the glass is hidden and the viewer shows no frames
- Do not place the panel again on the 250 ms refresh
- Build output URLs from filename, subfolder and type only
- Viewer: skip undecodable frames, tolerate showPicker and blocked storage, keep the channel open on unload, shorten "Go to node…"
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Each slot lists the nodes it links to as chips that jump to them, and flags
required inputs with nothing connected. Links to a subgraph's own input or
output show as plain chips.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The shown node's live previews or last results appear as thumbnails under the
header, and the Output view shows one in place of the frame.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Forward ComfyUI's execution events as a throttled run message while the
viewer is connected: a run bar, node badges, an error banner and marked rows.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The pop-out can set the glass zoom, switch between Split, Glass and Info,
and resize the Inspector by dragging or with the arrow keys; the layout is kept per browser.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add the Inspector's header, nav row, breadcrumb and searchable node picker,
run panel actions through UIManager.runAction, and bring the editors, copy
buttons and viewer keys in line with the Inspector.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Send a snapshot of the palette tokens instead of a theme name, and draw the
viewer flat like the Inspector with SVG icons, switches and a stacked layout.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Frames are encoded with toBlob one at a time, stale decodes are dropped,
and fit and fullscreen use object-fit: contain so they no longer crop.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
InfoPanel builds the payload, applies the Inspector's edit guards and refreshes
the viewer on a 250 ms tick while connected, also when the glass is off.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Each ComfyUI tab talks to its viewer on a session channel. Pings run only while
connected, status follows pings, and a hidden glass keeps feeding the viewer.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Resolve the viewer from import.meta.url, open it as a popup window, and
render data:image values and node ids without raw HTML or inline handlers.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Paint Vue nodes under the glass from the DOM, since the canvas capture
has none of them.
- Resolve the Inspector's hovered node from the Vue node element under
the cursor, falling back to the canvas hit test in pan mode.
- Fit the node highlight to collapsed nodes in both modes.
- Draw Node Title Emphasis on the title bar instead of the first slot
row, and skip nodes without a title bar such as Reroute.
- Fill the glass with the page background so it is not half-empty at
the canvas edge or wrong at zoom 1.5 and above.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Restyle the panel on ComfyUI palette tokens and drop the built-in themes.
Add a header with Back/Forward, Prev/Next, Focus, Lock and a searchable
Go to node picker, a subgraph/group breadcrumb, and simplified modes:
Follow glass or Float, plus Sticky, Follow selection and Lock to node
(replaces Hold).
Fix widget edits (step2 steps, INT/FLOAT, commit on Enter/blur, undo),
subgraph lookups, orphaned dropdown menus, global arrow-key capture,
the pop-out editor, and remove Google Fonts loading and dead code.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Make the sidebar tab wrapper fill the panel, and let the content keep its
natural height when the parent has none, so the settings no longer collapse
to a 16px scroller.
- Only measure DOM images and videos under the glass, so per-frame work scales
with what is under the glass instead of all media on the page.
- Cap Virtual Zoom near 60 fps again, so high-refresh displays do not run two
full graph draws every frame.
- Cull nodes with LiteGraph's boundingRect and keep collapsed nodes, so title
bars and collapsed nodes in front of a preview stay on top in the glass.
- Drop the self-min on the title width and the dead pos/size guards.
- Remove the stale web/shared/settings.js build output.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Updated `sanitizeElement` to strictly remove whitespace and control characters from URI attributes before validation.
This prevents bypasses like `java\tscript:` in `href`, `src`, `action`, and `formaction` attributes.
Added comprehensive unit tests covering these bypass vectors.
Co-authored-by: AEmotionStudio <163354043+AEmotionStudio@users.noreply.github.com>
Added `sanitizeElement` utility to recursively remove inline event handlers (on*) and javascript: URIs from HTML elements.
Applied sanitization in `MagnifyGlass.renderHtmlOverlays` when cloning nodes for the magnifying glass view.
Added unit tests to verify sanitization logic.
Co-authored-by: AEmotionStudio <163354043+AEmotionStudio@users.noreply.github.com>
- Replaced read-only hex code span with an editable text input in `createColorPicker`
- Implemented bidirectional sync between text input and color picker
- Added validation for hex codes and auto-correction on change/blur
- Ensured keydown propagation is stopped to prevent triggering global shortcuts
- Added aria-label for accessibility
- Updated unit tests to verify sync logic and event handling
- Added CSS styles for `magnify-color-preview` input to match UI design
- Ran build script to update `web/` artifacts
Co-authored-by: AEmotionStudio <163354043+AEmotionStudio@users.noreply.github.com>
Added `sanitizeElement` utility to recursively remove inline event handlers (on*) from HTML elements.
Applied sanitization in `MagnifyGlass.renderHtmlOverlays` when cloning nodes for the magnifying glass view.
Added unit tests to verify sanitization logic.
Co-authored-by: AEmotionStudio <163354043+AEmotionStudio@users.noreply.github.com>
Re-verified tests after checking PR comments.
Optimized node rendering by caching visible nodes.
Reduced redundant iterations over `app.graph._nodes` in `OffscreenRenderer`.
Implemented `getVisibleNodes` to calculate visible nodes once per frame (O(N)) and reused this list for text, title, and image preview rendering passes (O(M)).
This improves performance for large graphs by replacing multiple O(N) traversals with a single O(N) traversal followed by O(M) traversals where M << N.
Added unit tests in `tests/unit/OffscreenRenderer.test.ts` to verify node visibility culling logic.
Updated `.jules/bolt.md` with performance learnings.
Co-authored-by: AEmotionStudio <163354043+AEmotionStudio@users.noreply.github.com>
- Replaced read-only hex code span with an editable text input in `createColorPicker`
- Implemented bidirectional sync between text input and color picker
- Added validation for hex codes and auto-correction on change/blur
- Ensured keydown propagation is stopped to prevent triggering global shortcuts
- Added aria-label for accessibility
- Updated unit tests to verify sync logic and event handling
- Added CSS styles for `magnify-color-preview` input to match UI design
Co-authored-by: AEmotionStudio <163354043+AEmotionStudio@users.noreply.github.com>
Reduced redundant iterations over `app.graph._nodes` in `OffscreenRenderer`.
Implemented `getVisibleNodes` to calculate visible nodes once per frame (O(N)) and reused this list for text, title, and image preview rendering passes (O(M)).
This improves performance for large graphs by replacing multiple O(N) traversals with a single O(N) traversal followed by O(M) traversals where M << N.
Added unit tests in `tests/unit/OffscreenRenderer.test.ts` to verify node visibility culling logic.
Updated `.jules/bolt.md` with performance learnings.
Co-authored-by: AEmotionStudio <163354043+AEmotionStudio@users.noreply.github.com>
- Replaced read-only hex code span with an editable text input in `createColorPicker`
- Implemented bidirectional sync between text input and color picker
- Added validation for hex codes and auto-correction on blur
- Ensured keydown propagation is stopped to prevent triggering global shortcuts
- Added aria-label for accessibility
- Updated unit tests to verify sync logic and event handling
- Added CSS styles for `magnify-color-preview` input to match UI design
Co-authored-by: AEmotionStudio <163354043+AEmotionStudio@users.noreply.github.com>