Files
1hew-ComfyUI-1hewNodes/web/js/text_preview.js
T

226 lines
7.5 KiB
JavaScript

import { app } from "../../../scripts/app.js";
import { ComfyWidgets } from "../../../scripts/widgets.js";
const TEXT_PREVIEW_NODES = ["1hew_SaveTxt", "1hew_LoadTxt"];
function getSerializableWidgets(node) {
return (node?.widgets || []).filter((w) => w && w.serialize !== false);
}
function getWidgetDefaultValue(widget) {
const optionDefault = widget?.options?.default;
if (optionDefault !== undefined) {
return optionDefault;
}
if (widget?.type === "toggle") {
return false;
}
if (widget?.type === "combo") {
const values = widget?.options?.values;
if (Array.isArray(values) && values.length > 0) {
return values[0];
}
}
return "";
}
function isValueCompatible(widget, value) {
if (widget?.type === "toggle") {
return typeof value === "boolean";
}
if (widget?.type === "combo") {
return typeof value === "string";
}
if (widget?.type === "text" || widget?.type === "customtext") {
return typeof value === "string";
}
return value !== undefined;
}
function scoreWindow(widgets, values, start) {
let score = 0;
for (let i = 0; i < widgets.length; i += 1) {
if (isValueCompatible(widgets[i], values[start + i])) {
score += 1;
}
}
return score;
}
function normalizeWidgetsValues(node, rawValues) {
const widgets = getSerializableWidgets(node);
const expectedCount = widgets.length;
const sourceValues = Array.isArray(rawValues) ? rawValues.slice() : [];
if (!expectedCount) {
return sourceValues;
}
let candidate = sourceValues.slice(0, expectedCount);
if (sourceValues.length >= expectedCount) {
let bestStart = 0;
let bestScore = -1;
for (let start = 0; start <= sourceValues.length - expectedCount; start += 1) {
const score = scoreWindow(widgets, sourceValues, start);
if (score > bestScore) {
bestScore = score;
bestStart = start;
}
}
candidate = sourceValues.slice(bestStart, bestStart + expectedCount);
}
while (candidate.length < expectedCount) {
candidate.push(undefined);
}
return widgets.map((widget, index) => {
const value = candidate[index];
return isValueCompatible(widget, value)
? value
: getWidgetDefaultValue(widget);
});
}
function configurePreviewWidget(widget) {
if (!widget) {
return widget;
}
widget.serialize = false;
widget.options = widget.options || {};
widget.options.read_only = true;
widget.options.hidden = false;
if (widget.element) {
widget.element.readOnly = true;
}
return widget;
}
function movePreviewWidgetToTop(node, widget) {
if (!node?.widgets || !widget) {
return widget;
}
const idx = node.widgets.indexOf(widget);
if (idx > 0) {
node.widgets.splice(idx, 1);
node.widgets.splice(0, 0, widget);
}
return widget;
}
function ensurePreviewWidget(node) {
if (!node) {
return null;
}
let previewWidget = node.widgets?.find((w) => w.name === "preview_text") || null;
if (!previewWidget) {
previewWidget = ComfyWidgets["STRING"](
node,
"preview_text",
["STRING", { multiline: true }],
app,
).widget;
}
configurePreviewWidget(previewWidget);
movePreviewWidgetToTop(node, previewWidget);
return previewWidget;
}
app.registerExtension({
name: "ComfyUI-1hewNodesV3.TextPreview",
async beforeRegisterNodeDef(nodeType, nodeData) {
const typeName = nodeData?.name || nodeType?.type || nodeType?.title;
if (!TEXT_PREVIEW_NODES.includes(typeName)) {
return;
}
const onNodeCreated = nodeType.prototype.onNodeCreated;
nodeType.prototype.onNodeCreated = function () {
onNodeCreated?.apply(this, arguments);
const previewWidget = ensurePreviewWidget(this);
if (previewWidget) {
const savedPreviewText =
typeof this.properties?._comfy1hewPreviewText === "string"
? this.properties._comfy1hewPreviewText
: "";
if (savedPreviewText && !previewWidget.value) {
previewWidget.value = savedPreviewText;
}
}
};
const onConfigure = nodeType.prototype.onConfigure;
nodeType.prototype.onConfigure = function () {
const data = arguments[0];
const previewWidget = this.widgets?.find((w) => w.name === "preview_text");
const previewValue = previewWidget?.value ?? "";
const normalizedIncomingValues = Array.isArray(data?.widgets_values)
? normalizeWidgetsValues(this, data.widgets_values)
: null;
const savedPreviewText =
(typeof data?.properties?._comfy1hewPreviewText === "string"
? data.properties._comfy1hewPreviewText
: null)
?? (typeof this.properties?._comfy1hewPreviewText === "string"
? this.properties._comfy1hewPreviewText
: "");
if (data && normalizedIncomingValues) {
data.widgets_values = normalizedIncomingValues;
}
const r = onConfigure?.apply(this, arguments);
const restoredPreviewWidget = ensurePreviewWidget(this);
if (restoredPreviewWidget) {
const nextPreviewValue = previewValue || savedPreviewText;
if (nextPreviewValue && !restoredPreviewWidget.value) {
restoredPreviewWidget.value = nextPreviewValue;
}
}
return r;
};
const onSerialize = nodeType.prototype.onSerialize;
nodeType.prototype.onSerialize = function () {
const r = onSerialize?.apply(this, arguments);
const serialized = arguments[0];
const normalizedSerializedValues = normalizeWidgetsValues(
this,
Array.isArray(serialized?.widgets_values)
? serialized.widgets_values
: [],
);
const previewWidget = this.widgets?.find((w) => w?.name === "preview_text");
const previewTextToPersist =
(typeof previewWidget?.value === "string" ? previewWidget.value : "")
|| (typeof this.properties?._comfy1hewPreviewText === "string"
? this.properties._comfy1hewPreviewText
: "");
if (serialized) {
serialized.widgets_values = normalizedSerializedValues;
serialized.properties = {
...(serialized.properties || {}),
_comfy1hewPreviewText: previewTextToPersist,
};
}
return r;
};
const onExecuted = nodeType.prototype.onExecuted;
nodeType.prototype.onExecuted = function (message) {
onExecuted?.apply(this, arguments);
const w = ensurePreviewWidget(this);
if (!w) {
return;
}
const raw = message?.text;
if (raw == null) {
return;
}
w.value = Array.isArray(raw) ? raw.join("\n\n") : String(raw);
this.properties = this.properties || {};
this.properties._comfy1hewPreviewText = w.value;
};
},
});