Files
filliptm-ComfyUI_Fill-Nodes/web/PhotoPea.js
T
2024-08-06 23:44:53 -07:00

228 lines
6.1 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { app } from "../../scripts/app.js";
import { api } from "../../scripts/api.js";
import { $el } from "../../scripts/ui.js";
import { ComfyApp } from "../../scripts/app.js";
class LJPhotopeaEditorDialog {
static instance = null;
static getInstance() {
if(!LJPhotopeaEditorDialog.instance) {
LJPhotopeaEditorDialog.instance = new LJPhotopeaEditorDialog();
}
return LJPhotopeaEditorDialog.instance;
}
constructor() {
this.element = $el("div.photopea-editor", {
style: {
position: "fixed",
top: "0",
left: "0",
width: "100vw",
height: "100vh",
backgroundColor: "rgba(50, 0, 80, 0.8)",
display: "none",
zIndex: "9999"
}
}, [
this.createCloseButton(),
this.createUIContainer(),
]);
document.body.appendChild(this.element);
this.addKeyboardListener();
}
createCloseButton() {
return $el("button.close-button", {
textContent: "×",
onclick: () => this.hide(),
style: {
position: "absolute",
top: "10px",
right: "10px",
fontSize: "24px",
background: "none",
border: "none",
color: "white",
cursor: "pointer",
zIndex: "10000"
}
});
}
createUIContainer() {
this.uiContainer = $el("div.ui-container", {
style: {
position: "relative",
width: "100%",
height: "100%",
overflow: "hidden"
}
});
return this.uiContainer;
}
addKeyboardListener() {
document.addEventListener("keydown", (e) => {
if (e.key === "Escape" && this.element.style.display !== "none") {
this.hide();
}
});
}
show() {
this.element.style.display = "block";
this.createIframe();
}
hide() {
this.element.style.display = "none";
if (this.iframe) {
this.uiContainer.removeChild(this.iframe);
this.iframe = null;
}
}
createIframe() {
this.iframe = $el("iframe", {
src: `https://www.photopea.com/`,
style: {
width: "100%",
height: "100%",
border: "none",
},
});
this.uiContainer.appendChild(this.iframe);
this.iframe.onload = () => {
const target_image_path = ComfyApp.clipspace.imgs[ComfyApp.clipspace['selectedIndex']].src;
this.imageToBase64(target_image_path, (dataURL) => {
this.postMessageToPhotopea(`app.open("${dataURL}", null, false);`, "*");
});
};
}
async save() {
const saveMessage = 'app.activeDocument.saveToOE("png");';
const [payload, done] = await this.postMessageToPhotopea(saveMessage);
const file = new Blob([payload], { type: "image/png" });
const body = new FormData();
const filename = "clipspace-photopea-" + performance.now() + ".png";
if(ComfyApp.clipspace.widgets) {
const index = ComfyApp.clipspace.widgets.findIndex(obj => obj.name === 'image');
if(index >= 0)
ComfyApp.clipspace.widgets[index].value = `photopea/${filename} [input]`;
}
body.append("image", file, filename);
body.append("subfolder", "photopea");
await this.uploadFile(body);
ComfyApp.onClipspaceEditorSave();
this.hide();
}
async postMessageToPhotopea(message) {
var request = new Promise(function (resolve, reject) {
var responses = [];
var photopeaMessageHandle = function (response) {
responses.push(response.data);
if (response.data == "done") {
window.removeEventListener("message", photopeaMessageHandle);
resolve(responses)
}
};
window.addEventListener("message", photopeaMessageHandle);
});
this.iframe.contentWindow.postMessage(message, "*");
return await request;
}
imageToBase64(url, callback) {
fetch(url)
.then((response) => response.blob())
.then((blob) => {
const reader = new FileReader();
reader.readAsDataURL(blob);
reader.onloadend = () => {
const base64String = reader.result;
callback(base64String);
};
});
}
async uploadFile(formData) {
try {
const resp = await api.fetchApi('/upload/image', {
method: 'POST',
body: formData
})
if (resp.status === 200) {
const data = await resp.json();
ComfyApp.clipspace.imgs[ComfyApp.clipspace['selectedIndex']] = new Image();
ComfyApp.clipspace.imgs[ComfyApp.clipspace['selectedIndex']].src = `view?filename=${data.name}&subfolder=${data.subfolder}&type=${data.type}`;
} else {
alert(resp.status + " - " + resp.statusText);
}
} catch (error) {
console.error('Error:', error);
}
}
}
function addMenuHandler(nodeType, cb) {
const getOpts = nodeType.prototype.getExtraMenuOptions;
nodeType.prototype.getExtraMenuOptions = function () {
const r = getOpts.apply(this, arguments);
cb.apply(this, arguments);
return r;
};
}
app.registerExtension({
name: "Comfy.LJ.PhotopeaEditor",
async beforeRegisterNodeDef(nodeType, nodeData, app) {
if (Array.isArray(nodeData.output) && (nodeData.output.includes("MASK") || nodeData.output.includes("IMAGE"))) {
addMenuHandler(nodeType, function (_, options) {
options.unshift({
content: "FL PhotoPea",
callback: () => {
ComfyApp.copyToClipspace(this);
ComfyApp.clipspace_return_node = this;
let dlg = LJPhotopeaEditorDialog.getInstance();
dlg.show();
},
});
});
}
},
async setup() {
const photopeaEditor = LJPhotopeaEditorDialog.getInstance();
// Add save button
const saveButton = $el("button", {
textContent: "Save",
onclick: () => photopeaEditor.save(),
style: {
position: "absolute",
bottom: "10px",
right: "10px",
zIndex: "10001",
padding: "5px 15px",
fontSize: "14px",
backgroundColor: "#8a2be2",
color: "white",
border: "none",
borderRadius: "5px",
cursor: "pointer",
}
});
photopeaEditor.element.appendChild(saveButton);
}
});