|
|
|
@ -269,6 +269,71 @@ export class ComfyApp {
|
|
|
|
|
* @param {*} node The node to add the menu handler |
|
|
|
|
*/ |
|
|
|
|
#addNodeContextMenuHandler(node) { |
|
|
|
|
function getCopyImageOption(img) { |
|
|
|
|
if (typeof window.ClipboardItem === "undefined") return []; |
|
|
|
|
return [ |
|
|
|
|
{ |
|
|
|
|
content: "Copy Image", |
|
|
|
|
callback: async () => { |
|
|
|
|
const url = new URL(img.src); |
|
|
|
|
url.searchParams.delete("preview"); |
|
|
|
|
|
|
|
|
|
const writeImage = async (blob) => { |
|
|
|
|
await navigator.clipboard.write([ |
|
|
|
|
new ClipboardItem({ |
|
|
|
|
[blob.type]: blob, |
|
|
|
|
}), |
|
|
|
|
]); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
try { |
|
|
|
|
const data = await fetch(url); |
|
|
|
|
const blob = await data.blob(); |
|
|
|
|
try { |
|
|
|
|
await writeImage(blob); |
|
|
|
|
} catch (error) { |
|
|
|
|
// Chrome seems to only support PNG on write, convert and try again
|
|
|
|
|
if (blob.type !== "image/png") { |
|
|
|
|
const canvas = $el("canvas", { |
|
|
|
|
width: img.naturalWidth, |
|
|
|
|
height: img.naturalHeight, |
|
|
|
|
}); |
|
|
|
|
const ctx = canvas.getContext("2d"); |
|
|
|
|
let image; |
|
|
|
|
if (typeof window.createImageBitmap === "undefined") { |
|
|
|
|
image = new Image(); |
|
|
|
|
const p = new Promise((resolve, reject) => { |
|
|
|
|
image.onload = resolve; |
|
|
|
|
image.onerror = reject; |
|
|
|
|
}).finally(() => { |
|
|
|
|
URL.revokeObjectURL(image.src); |
|
|
|
|
}); |
|
|
|
|
image.src = URL.createObjectURL(blob); |
|
|
|
|
await p; |
|
|
|
|
} else { |
|
|
|
|
image = await createImageBitmap(blob); |
|
|
|
|
} |
|
|
|
|
try { |
|
|
|
|
ctx.drawImage(image, 0, 0); |
|
|
|
|
canvas.toBlob(writeImage, "image/png"); |
|
|
|
|
} finally { |
|
|
|
|
if (typeof image.close === "function") { |
|
|
|
|
image.close(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
throw error; |
|
|
|
|
} |
|
|
|
|
} catch (error) { |
|
|
|
|
alert("Error copying image: " + (error.message ?? error)); |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
}, |
|
|
|
|
]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
node.prototype.getExtraMenuOptions = function (_, options) { |
|
|
|
|
if (this.imgs) { |
|
|
|
|
// If this node has images then we add an open in new tab item
|
|
|
|
@ -286,16 +351,17 @@ export class ComfyApp {
|
|
|
|
|
content: "Open Image", |
|
|
|
|
callback: () => { |
|
|
|
|
let url = new URL(img.src); |
|
|
|
|
url.searchParams.delete('preview'); |
|
|
|
|
window.open(url, "_blank") |
|
|
|
|
url.searchParams.delete("preview"); |
|
|
|
|
window.open(url, "_blank"); |
|
|
|
|
}, |
|
|
|
|
}, |
|
|
|
|
...getCopyImageOption(img),
|
|
|
|
|
{ |
|
|
|
|
content: "Save Image", |
|
|
|
|
callback: () => { |
|
|
|
|
const a = document.createElement("a"); |
|
|
|
|
let url = new URL(img.src); |
|
|
|
|
url.searchParams.delete('preview'); |
|
|
|
|
url.searchParams.delete("preview"); |
|
|
|
|
a.href = url; |
|
|
|
|
a.setAttribute("download", new URLSearchParams(url.search).get("filename")); |
|
|
|
|
document.body.append(a); |
|
|
|
@ -308,33 +374,41 @@ export class ComfyApp {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
options.push({ |
|
|
|
|
content: "Bypass", |
|
|
|
|
callback: (obj) => { if (this.mode === 4) this.mode = 0; else this.mode = 4; this.graph.change(); } |
|
|
|
|
}); |
|
|
|
|
content: "Bypass", |
|
|
|
|
callback: (obj) => { |
|
|
|
|
if (this.mode === 4) this.mode = 0; |
|
|
|
|
else this.mode = 4; |
|
|
|
|
this.graph.change(); |
|
|
|
|
}, |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
// prevent conflict of clipspace content
|
|
|
|
|
if(!ComfyApp.clipspace_return_node) { |
|
|
|
|
if (!ComfyApp.clipspace_return_node) { |
|
|
|
|
options.push({ |
|
|
|
|
content: "Copy (Clipspace)", |
|
|
|
|
callback: (obj) => { ComfyApp.copyToClipspace(this); } |
|
|
|
|
}); |
|
|
|
|
content: "Copy (Clipspace)", |
|
|
|
|
callback: (obj) => { |
|
|
|
|
ComfyApp.copyToClipspace(this); |
|
|
|
|
}, |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
if(ComfyApp.clipspace != null) { |
|
|
|
|
if (ComfyApp.clipspace != null) { |
|
|
|
|
options.push({ |
|
|
|
|
content: "Paste (Clipspace)", |
|
|
|
|
callback: () => { ComfyApp.pasteFromClipspace(this); } |
|
|
|
|
}); |
|
|
|
|
content: "Paste (Clipspace)", |
|
|
|
|
callback: () => { |
|
|
|
|
ComfyApp.pasteFromClipspace(this); |
|
|
|
|
}, |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if(ComfyApp.isImageNode(this)) { |
|
|
|
|
if (ComfyApp.isImageNode(this)) { |
|
|
|
|
options.push({ |
|
|
|
|
content: "Open in MaskEditor", |
|
|
|
|
callback: (obj) => { |
|
|
|
|
ComfyApp.copyToClipspace(this); |
|
|
|
|
ComfyApp.clipspace_return_node = this; |
|
|
|
|
ComfyApp.open_maskeditor(); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
content: "Open in MaskEditor", |
|
|
|
|
callback: (obj) => { |
|
|
|
|
ComfyApp.copyToClipspace(this); |
|
|
|
|
ComfyApp.clipspace_return_node = this; |
|
|
|
|
ComfyApp.open_maskeditor(); |
|
|
|
|
}, |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|