113 lines
3.4 KiB
JavaScript
113 lines
3.4 KiB
JavaScript
import { api } from "../../scripts/api.js";
|
|
import { app } from "../../scripts/app.js";
|
|
|
|
export class Util {
|
|
|
|
// Server
|
|
static AddMessageListener(messagePath, handlerFunc) {
|
|
api.addEventListener(messagePath, handlerFunc);
|
|
}
|
|
|
|
// Widget
|
|
static SetTextAreaContent(widget, text) {
|
|
widget.element.textContent = text
|
|
}
|
|
|
|
static SetTextAreaScrollPos(widget, pos01) {
|
|
widget.element.scroll(0, widget.element.scrollHeight * pos01)
|
|
}
|
|
|
|
static AddReadOnlyTextArea(node, name, text, placeholder = "") {
|
|
const inputEl = document.createElement("textarea");
|
|
inputEl.className = "comfy-multiline-input";
|
|
inputEl.placeholder = placeholder
|
|
inputEl.spellcheck = false
|
|
inputEl.readOnly = true
|
|
inputEl.textContent = text
|
|
return node.addDOMWidget(name, "", inputEl, {
|
|
serialize: false,
|
|
});
|
|
}
|
|
|
|
static AddButtonWidget(node, label, callback, value = null) {
|
|
return node.addWidget("button", label, value, callback);
|
|
}
|
|
|
|
}
|
|
|
|
// 通用终端管理器
|
|
export class TerminalManager {
|
|
constructor(messagePath, nodeType) {
|
|
this.messagePath = messagePath;
|
|
this.nodeType = nodeType;
|
|
this.textVersion = 0;
|
|
this.lines = new Array();
|
|
|
|
// 监听消息
|
|
Util.AddMessageListener(messagePath, (event) => {
|
|
this.textVersion++;
|
|
if (event.detail.clear) {
|
|
this.lines.length = 0;
|
|
}
|
|
let totalText = String(event.detail.text || "");
|
|
this.lines.push(...(totalText.split("\n")));
|
|
if (this.lines.length > 1024) {
|
|
this.lines = this.lines.slice(-1024);
|
|
}
|
|
// 刷新所有相关节点
|
|
for (let i = 0; i < app.graph._nodes.length; i++) {
|
|
var node = app.graph._nodes[i];
|
|
if (node.type == nodeType && node.setDirtyCanvas) {
|
|
node.setDirtyCanvas(true);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
// 清空终端
|
|
clearTerminal() {
|
|
this.lines.length = 0;
|
|
this.textVersion++;
|
|
}
|
|
|
|
// 获取终端内容
|
|
getContent() {
|
|
return this.lines.join("\n");
|
|
}
|
|
|
|
// 创建节点时的设置
|
|
setupNode(node) {
|
|
var textArea = Util.AddReadOnlyTextArea(node, "terminal", "");
|
|
setTimeout(() => {
|
|
if (textArea.element) {
|
|
textArea.element.style.backgroundColor = "#000000ff";
|
|
textArea.element.style.color = "#ffffffff";
|
|
textArea.element.style.fontFamily = "monospace";
|
|
}
|
|
}, 0);
|
|
|
|
let clearBtn = Util.AddButtonWidget(node, "清空日志", () => {
|
|
this.clearTerminal();
|
|
});
|
|
clearBtn.width = 128;
|
|
|
|
node.terminalVersion = -1;
|
|
return node;
|
|
}
|
|
|
|
// 绘制时的更新
|
|
updateNode(node, onDrawForeground, ctx, graphcanvas) {
|
|
if (node.terminalVersion != this.textVersion) {
|
|
node.terminalVersion = this.textVersion;
|
|
for (var i = 0; i < node.widgets.length; i++) {
|
|
var wid = node.widgets[i];
|
|
if (wid.name == "terminal") {
|
|
Util.SetTextAreaContent(wid, this.getContent());
|
|
Util.SetTextAreaScrollPos(wid, 1.0);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return onDrawForeground?.apply(node, [ctx, graphcanvas]);
|
|
}
|
|
}
|