Unverified Commit 7e436ba9 authored by pythongosssss's avatar pythongosssss Committed by GitHub
Browse files

Added handling of sockets

Started rework of UI elements
Added pnginfo handling
parent 2eaa6640
This diff is collapsed.
import { ComfyWidgets } from "./widgets.js"; import { ComfyWidgets } from "./widgets.js";
import { ComfyUI } from "./ui.js";
import { api } from "./api.js"; import { api } from "./api.js";
import { defaultGraph } from "./defaultGraph.js"; import { defaultGraph } from "./defaultGraph.js";
import { getPngMetadata } from "./pnginfo.js";
class ComfyDialog {
constructor() {
this.element = document.createElement("div");
this.element.classList.add("comfy-modal");
const content = document.createElement("div");
content.classList.add("comfy-modal-content");
this.textElement = document.createElement("p");
content.append(this.textElement);
const closeBtn = document.createElement("button");
closeBtn.type = "button";
closeBtn.textContent = "CLOSE";
content.append(closeBtn);
closeBtn.onclick = () => this.close();
this.element.append(content);
document.body.append(this.element);
}
close() {
this.element.style.display = "none";
}
show(html) {
this.textElement.innerHTML = html;
this.element.style.display = "flex";
}
}
class ComfyQueue {
constructor() {
this.element = document.createElement("div");
}
async update() {
if (this.element.style.display !== "none") {
await this.load();
}
}
async show() {
this.element.style.display = "block";
await this.load();
}
async load() {
const queue = await api.getQueue();
}
hide() {
this.element.style.display = "none";
}
}
class ComfyUI {
constructor(app) {
this.app = app;
this.menuContainer = document.createElement("div");
this.menuContainer.classList.add("comfy-menu");
document.body.append(this.menuContainer);
this.dialog = new ComfyDialog();
this.queue = new ComfyQueue();
}
}
class ComfyApp { class ComfyApp {
constructor() { constructor() {
...@@ -360,6 +294,103 @@ class ComfyApp { ...@@ -360,6 +294,103 @@ class ComfyApp {
}; };
} }
#addDropHandler() {
// Get prompt from dropped PNG or json
document.addEventListener("drop", async (event) => {
event.preventDefault();
event.stopPropagation();
const file = event.dataTransfer.files[0];
if (file.type === "image/png") {
const pngInfo = await getPngMetadata(file);
if (pngInfo && pngInfo.workflow) {
this.loadGraphData(JSON.parse(pngInfo.workflow));
}
} else if (file.type === "application/json" || file.name.endsWith(".json")) {
const reader = new FileReader();
reader.onload = () => {
this.loadGraphData(JSON.parse(reader.result));
};
reader.readAsText(file);
}
prompt_file_load(file);
});
}
#addDrawNodeProgressHandler() {
const orig = LGraphCanvas.prototype.drawNodeShape;
const self = this;
LGraphCanvas.prototype.drawNodeShape = function (node, ctx, size, fgcolor, bgcolor, selected, mouse_over) {
const res = orig.apply(this, arguments);
if (node.id + "" === self.runningNodeId) {
const shape = node._shape || node.constructor.shape || LiteGraph.ROUND_SHAPE;
ctx.lineWidth = 1;
ctx.globalAlpha = 0.8;
ctx.beginPath();
if (shape == LiteGraph.BOX_SHAPE)
ctx.rect(-6, -6 + LiteGraph.NODE_TITLE_HEIGHT, 12 + size[0] + 1, 12 + size[1] + LiteGraph.NODE_TITLE_HEIGHT);
else if (shape == LiteGraph.ROUND_SHAPE || (shape == LiteGraph.CARD_SHAPE && node.flags.collapsed))
ctx.roundRect(
-6,
-6 - LiteGraph.NODE_TITLE_HEIGHT,
12 + size[0] + 1,
12 + size[1] + LiteGraph.NODE_TITLE_HEIGHT,
this.round_radius * 2
);
else if (shape == LiteGraph.CARD_SHAPE)
ctx.roundRect(
-6,
-6 + LiteGraph.NODE_TITLE_HEIGHT,
12 + size[0] + 1,
12 + size[1] + LiteGraph.NODE_TITLE_HEIGHT,
this.round_radius * 2,
2
);
else if (shape == LiteGraph.CIRCLE_SHAPE)
ctx.arc(size[0] * 0.5, size[1] * 0.5, size[0] * 0.5 + 6, 0, Math.PI * 2);
ctx.strokeStyle = "#0f0";
ctx.stroke();
ctx.strokeStyle = fgcolor;
ctx.globalAlpha = 1;
if (self.progress) {
ctx.fillStyle = "green";
ctx.fillRect(0, 0, size[0] * (self.progress.value / self.progress.max), 6);
ctx.fillStyle = bgcolor;
}
}
return res;
};
}
#addApiUpdateHandlers() {
api.addEventListener("status", (status) => {
console.log(status);
});
api.addEventListener("reconnecting", () => {});
api.addEventListener("reconnected", () => {});
api.addEventListener("progress", ({ detail }) => {
this.progress = detail;
this.graph.setDirtyCanvas(true, false);
});
api.addEventListener("executing", ({ detail }) => {
this.progress = null;
this.runningNodeId = detail;
this.graph.setDirtyCanvas(true, false);
});
api.addEventListener("executed", (e) => {});
api.init();
}
/** /**
* Set up the app on the page * Set up the app on the page
*/ */
...@@ -406,6 +437,9 @@ class ComfyApp { ...@@ -406,6 +437,9 @@ class ComfyApp {
// Save current workflow automatically // Save current workflow automatically
setInterval(() => localStorage.setItem("workflow", JSON.stringify(this.graph.serialize())), 1000); setInterval(() => localStorage.setItem("workflow", JSON.stringify(this.graph.serialize())), 1000);
this.#addDrawNodeProgressHandler();
this.#addApiUpdateHandlers();
this.#addDropHandler();
await this.#invokeExtensionsAsync("setup"); await this.#invokeExtensionsAsync("setup");
} }
...@@ -561,6 +595,8 @@ class ComfyApp { ...@@ -561,6 +595,8 @@ class ComfyApp {
} }
} }
// TODO: check dynamic prompts here
this.canvas.draw(true, true); this.canvas.draw(true, true);
await this.ui.queue.update(); await this.ui.queue.update();
} }
......
export function getPngMetadata(file) {
return new Promise((r) => {
const reader = new FileReader();
reader.onload = (event) => {
// Get the PNG data as a Uint8Array
const pngData = new Uint8Array(event.target.result);
const dataView = new DataView(pngData.buffer);
// Check that the PNG signature is present
if (dataView.getUint32(0) !== 0x89504e47) {
console.error("Not a valid PNG file");
r();
return;
}
// Start searching for chunks after the PNG signature
let offset = 8;
let txt_chunks = {};
// Loop through the chunks in the PNG file
while (offset < pngData.length) {
// Get the length of the chunk
const length = dataView.getUint32(offset);
// Get the chunk type
const type = String.fromCharCode(...pngData.slice(offset + 4, offset + 8));
if (type === "tEXt") {
// Get the keyword
let keyword_end = offset + 8;
while (pngData[keyword_end] !== 0) {
keyword_end++;
}
const keyword = String.fromCharCode(...pngData.slice(offset + 8, keyword_end));
// Get the text
const text = String.fromCharCode(...pngData.slice(keyword_end + 1, offset + 8 + length));
txt_chunks[keyword] = text;
}
offset += 12 + length;
}
r(txt_chunks);
};
reader.readAsArrayBuffer(file);
});
}
import { api } from "./api.js";
class ComfyDialog {
constructor() {
this.element = document.createElement("div");
this.element.classList.add("comfy-modal");
const content = document.createElement("div");
content.classList.add("comfy-modal-content");
this.textElement = document.createElement("p");
content.append(this.textElement);
const closeBtn = document.createElement("button");
closeBtn.type = "button";
closeBtn.textContent = "CLOSE";
content.append(closeBtn);
closeBtn.onclick = () => this.close();
this.element.append(content);
document.body.append(this.element);
}
close() {
this.element.style.display = "none";
}
show(html) {
this.textElement.innerHTML = html;
this.element.style.display = "flex";
}
}
class ComfyList {
constructor() {
this.element = document.createElement("div");
this.element.style.display = "none";
this.element.textContent = "hello";
}
get visible() {
return this.element.style.display !== "none";
}
async load() {
// const queue = await api.getQueue();
}
async update() {
if (this.visible) {
await this.load();
}
}
async show() {
this.element.style.display = "block";
await this.load();
}
hide() {
this.element.style.display = "none";
}
toggle() {
if (this.visible) {
this.hide();
return false;
} else {
this.show();
return true;
}
}
}
export class ComfyUI {
constructor(app) {
this.app = app;
this.dialog = new ComfyDialog();
this.queue = new ComfyList();
this.history = new ComfyList();
this.menuContainer = document.createElement("div");
this.menuContainer.classList.add("comfy-menu");
this.queueSize = document.createElement("span");
this.menuContainer.append(this.queueSize);
this.addAction("Queue Prompt", () => {
app.queuePrompt(0);
}, "queue");
this.btnContainer = document.createElement("div");
this.btnContainer.classList.add("comfy-menu-btns");
this.menuContainer.append(this.btnContainer);
this.addAction(
"Queue Front",
() => {
app.queuePrompt(-1);
},
"sm"
);
this.addAction(
"See Queue",
(btn) => {
btn.textContent = this.queue.toggle() ? "Close" : "See Queue";
},
"sm"
);
this.addAction(
"See History",
(btn) => {
btn.textContent = this.history.toggle() ? "Close" : "See History";
},
"sm"
);
this.menuContainer.append(this.queue.element);
this.menuContainer.append(this.history.element);
this.addAction("Save", () => {
app.queuePrompt(-1);
});
this.addAction("Load", () => {
app.queuePrompt(-1);
});
this.addAction("Clear", () => {
app.queuePrompt(-1);
});
this.addAction("Load Default", () => {
app.queuePrompt(-1);
});
document.body.append(this.menuContainer);
this.setStatus({ exec_info: { queue_remaining: "X" } });
}
addAction(text, cb, cls) {
const btn = document.createElement("button");
btn.classList.add("comfy-menu-btn-" + (cls || "lg"));
btn.textContent = text;
btn.onclick = () => {
cb(btn);
};
(cls === "sm" ? this.btnContainer : this.menuContainer).append(btn);
}
setStatus(status) {
this.queueSize.textContent = "Queue size: " + (status ? status.exec_info.queue_remaining : "ERR");
}
}
...@@ -44,7 +44,6 @@ function addMultilineWidget(node, name, defaultVal, dynamicPrompt, app) { ...@@ -44,7 +44,6 @@ function addMultilineWidget(node, name, defaultVal, dynamicPrompt, app) {
const visible = app.canvas.ds.scale > 0.5; const visible = app.canvas.ds.scale > 0.5;
const t = ctx.getTransform(); const t = ctx.getTransform();
const margin = 10; const margin = 10;
console.log("back you go")
Object.assign(this.inputEl.style, { Object.assign(this.inputEl.style, {
left: `${t.a * margin + t.e}px`, left: `${t.a * margin + t.e}px`,
top: `${t.d * (y + widgetHeight - margin) + t.f}px`, top: `${t.d * (y + widgetHeight - margin) + t.f}px`,
......
...@@ -64,6 +64,38 @@ body { ...@@ -64,6 +64,38 @@ body {
cursor: pointer; cursor: pointer;
} }
.comfy-menu {
width: 200px;
font-size: 15px;
position: absolute;
top: 50%;
right: 0%;
background-color: white;
text-align: center;
z-index: 100;
width: 170px;
display: flex;
flex-direction: column;
align-items: center;
}
.comfy-menu-btns {
margin-bottom: 10px;
}
.comfy-menu-btn-sm {
font-size: 10px;
width: 50%;
}
.comfy-menu-btn-lg, .comfy-menu-btn-queue {
font-size: 20px;
}
.comfy-menu-btn-queue {
width: 100%;
}
@media (prefers-color-scheme: dark) { @media (prefers-color-scheme: dark) {
body { body {
background-color: #202020; background-color: #202020;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment