Added textbox with copy and paste functionality
This commit is contained in:
@@ -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"
|
||||
|
||||
@@ -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"})
|
||||
@@ -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'],)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
),
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user