Files
ausboss-ComfyUI-AusBoss/js/shared/core_preview.mjs
T
ausboss 5babcc7ed6 Keep a run's results on the workflow tab that queued it
Every workflow tab in a page shares one server connection, and ComfyUI
files a node's results by node id. A run from one tab that finished while
another tab was open landed on the open tab's node with the same id. On
Video Crop + Rotate + Pad -> Clip that was a second video under the
buttons that grew the node over the one below; Show Text and Seed also
saved the other workflow's text and seed into this one, and Save Video and
Compare replaced their own result.

- The three Crop + Rotate + Pad nodes stand down ComfyUI's image and video
  previews (they send no picture of their own), in both renderers.
- suppressCoreVideoPreview sets hideOutputImages, so Nodes 2.0 no longer
  draws Save Video's clip a second time under its player.
- shared/prompt_scope.mjs notes which graph queued each run (the queue
  call is wrapped for the prompt id). For a result from another tab, the
  AusBoss node here gets this tab's own stored result back, every pack
  onExecuted handler returns early, and the result is handed to the owner
  tab's AusBoss nodes when that tab is open again. Core nodes are left
  alone.

Tests: prompt_scope (scope rules plus a policy check that every
onExecuted handler asks isForeignRun first) and core_preview (every
transform kind suppresses both previews; video suppression sets
hideOutputImages) fail on main and pass here.
2026-09-29 15:53:03 -05:00

76 lines
2.9 KiB
JavaScript

// Stand ComfyUI's own in-node previews down on nodes that draw their own.
//
// A node that returns a ui payload — or streams progress previews — gets a
// preview from the frontend automatically: an image one as the canvas widget
// named $$canvas-image-preview, a video one as the DOM widget named
// video-preview. Every AusBoss node here already presents that same result
// inside its own panel, so left alone the node shows it twice, once in the
// panel and once again underneath.
//
// The widgets are hidden rather than removed. The frontend re-adds a preview
// whenever it finds none and the node has images, so removing one just brings
// it back on the next frame; a hidden widget is still found by name and left
// alone. Its value is untouched either way, and neither serializes.
export const CORE_VIDEO_PREVIEW_WIDGET = "video-preview";
export const CORE_IMAGE_PREVIEW_WIDGET = "$$canvas-image-preview";
export function hideCanvasWidget(widget, element = null) {
if (!widget || widget.__ausbossHidden) return;
widget.__ausbossHidden = true;
widget.hidden = true;
widget._hidden = true;
widget.computeSize = () => [0, -4];
widget.computeLayoutSize = () => ({ minWidth: 0, minHeight: 0 });
widget.draw = () => {};
widget.mouse = () => false;
if (element) element.style.display = "none";
}
// Wrap one of the node's own add*Widget methods so the named widget is hidden
// the moment the frontend creates it, and sweep any copy already present.
function suppressWidget(node, flag, method, targetName, elementOf) {
if (!node || node[flag]) return;
node[flag] = true;
const prior = node[method];
if (typeof prior === "function") {
node[method] = function (...args) {
const widget = prior.apply(this, args);
if (widget?.name === targetName || args[0] === targetName) {
hideCanvasWidget(widget, elementOf(widget, args));
}
return widget;
};
}
for (const widget of node.widgets || []) {
if (widget?.name === targetName) hideCanvasWidget(widget, elementOf(widget, []));
}
}
export function suppressCoreVideoPreview(node) {
// Nodes 2.0 has no video-preview widget to hide: it draws the node's
// output under the widgets itself unless the node sets this flag (the
// classic renderer never reads it). Without it Save Video showed its clip
// twice there, once in the panel and once underneath.
if (node) node.hideOutputImages = true;
suppressWidget(
node,
"__ausbossCorePreviewSuppressed",
"addDOMWidget",
CORE_VIDEO_PREVIEW_WIDGET,
(widget, args) => args[2] || widget?.element || node.videoContainer,
);
}
export function suppressCoreImagePreview(node) {
// The image preview arrives through addCustomWidget, not addDOMWidget: it
// is painted straight onto the graph canvas and owns no element.
suppressWidget(
node,
"__ausbossCoreImagePreviewSuppressed",
"addCustomWidget",
CORE_IMAGE_PREVIEW_WIDGET,
() => null,
);
}