Added textbox with copy and paste functionality

This commit is contained in:
Lucas Sköld
2024-05-06 00:23:14 +02:00
parent 56e6098734
commit 6110dbd731
4 changed files with 124 additions and 2 deletions
+3
View File
@@ -15,6 +15,7 @@ from .src.prompt_selector import PromptSelectNode
from .src.perlin_noise import FilmGrain
from .src.upscale_with_model_by import UpscaleImageBy
from .src.load_lora_from_folder import LoadLoraFolderNode
from .src.textbox import TextboxNode
NODE_CLASS_MAPPINGS = {
"Find SDXL Resolution": FindResolutionNode,
@@ -31,6 +32,7 @@ NODE_CLASS_MAPPINGS = {
"Colored Film Grain": FilmGrain,
"Upscale Image With Model By": UpscaleImageBy,
"Load Lora Folder": LoadLoraFolderNode,
"Copy/Paste Textbox": TextboxNode,
}
NODE_DISPLAY_NAME_MAPPINGS = {
@@ -48,6 +50,7 @@ NODE_DISPLAY_NAME_MAPPINGS = {
"Colored Film Grain": "Colored Film Grain",
"Upscale Image With Model By": "Upscale Image With Model By",
"Load Lora Folder": "Load Lora Folder",
"Copy/Paste Textbox": "Textbox",
}
WEB_DIRECTORY = "./web"
+31 -2
View File
@@ -1,7 +1,11 @@
import os
import json
import time
import torch
from server import PromptServer
from aiohttp import web
class ConfigReader:
@staticmethod
def get_setting(setting_id, default=None):
@@ -117,7 +121,7 @@ class Utility:
def initialize_state():
# Default values
default_state = {
'random_character_chosen': False
'character': "None"
}
state_path = os.path.join(Utility.ROOT_DIR, 'state.json')
@@ -165,4 +169,29 @@ class Utility:
# Create a new state.json with default values or empty
with open(state_path, 'w') as f:
json.dump({}, f)
return None
return None
class MessageHolder:
messages = {}
@classmethod
def addMessage(self, id, message):
self.messages[str(id)] = message
print(f"Adding message for ID: {id}, Message: {message}")
@classmethod
def waitForMessage(self, id, period = 0.1):
sid = str(id)
while not (sid in self.messages):
time.sleep(period)
message = self.messages.pop(str(id),None)
return message
routes = PromptServer.instance.routes
@routes.post('/textbox_string')
async def handle_textbox_string(request):
data = await request.json() # Parse JSON from request
MessageHolder.addMessage(data.get("node_id"), data.get("outputs"))
return web.json_response({"status": "ok"})
+26
View File
@@ -0,0 +1,26 @@
from server import PromptServer
from ..sn0w import MessageHolder
class TextboxNode:
@classmethod
def INPUT_TYPES(s):
return {
"required": {
},
"hidden": {
"unique_id": "UNIQUE_ID",
},
}
RETURN_TYPES = ("STRING",)
FUNCTION = "run"
CATEGORY = "utils"
def run(self, unique_id):
PromptServer.instance.send_sync("textbox", {
"id": unique_id,
})
outputs = MessageHolder.waitForMessage(unique_id)
return (outputs['output'],)
+64
View File
@@ -0,0 +1,64 @@
import { app } from "../../../scripts/app.js";
import { api } from '../../scripts/api.js';
import { ComfyWidgets } from "../../../scripts/widgets.js";
app.registerExtension({
name: "sn0w.Textbox",
async beforeRegisterNodeDef(nodeType, nodeData, app) {
if (nodeData.name === "Copy/Paste Textbox") {
// Get textbox text
nodeType.prototype.getTextboxText = function() {
const textbox = this.inputEl ? this.inputEl.value : '';
return textbox;
};
nodeType.prototype.populate = function() {
// Adding a multiline text widget and storing a reference to the input element
let textWidget = ComfyWidgets["STRING"](this, "text", ["STRING", { default: "", multiline: true }], app).widget;
this.inputEl = textWidget.inputEl || textWidget.querySelector('input, textarea');
// Implement copy functionality with proper callback
this.addWidget("button", "Copy", "Copy", () => {
navigator.clipboard.writeText(this.getTextboxText());
}, { serialize: false });
// Implement paste functionality with proper callback handling asynchronous operation
this.addWidget("button", "Paste", "Paste", () => {
navigator.clipboard.readText().then(text => {
this.inputEl.value = text;
}).catch(error => {
console.error('Failed to read clipboard contents:', error);
});
}, { serialize: false });
};
nodeType.prototype.onNodeCreated = function () {
this.populate();
// Bind the getTextboxText to this instance
this.getTextboxText = this.getTextboxText.bind(this);
console.log(this)
api.addEventListener('textbox', (event) => {
const data = event.detail
const outputText = this.getTextboxText();
if (this.id == data.id) {
api.fetchApi("/textbox_string", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(
{
node_id: data.id,
outputs: {
output: outputText
}
}
),
})
}
})
}
}
},
});