Merge branch 'dragdrop-image-upload' of https://github.com/pythongosssss/ComfyUI into m1
This commit is contained in:
commit
ef71d2c281
|
@ -291,9 +291,47 @@ class ComfyApp {
|
|||
document.addEventListener("drop", async (event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
const file = event.dataTransfer.files[0];
|
||||
await this.handleFile(file);
|
||||
|
||||
const n = this.dragOverNode;
|
||||
this.dragOverNode = null;
|
||||
// Node handles file drop, we dont use the built in onDropFile handler as its buggy
|
||||
// If you drag multiple files it will call it multiple times with the same file
|
||||
if (n && n.onDragDrop && (await n.onDragDrop(event))) {
|
||||
return;
|
||||
}
|
||||
|
||||
await this.handleFile(event.dataTransfer.files[0]);
|
||||
});
|
||||
|
||||
// Always clear over node on drag leave
|
||||
this.canvasEl.addEventListener("dragleave", async () => {
|
||||
if (this.dragOverNode) {
|
||||
this.dragOverNode = null;
|
||||
this.graph.setDirtyCanvas(false, true);
|
||||
}
|
||||
});
|
||||
|
||||
// Add handler for dropping onto a specific node
|
||||
this.canvasEl.addEventListener(
|
||||
"dragover",
|
||||
(e) => {
|
||||
this.canvas.adjustMouseEvent(e);
|
||||
const node = this.graph.getNodeOnPos(e.canvasX, e.canvasY);
|
||||
if (node) {
|
||||
if (node.onDragOver && node.onDragOver(e)) {
|
||||
this.dragOverNode = node;
|
||||
|
||||
// dragover event is fired very frequently, run this on an animation frame
|
||||
requestAnimationFrame(() => {
|
||||
this.graph.setDirtyCanvas(false, true);
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.dragOverNode = null;
|
||||
},
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -321,15 +359,22 @@ class ComfyApp {
|
|||
}
|
||||
|
||||
/**
|
||||
* Draws currently executing node highlight and progress bar
|
||||
* Draws node highlights (executing, drag drop) and progress bar
|
||||
*/
|
||||
#addDrawNodeProgressHandler() {
|
||||
#addDrawNodeHandler() {
|
||||
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) {
|
||||
let color = null;
|
||||
if (node.id === +self.runningNodeId) {
|
||||
color = "#0f0";
|
||||
} else if (self.dragOverNode && node.id === self.dragOverNode.id) {
|
||||
color = "dodgerblue";
|
||||
}
|
||||
|
||||
if (color) {
|
||||
const shape = node._shape || node.constructor.shape || LiteGraph.ROUND_SHAPE;
|
||||
ctx.lineWidth = 1;
|
||||
ctx.globalAlpha = 0.8;
|
||||
|
@ -355,7 +400,7 @@ class ComfyApp {
|
|||
);
|
||||
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.strokeStyle = color;
|
||||
ctx.stroke();
|
||||
ctx.strokeStyle = fgcolor;
|
||||
ctx.globalAlpha = 1;
|
||||
|
@ -435,7 +480,7 @@ class ComfyApp {
|
|||
await this.#loadExtensions();
|
||||
|
||||
// Create and mount the LiteGraph in the DOM
|
||||
const canvasEl = Object.assign(document.createElement("canvas"), { id: "graph-canvas" });
|
||||
const canvasEl = (this.canvasEl = Object.assign(document.createElement("canvas"), { id: "graph-canvas" }));
|
||||
document.body.prepend(canvasEl);
|
||||
|
||||
this.graph = new LGraph();
|
||||
|
@ -476,7 +521,7 @@ class ComfyApp {
|
|||
// Save current workflow automatically
|
||||
setInterval(() => localStorage.setItem("workflow", JSON.stringify(this.graph.serialize())), 1000);
|
||||
|
||||
this.#addDrawNodeProgressHandler();
|
||||
this.#addDrawNodeHandler();
|
||||
this.#addApiUpdateHandlers();
|
||||
this.#addDropHandler();
|
||||
this.#addPasteHandler();
|
||||
|
|
|
@ -132,7 +132,7 @@ export const ComfyWidgets = {
|
|||
|
||||
function showImage(name) {
|
||||
// Position the image somewhere sensible
|
||||
if(!node.imageOffset) {
|
||||
if (!node.imageOffset) {
|
||||
node.imageOffset = uploadWidget.last_y ? uploadWidget.last_y + 25 : 75;
|
||||
}
|
||||
|
||||
|
@ -162,6 +162,36 @@ export const ComfyWidgets = {
|
|||
}
|
||||
});
|
||||
|
||||
async function uploadFile(file, updateNode) {
|
||||
try {
|
||||
// Wrap file in formdata so it includes filename
|
||||
const body = new FormData();
|
||||
body.append("image", file);
|
||||
const resp = await fetch("/upload/image", {
|
||||
method: "POST",
|
||||
body,
|
||||
});
|
||||
|
||||
if (resp.status === 200) {
|
||||
const data = await resp.json();
|
||||
// Add the file as an option and update the widget value
|
||||
if (!imageWidget.options.values.includes(data.name)) {
|
||||
imageWidget.options.values.push(data.name);
|
||||
}
|
||||
|
||||
if (updateNode) {
|
||||
showImage(data.name);
|
||||
|
||||
imageWidget.value = data.name;
|
||||
}
|
||||
} else {
|
||||
alert(resp.status + " - " + resp.statusText);
|
||||
}
|
||||
} catch (error) {
|
||||
alert(error);
|
||||
}
|
||||
}
|
||||
|
||||
const fileInput = document.createElement("input");
|
||||
Object.assign(fileInput, {
|
||||
type: "file",
|
||||
|
@ -169,30 +199,7 @@ export const ComfyWidgets = {
|
|||
style: "display: none",
|
||||
onchange: async () => {
|
||||
if (fileInput.files.length) {
|
||||
try {
|
||||
// Wrap file in formdata so it includes filename
|
||||
const body = new FormData();
|
||||
body.append("image", fileInput.files[0]);
|
||||
const resp = await fetch("/upload/image", {
|
||||
method: "POST",
|
||||
body,
|
||||
});
|
||||
|
||||
if (resp.status === 200) {
|
||||
const data = await resp.json();
|
||||
showImage(data.name);
|
||||
|
||||
// Add the file as an option and update the widget value
|
||||
if (!imageWidget.options.values.includes(data.name)) {
|
||||
imageWidget.options.values.push(data.name);
|
||||
}
|
||||
imageWidget.value = data.name;
|
||||
} else {
|
||||
alert(resp.status + " - " + resp.statusText);
|
||||
}
|
||||
} catch (error) {
|
||||
alert(error);
|
||||
}
|
||||
await uploadFile(fileInput.files[0], true);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
@ -204,6 +211,30 @@ export const ComfyWidgets = {
|
|||
});
|
||||
uploadWidget.serialize = false;
|
||||
|
||||
// Add handler to check if an image is being dragged over our node
|
||||
node.onDragOver = function (e) {
|
||||
if (e.dataTransfer && e.dataTransfer.items) {
|
||||
const image = [...e.dataTransfer.items].find((f) => f.kind === "file" && f.type.startsWith("image/"));
|
||||
return !!image;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
// On drop upload files
|
||||
node.onDragDrop = function (e) {
|
||||
console.log("onDragDrop called");
|
||||
let handled = false;
|
||||
for (const file of e.dataTransfer.files) {
|
||||
if (file.type.startsWith("image/")) {
|
||||
uploadFile(file, !handled); // Dont await these, any order is fine, only update on first one
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
return handled;
|
||||
};
|
||||
|
||||
return { widget: uploadWidget };
|
||||
},
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue