Files
billwuhao-ComfyUI_AudioTools/web/string_editor_node.js
T
2025-04-25 15:57:18 +08:00

137 lines
7.5 KiB
JavaScript

// filename: ComfyUI/web/extensions/string_editor_persistent_tempfile_node.js
import { app } from "../../scripts/app.js";
import { api } from "../../scripts/api.js";
app.registerExtension({
name: "Comfy.StringEditorPersistentTempFileNode",
async nodeCreated(node) {
if (node.constructor.comfyClass !== "StringEditorPersistentTempFileNode") {
return;
}
console.log("StringEditorPersistentTempFileNode: nodeCreated", node.id);
const container = document.createElement("div");
container.style.display = "flex";
container.style.flexDirection = "column";
// Removed justify-content, let natural flow happen
// Removed height: 100%
container.style.padding = "2px";
container.style.margin = "0";
container.style.gap = "2px"; // Smaller gap
// --- Control Overflow ---
container.style.overflow = "hidden"; // Prevent container itself from overflowing node bounds
// -----------------------
// const label = document.createElement("label");
// label.textContent = "Edit Text & Continue (Persistent):";
// label.style.fontSize = "0.8em";
// label.style.color = "var(--descrip-text)";
// label.style.marginBottom = "3px";
// label.style.flexShrink = "0";
// container.appendChild(label); // Label directly in container
const textarea = document.createElement("textarea");
textarea.rows = 50; // Keep large default rows
textarea.placeholder = "Workflow paused. Edit text and click Continue.";
// --- Control Textarea Size/Overflow ---
// Let textarea be naturally sized by rows initially, but limit max height
textarea.style.minHeight = "160px"; // Reasonable minimum
textarea.style.maxHeight = "600px"; // Set a sensible maximum height (adjust as needed)
textarea.style.overflowY = "auto"; // Add scrollbar if content exceeds max height
textarea.style.resize = "vertical";
textarea.style.padding = "1px";
textarea.style.border = "1px solid var(--border-color)";
textarea.style.backgroundColor = "var(--comfy-input-bg)";
textarea.style.color = "var(--input-text)";
textarea.style.width = "calc(100% - 1px)"; // Ensure it fits horizontally within padding
textarea.disabled = true;
node.stringEditorTextarea = textarea;
container.appendChild(textarea); // Textarea directly in container
const button = document.createElement("button");
button.textContent = "Continue Workflow";
button.style.padding = "3px 10px";
button.style.marginTop = "5px";
button.style.cursor = "pointer";
button.style.border = "1px solid var(--border-color)";
button.style.backgroundColor = "var(--comfy-input-bg)";
button.style.color = "var(--input-text)";
button.style.flexShrink = "0"; // Prevent shrinking
button.style.borderRadius = "15px";
button.disabled = true;
node.stringEditorButton = button;
container.appendChild(button); // Button directly in container
const widget = node.addDOMWidget(`string_editor_persistent_widget_${node.id}`, "dom", container, {});
// --- computeSize (Simpler - let content mostly decide) ---
widget.computeSize = function(width) {
// Estimate minimum based on non-textarea elements + small textarea amount
const minHeight = 250; // Minimum needed for label, button, small textarea
// Get the container's *current* scrollHeight as a proxy for desired height
let contentHeight = container.scrollHeight;
const maxHeight = 800; // Absolute max node height (adjust)
// Use scrollHeight, but cap it and ensure minimum
let targetHeight = Math.max(minHeight, contentHeight + 10); // Add padding
targetHeight = Math.min(maxHeight, targetHeight); // Apply max height
console.log(`[computeSize] Request W: ${width}, scrollH: ${container.scrollHeight}, Target H: ${targetHeight}`);
return [width, Math.ceil(targetHeight)];
}
// --- Resize Observer (Still useful for manual drag) ---
let resizeTimeout;
new ResizeObserver(() => {
clearTimeout(resizeTimeout);
resizeTimeout = setTimeout(() => {
try {
// When textarea manually resizes, tell the node its overall size might need recalculating
node.computeSize(); // Trigger node's own size update based on widget
node.setDirtyCanvas(true, true);
} catch(e) { console.error("ResizeObserver error:", e); }
}, 150);
}).observe(textarea);
// --- Button Click Handler (Keep TempFile logic) ---
button.addEventListener("click", async () => {
// ...(Same logic: call /signal_continue, then app.queuePrompt() on success)...
const editedString = textarea.value; const nodeId = node.id;
console.log(`StringEditorPersistent: 'Continue' clicked for node ${nodeId}.`);
button.disabled = true; textarea.disabled = true;
try {
const response = await api.fetchApi("/string_editor/signal_continue", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ node_id: nodeId, edited_string: editedString }), });
if (!response.ok) { const errorData = await response.json(); const errorMsg = `Error saving state: ${errorData.message || response.statusText} (Status: ${response.status})`; console.error(`StringEditorPersistent: ${errorMsg} for node ${nodeId}`); alert(errorMsg); button.textContent = "Continue Workflow"; button.disabled = false; textarea.disabled = false; }
else { console.log(`StringEditorPersistent: State saved. Re-queueing prompt.`); app.queuePrompt(); }
} catch (error) { console.error(`StringEditorPersistent: Network error during continue for node ${nodeId}:`, error); alert(`Network error: ${error.message}`); button.textContent = "Continue Workflow"; button.disabled = false; textarea.disabled = false; }
});
// Initial size calculation
node.computeSize();
node.setDirtyCanvas(true, true);
}, // end nodeCreated
async setup(app) {
// ...(setup listener remains the same - listens for string_editor_persistent_tempfile_display)...
console.log("StringEditorPersistentTempFileNode: Setup.");
api.addEventListener("string_editor_persistent_tempfile_display", (event) => { // Listen for NEW event name
const { node_id, string_to_edit } = event.detail;
console.log(`StringEditorPersistent: Received 'display' event for node ${node_id}`);
const node = app.graph.getNodeById(node_id);
if (node && node.stringEditorTextarea && node.stringEditorButton) {
console.log(`StringEditorPersistent: Updating UI for node ${node_id}`);
node.stringEditorTextarea.value = string_to_edit;
node.stringEditorTextarea.disabled = false;
node.stringEditorButton.textContent = "Continue Workflow";
node.stringEditorButton.disabled = false;
node.computeSize(); // Recalculate size after content update
node.setDirtyCanvas(true, true);
} else { console.warn(`StringEditorPersistent: Could not find node/widgets for ID ${node_id}`); }
});
} // end setup
});
console.log("StringEditorPersistentTempFileNode: Extension registered.");