Moving from a node to the panel crossed empty canvas or other nodes and changed what it showed, so Lock and the editors were out of reach without Sticky. Hover now holds the node while the pointer heads for the panel, until it rests, and only reads the canvas, DOM widgets and Vue nodes, so the sidebar no longer exposes nodes behind it. With Follow Cursor the glass holds still on the way. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
491 lines
21 KiB
JavaScript
491 lines
21 KiB
JavaScript
var __defProp = Object.defineProperty;
|
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
import { Logger } from "../shared/logger.js";
|
|
import { StateManager } from "./StateManager.js";
|
|
import { UIManager } from "./UIManager.js";
|
|
import { PositionManager } from "./PositionManager.js";
|
|
import { EventManager } from "./EventManager.js";
|
|
import { InformationGatherer } from "./InformationGatherer.js";
|
|
import { CanvasHighlighter } from "./CanvasHighlighter.js";
|
|
import { getSlotLinks, getImportantNodeParameters } from "./NodeDataExtractor.js";
|
|
import { WidgetSyncManager } from "./widget-editors/WidgetSyncManager.js";
|
|
const AIM_REST_MS = 300;
|
|
function rayHitsRect(x, y, dx, dy, rect, margin = 12) {
|
|
let near = 0;
|
|
let far = Infinity;
|
|
for (const [origin, step, low, high] of [[x, dx, rect.left - margin, rect.right + margin], [y, dy, rect.top - margin, rect.bottom + margin]]) {
|
|
if (step === 0) {
|
|
if (origin < low || origin > high) return false;
|
|
continue;
|
|
}
|
|
const a = (low - origin) / step;
|
|
const b = (high - origin) / step;
|
|
near = Math.max(near, Math.min(a, b));
|
|
far = Math.min(far, Math.max(a, b));
|
|
}
|
|
return near <= far;
|
|
}
|
|
class InfoPanel {
|
|
constructor(magnifyGlass) {
|
|
__publicField(this, "magnifyGlass");
|
|
__publicField(this, "stateManager");
|
|
__publicField(this, "uiManager");
|
|
__publicField(this, "positionManager");
|
|
__publicField(this, "eventManager");
|
|
__publicField(this, "informationGatherer");
|
|
__publicField(this, "canvasHighlighter");
|
|
__publicField(this, "originalUpdateMagnifiedView");
|
|
__publicField(this, "originalShow");
|
|
__publicField(this, "originalHide");
|
|
__publicField(this, "originalPositionGlass");
|
|
__publicField(this, "updateFrameId", null);
|
|
__publicField(this, "boundScheduleSelectionUpdate");
|
|
// Refreshes the pop-out while it is connected, since it gets no input of its own here
|
|
__publicField(this, "popOutTimer", null);
|
|
// What the pop-out was last sent from, null to send the next update whatever it holds
|
|
__publicField(this, "popOutKey", null);
|
|
// The node the pop-out shows and the graph it came from; its edits apply only there
|
|
__publicField(this, "popOutNodeId", null);
|
|
__publicField(this, "popOutGraph", null);
|
|
// The results the pop-out's /view URLs were built from; each build gets a new rand param, which loads every image again
|
|
__publicField(this, "popOutImages", null);
|
|
__publicField(this, "popOutImageUrls", []);
|
|
// The hovered node, kept while the pointer is over other UI or heads for the panel
|
|
__publicField(this, "hoverNodeId", null);
|
|
__publicField(this, "hoverGraph", null);
|
|
// Where the pointer last was over that node, where it is and when it last moved
|
|
__publicField(this, "hoverAnchor", null);
|
|
__publicField(this, "pointer", { x: 0, y: 0, movedAt: 0 });
|
|
__publicField(this, "aiming", false);
|
|
__publicField(this, "aimTimer", null);
|
|
// The node Sticky keeps, looked up again on each update like the locked one
|
|
__publicField(this, "stickyNodeId", null);
|
|
__publicField(this, "stickyGraph", null);
|
|
this.magnifyGlass = magnifyGlass;
|
|
this.stateManager = new StateManager();
|
|
this.uiManager = new UIManager(this.stateManager);
|
|
this.informationGatherer = new InformationGatherer();
|
|
this.canvasHighlighter = new CanvasHighlighter(this.stateManager.state.settings);
|
|
this.positionManager = new PositionManager(this.stateManager, this.uiManager.elements.panel);
|
|
this.eventManager = new EventManager(this.stateManager, this.uiManager.elements.panel, {
|
|
toggleVisibility: () => {
|
|
if (this.stateManager.state.isPanelVisible) {
|
|
this.uiManager.hide();
|
|
} else {
|
|
this.uiManager.show();
|
|
}
|
|
},
|
|
toggleFloat: () => this.uiManager.toggleFloating(),
|
|
toggleSticky: () => this.uiManager.setPersist(!this.stateManager.state.settings["🔍MagnifyGlass.InfoPanelPersist"]),
|
|
updateLayout: () => {
|
|
this.uiManager.applyStyles();
|
|
this.uiManager.updateControlStates();
|
|
this.positionManager.positionPanel();
|
|
this.positionManager.positionFloatingControls(this.uiManager.elements.controls);
|
|
},
|
|
isGlassActive: () => this.magnifyGlass.state.active
|
|
});
|
|
this.boundScheduleSelectionUpdate = () => {
|
|
if (this.magnifyGlass.state.active && this.stateManager.state.settings["🔍MagnifyGlass.InfoPanelFollowSelection"]) {
|
|
this.scheduleInfoUpdate();
|
|
}
|
|
};
|
|
document.addEventListener("pointerup", this.boundScheduleSelectionUpdate, true);
|
|
document.addEventListener("keyup", this.boundScheduleSelectionUpdate, true);
|
|
this.originalUpdateMagnifiedView = magnifyGlass.updateMagnifiedView;
|
|
this.originalShow = magnifyGlass.ui.show;
|
|
this.originalHide = magnifyGlass.ui.hide;
|
|
this.originalPositionGlass = magnifyGlass.ui.positionGlass;
|
|
this.hookIntoMagnifyGlass();
|
|
const popOut = this.magnifyGlass.popOutManager;
|
|
if (popOut) {
|
|
popOut.onStateChange = (isOpen) => {
|
|
this.uiManager.updateControlStates();
|
|
this.setPopOutRefresh(isOpen);
|
|
};
|
|
popOut.onNodeSelect = (nodeId) => {
|
|
this.uiManager.jumpToNode(nodeId);
|
|
};
|
|
popOut.onWidgetEdit = (data) => {
|
|
var _a;
|
|
if (this.uiManager.canEdit() && ((_a = this.popOutRow(data)) == null ? void 0 : _a.isEditable)) {
|
|
WidgetSyncManager.syncWidgetValue(data.nodeId, data.widgetName, data.value);
|
|
}
|
|
this.refreshPopOut();
|
|
};
|
|
popOut.onButtonClick = (data) => {
|
|
var _a;
|
|
if ((_a = this.popOutRow(data)) == null ? void 0 : _a.isActionable) {
|
|
WidgetSyncManager.clickButton(data.nodeId, data.widgetName);
|
|
}
|
|
this.refreshPopOut();
|
|
};
|
|
popOut.onRequestOptions = (data) => {
|
|
var _a, _b;
|
|
return ((_b = (_a = this.popOutRow(data)) == null ? void 0 : _a.constraints) == null ? void 0 : _b.options) ?? [];
|
|
};
|
|
popOut.onSearchNodes = (query) => this.uiManager.nodeSelector.search(query);
|
|
popOut.onPanelAction = (name, nodeId) => {
|
|
var _a;
|
|
if (nodeId === this.popOutNodeId && ((_a = app.canvas) == null ? void 0 : _a.graph) === this.popOutGraph) {
|
|
this.uiManager.runAction(name, nodeId);
|
|
}
|
|
};
|
|
this.setPopOutRefresh(popOut.isPopOutOpen());
|
|
}
|
|
this.uiManager.onRefresh = () => this.updateInfo();
|
|
Logger.debug("Info Panel initialized successfully");
|
|
}
|
|
hookIntoMagnifyGlass() {
|
|
const mg = this.magnifyGlass;
|
|
mg.updateMagnifiedView = () => {
|
|
this.originalUpdateMagnifiedView.call(mg);
|
|
if (mg.state.active) {
|
|
this.scheduleInfoUpdate();
|
|
}
|
|
};
|
|
mg.ui.show = () => {
|
|
this.originalShow.call(mg.ui);
|
|
if (!this.magnifyGlass.state.active) {
|
|
return;
|
|
}
|
|
if (this.stateManager.state.wasPanelVisibleBeforeHide) {
|
|
this.uiManager.show();
|
|
setTimeout(() => {
|
|
this.positionManager.positionPanel();
|
|
this.positionManager.positionFloatingControls(this.uiManager.elements.controls);
|
|
}, 10);
|
|
} else {
|
|
const showControls = this.stateManager.state.settings["🔍MagnifyGlass.ShowHoveringControls"] !== false;
|
|
if (showControls && this.uiManager.elements.controls) {
|
|
this.uiManager.elements.controls.style.display = "flex";
|
|
this.uiManager.elements.controls.style.pointerEvents = "auto";
|
|
}
|
|
this.uiManager.updateControlStates();
|
|
setTimeout(() => {
|
|
this.positionManager.positionFloatingControls(this.uiManager.elements.controls);
|
|
}, 10);
|
|
}
|
|
};
|
|
mg.ui.positionGlass = (x, y) => {
|
|
if (this.aiming || this.isPointerOnPanel()) return;
|
|
this.originalPositionGlass.call(mg.ui, x, y);
|
|
};
|
|
mg.ui.hide = () => {
|
|
this.stateManager.state.wasPanelVisibleBeforeHide = this.stateManager.state.isPanelVisible;
|
|
this.originalHide.call(mg.ui);
|
|
this.uiManager.hide();
|
|
if (this.uiManager.elements.controls) {
|
|
this.uiManager.elements.controls.style.display = "none";
|
|
this.uiManager.elements.controls.style.pointerEvents = "none";
|
|
}
|
|
this.canvasHighlighter.setHighlightedNode(null);
|
|
};
|
|
}
|
|
scheduleInfoUpdate() {
|
|
if (this.updateFrameId !== null) return;
|
|
this.updateFrameId = requestAnimationFrame(() => {
|
|
this.updateFrameId = null;
|
|
this.updateInfo();
|
|
});
|
|
}
|
|
/**
|
|
* Undo everything the constructor set up: glass hooks, pop-out callbacks,
|
|
* listeners, timers and DOM.
|
|
*/
|
|
cleanup() {
|
|
const mg = this.magnifyGlass;
|
|
mg.updateMagnifiedView = this.originalUpdateMagnifiedView;
|
|
mg.ui.show = this.originalShow;
|
|
mg.ui.hide = this.originalHide;
|
|
mg.ui.positionGlass = this.originalPositionGlass;
|
|
if (mg.popOutManager) {
|
|
mg.popOutManager.onStateChange = null;
|
|
mg.popOutManager.onNodeSelect = null;
|
|
mg.popOutManager.onWidgetEdit = null;
|
|
mg.popOutManager.onButtonClick = null;
|
|
mg.popOutManager.onRequestOptions = null;
|
|
mg.popOutManager.onSearchNodes = null;
|
|
mg.popOutManager.onPanelAction = null;
|
|
}
|
|
this.setPopOutRefresh(false);
|
|
if (this.updateFrameId !== null) {
|
|
cancelAnimationFrame(this.updateFrameId);
|
|
this.updateFrameId = null;
|
|
}
|
|
if (this.aimTimer !== null) {
|
|
clearTimeout(this.aimTimer);
|
|
this.aimTimer = null;
|
|
}
|
|
document.removeEventListener("pointerup", this.boundScheduleSelectionUpdate, true);
|
|
document.removeEventListener("keyup", this.boundScheduleSelectionUpdate, true);
|
|
this.eventManager.cleanup();
|
|
this.uiManager.cleanup();
|
|
this.canvasHighlighter.cleanup();
|
|
}
|
|
/**
|
|
* Follow the glass again from where it starts.
|
|
*/
|
|
resetPosition() {
|
|
if (!this.stateManager.state.isGlassPreviewVisible) return;
|
|
this.stateManager.state.isFloating = false;
|
|
this.stateManager.state.floatPosition = null;
|
|
this.stateManager.saveLayout();
|
|
this.positionManager.positionPanel();
|
|
this.uiManager.updateControlStates();
|
|
}
|
|
/**
|
|
* Update the info panel and the pop-out with the node to show.
|
|
* @param fromTick - The pop-out's refresh: the glass has not moved, so the panel is not placed again
|
|
*/
|
|
updateInfo(fromTick = false) {
|
|
var _a, _b, _c, _d, _e;
|
|
const settings = this.stateManager.state.settings;
|
|
const isActive = this.magnifyGlass.state.active;
|
|
const popOutOpen = !!((_a = this.magnifyGlass.popOutManager) == null ? void 0 : _a.isPopOutOpen());
|
|
if (!isActive) {
|
|
if (this.stateManager.state.isPanelVisible) this.uiManager.hide();
|
|
if (this.uiManager.elements.controls && this.uiManager.elements.controls.style.display !== "none") {
|
|
this.uiManager.elements.controls.style.display = "none";
|
|
}
|
|
this.canvasHighlighter.setHighlightedNode(null);
|
|
if (!popOutOpen) return;
|
|
}
|
|
const hovered = isActive ? this.resolveHover() : null;
|
|
let node = hovered ? this.informationGatherer.getDetailedNodeInfo(hovered) : null;
|
|
let source = "hover";
|
|
const state = this.stateManager.state;
|
|
if (state.lockedNodeId !== null && state.lockedGraph !== ((_b = app.canvas) == null ? void 0 : _b.graph)) {
|
|
state.lockedNodeId = null;
|
|
}
|
|
const lockedNode = state.lockedNodeId === null ? null : this.uiManager.nodeSelector.getNodeById(state.lockedNodeId);
|
|
if (!lockedNode) {
|
|
state.lockedNodeId = null;
|
|
}
|
|
const selectedNode = !lockedNode && settings["🔍MagnifyGlass.InfoPanelFollowSelection"] ? Object.values(((_c = app.canvas) == null ? void 0 : _c.selected_nodes) ?? {})[0] : void 0;
|
|
state.showsSelection = !!selectedNode;
|
|
const shownNode = lockedNode ?? selectedNode;
|
|
if (shownNode) {
|
|
node = this.informationGatherer.getDetailedNodeInfo(shownNode);
|
|
source = lockedNode ? "locked" : "selection";
|
|
}
|
|
if (node) {
|
|
this.stickyNodeId = node.id;
|
|
this.stickyGraph = (_d = app.canvas) == null ? void 0 : _d.graph;
|
|
} else if (settings["🔍MagnifyGlass.InfoPanelPersist"] && this.stickyNodeId !== null) {
|
|
const stickyNode = this.stickyGraph === ((_e = app.canvas) == null ? void 0 : _e.graph) ? this.uiManager.nodeSelector.getNodeById(this.stickyNodeId) : null;
|
|
if (stickyNode) {
|
|
node = this.informationGatherer.getDetailedNodeInfo(stickyNode);
|
|
source = "sticky";
|
|
} else {
|
|
this.stickyNodeId = null;
|
|
}
|
|
}
|
|
state.currentNodeId = (node == null ? void 0 : node.id) ?? null;
|
|
const info = { hoveredNode: node };
|
|
if (isActive) {
|
|
this.uiManager.displayInfo(info);
|
|
this.canvasHighlighter.setHighlightedNode(node ? node.id : null);
|
|
if (!fromTick && !this.aiming && !this.isPointerOnPanel()) {
|
|
this.positionManager.positionPanel();
|
|
this.positionManager.positionFloatingControls(this.uiManager.elements.controls);
|
|
}
|
|
}
|
|
if (popOutOpen) {
|
|
this.sendPopOutInfo(info, source);
|
|
}
|
|
}
|
|
/**
|
|
* The node under the pointer. Over other UI (the sidebar, a menu, this panel) the last one stays, and so it
|
|
* does while the pointer heads from it for the panel, crossing canvas and other nodes, until the pointer rests.
|
|
*/
|
|
resolveHover() {
|
|
var _a;
|
|
const { x, y } = this.magnifyGlass.lastKnownMousePosition;
|
|
const now = performance.now();
|
|
if (x !== this.pointer.x || y !== this.pointer.y) this.pointer = { x, y, movedAt: now };
|
|
const graph = (_a = app.canvas) == null ? void 0 : _a.graph;
|
|
const kept = this.hoverNodeId !== null && this.hoverGraph === graph ? this.uiManager.nodeSelector.getNodeById(this.hoverNodeId) : null;
|
|
this.aiming = false;
|
|
if (!this.informationGatherer.isPointerOverGraph(x, y)) return kept;
|
|
const node = this.informationGatherer.getNodeUnderCursor();
|
|
if (node !== kept && kept && now - this.pointer.movedAt < AIM_REST_MS && this.headsForPanel(x, y)) {
|
|
this.aiming = true;
|
|
this.aimTimer ?? (this.aimTimer = window.setTimeout(() => {
|
|
this.aimTimer = null;
|
|
this.scheduleInfoUpdate();
|
|
}, AIM_REST_MS));
|
|
return kept;
|
|
}
|
|
this.hoverAnchor = node ? { x, y } : null;
|
|
this.hoverNodeId = (node == null ? void 0 : node.id) ?? null;
|
|
this.hoverGraph = graph;
|
|
return node;
|
|
}
|
|
/**
|
|
* Whether the pointer moves from where it left the shown node toward the panel or its controls.
|
|
*/
|
|
headsForPanel(x, y) {
|
|
const anchor = this.hoverAnchor;
|
|
if (!anchor || !this.stateManager.state.isPanelVisible) return false;
|
|
const dx = x - anchor.x;
|
|
const dy = y - anchor.y;
|
|
if (dx === 0 && dy === 0) return false;
|
|
const { panel, controls } = this.uiManager.elements;
|
|
return [panel, controls].some((element) => {
|
|
const rect = element == null ? void 0 : element.getBoundingClientRect();
|
|
const covers = !!rect && anchor.x >= rect.left && anchor.x <= rect.right && anchor.y >= rect.top && anchor.y <= rect.bottom;
|
|
return !!rect && rect.width > 0 && !covers && rayHitsRect(anchor.x, anchor.y, dx, dy, rect);
|
|
});
|
|
}
|
|
isPointerOnPanel() {
|
|
const { x, y } = this.magnifyGlass.lastKnownMousePosition;
|
|
const element = document.elementFromPoint(x, y);
|
|
const { panel, controls } = this.uiManager.elements;
|
|
return !!element && (!!(panel == null ? void 0 : panel.contains(element)) || !!(controls == null ? void 0 : controls.contains(element)));
|
|
}
|
|
/**
|
|
* Send the pop-out what the Inspector shows, when it changed since the last send.
|
|
*/
|
|
sendPopOutInfo(info, source) {
|
|
var _a, _b;
|
|
const nav = {
|
|
source,
|
|
locked: this.stateManager.state.lockedNodeId !== null,
|
|
...this.uiManager.getHistoryNav(),
|
|
canEdit: this.uiManager.canEdit()
|
|
};
|
|
const node = info.hoveredNode;
|
|
const liveNode = node && this.uiManager.nodeSelector.getNodeById(node.id);
|
|
const links = liveNode ? getSlotLinks(liveNode) : { inputs: [], outputs: [] };
|
|
const key = [
|
|
...this.uiManager.getRenderKey(info),
|
|
...Object.values(nav),
|
|
app.lastNodeErrors,
|
|
node && ((_a = app.nodeOutputs[node.locatorId]) == null ? void 0 : _a.images),
|
|
node && app.nodePreviewImages[node.locatorId],
|
|
JSON.stringify(links)
|
|
];
|
|
const sent = this.popOutKey;
|
|
if (sent && key.length === sent.length && key.every((v, i) => Object.is(v, sent[i]))) return;
|
|
this.popOutKey = key;
|
|
this.popOutNodeId = (node == null ? void 0 : node.id) ?? null;
|
|
this.popOutGraph = (_b = app.canvas) == null ? void 0 : _b.graph;
|
|
this.magnifyGlass.popOutManager.sendInfo(this.buildPopOutInfo(node, nav, links));
|
|
}
|
|
/**
|
|
* The pop-out payload: the node's identity and place, its widget rows, outputs and links as plain data.
|
|
*/
|
|
buildPopOutInfo(node, nav, links) {
|
|
var _a, _b, _c;
|
|
if (!node) return { node: null, nav, rows: [], outputs: [], links };
|
|
const errors = /* @__PURE__ */ new Map();
|
|
for (const error of ((_b = (_a = app.lastNodeErrors) == null ? void 0 : _a[node.executionId]) == null ? void 0 : _b.errors) ?? []) {
|
|
const input = (_c = error.extra_info) == null ? void 0 : _c.input_name;
|
|
if (input) errors.set(input, error.details ? `${error.message}: ${error.details}` : error.message);
|
|
}
|
|
return {
|
|
node: {
|
|
id: node.id,
|
|
title: node.title,
|
|
type: node.type,
|
|
mode: node.mode,
|
|
execOrder: node.executionOrder,
|
|
executionId: node.executionId,
|
|
graphPath: node.graphPath,
|
|
group: node.group,
|
|
isSubgraph: node.isSubgraph
|
|
},
|
|
nav,
|
|
rows: getImportantNodeParameters(node).map((row) => {
|
|
const { options, ...constraints } = row.constraints ?? {};
|
|
const raw = row.rawValue;
|
|
return {
|
|
label: row.label,
|
|
widgetName: row.widgetName,
|
|
widgetType: row.widgetType,
|
|
value: row.value,
|
|
rawValue: raw === null || typeof raw === "string" || typeof raw === "number" || typeof raw === "boolean" ? raw : void 0,
|
|
isEditable: !!row.isEditable,
|
|
isLinked: !!row.isLinked,
|
|
isActionable: !!row.isActionable,
|
|
constraints,
|
|
error: row.widgetName ? errors.get(row.widgetName) : void 0
|
|
};
|
|
}),
|
|
outputs: this.popOutOutputs(node.locatorId),
|
|
links
|
|
};
|
|
}
|
|
/**
|
|
* The node's images as ComfyUI previews them on the node: its live previews while it runs, otherwise its last results.
|
|
*/
|
|
popOutOutputs(locatorId) {
|
|
var _a;
|
|
const previews = app.nodePreviewImages[locatorId];
|
|
if (previews == null ? void 0 : previews.length) return previews;
|
|
const output = app.nodeOutputs[locatorId];
|
|
if (!(output == null ? void 0 : output.images)) return [];
|
|
if (output.images !== this.popOutImages) {
|
|
this.popOutImages = output.images;
|
|
const video = ((_a = output.animated) == null ? void 0 : _a.some(Boolean)) && !output.images.some((image) => /webp|png/.test(image.filename));
|
|
this.popOutImageUrls = video ? [] : output.images.map(({ filename, subfolder, type }) => app.api.apiURL(`/view?${new URLSearchParams({ filename, subfolder, type })}${app.getRandParam()}`));
|
|
}
|
|
return this.popOutImageUrls;
|
|
}
|
|
/**
|
|
* The row of a widget on the node the pop-out shows, while its graph is still on screen.
|
|
*/
|
|
popOutRow({ nodeId, widgetName }) {
|
|
var _a;
|
|
if (nodeId !== this.popOutNodeId || ((_a = app.canvas) == null ? void 0 : _a.graph) !== this.popOutGraph) return void 0;
|
|
const node = this.uiManager.nodeSelector.getNodeById(nodeId);
|
|
return node ? getImportantNodeParameters(this.informationGatherer.getDetailedNodeInfo(node)).find((row) => row.widgetName === widgetName) : void 0;
|
|
}
|
|
/**
|
|
* Send the pop-out its info now, even if nothing changed.
|
|
*/
|
|
refreshPopOut() {
|
|
this.popOutKey = null;
|
|
this.updateInfo();
|
|
}
|
|
/**
|
|
* Refresh the pop-out a few times a second while it is connected: values change after a run
|
|
* or from another window without any input in this one.
|
|
*/
|
|
setPopOutRefresh(connected) {
|
|
if (this.popOutTimer !== null) {
|
|
clearInterval(this.popOutTimer);
|
|
this.popOutTimer = null;
|
|
}
|
|
if (!connected) return;
|
|
this.popOutTimer = window.setInterval(() => this.updateInfo(true), 250);
|
|
this.refreshPopOut();
|
|
}
|
|
}
|
|
function mountInfoPanel(magnifyGlass) {
|
|
if (window.infoPanelManager) return;
|
|
const infoPanel = new InfoPanel(magnifyGlass);
|
|
window.infoPanelManager = infoPanel;
|
|
(window.comfyUIMagnifyGlassExtensions ?? (window.comfyUIMagnifyGlassExtensions = [])).push(infoPanel);
|
|
magnifyGlass.setGlassPreviewActive(true);
|
|
if (magnifyGlass.state.active) {
|
|
magnifyGlass.ui.show();
|
|
}
|
|
}
|
|
function unmountInfoPanel(magnifyGlass) {
|
|
var _a;
|
|
const infoPanel = window.infoPanelManager;
|
|
if (!infoPanel) return;
|
|
infoPanel.cleanup();
|
|
window.infoPanelManager = void 0;
|
|
window.comfyUIMagnifyGlassExtensions = (_a = window.comfyUIMagnifyGlassExtensions) == null ? void 0 : _a.filter((ext) => ext !== infoPanel);
|
|
magnifyGlass.setGlassPreviewActive(true);
|
|
}
|
|
export {
|
|
InfoPanel,
|
|
mountInfoPanel,
|
|
unmountInfoPanel
|
|
};
|