diff --git a/js/comfyui-manager.js b/js/comfyui-manager.js index fb10121f..d37bd771 100644 --- a/js/comfyui-manager.js +++ b/js/comfyui-manager.js @@ -2,6 +2,7 @@ import { app } from "../../scripts/app.js"; import { api } from "../../scripts/api.js" import { ComfyDialog, $el } from "../../scripts/ui.js"; import { ComfyWidgets } from "../../scripts/widgets.js"; +import { ShareDialog } from "./comfyui-share.js"; var update_comfyui_button = null; var fetch_updates_button = null; @@ -1986,395 +1987,6 @@ class ManagerMenuDialog extends ComfyDialog { } } -class ShareDialog extends ComfyDialog { - static instance = null; - static matrix_auth = { homeserver: "matrix.org", username: "", password: "" }; - static cw_sharekey = ""; - - constructor() { - super(); - - this.element = $el("div.comfy-modal", { parent: document.body }, - [$el("div.comfy-modal-content", - { - style: { - overflowY: "auto", - } - }, - [...this.createButtons()]), - ]); - } - - createButtons() { - this.is_nsfw_checkbox = $el("input", { type: 'checkbox', id: "is_nsfw" }, []) - const is_nsfw_checkbox_text = $el("label", {}, [" Is this NSFW?"]) - this.is_nsfw_checkbox.style.color = "var(--fg-color)"; - this.is_nsfw_checkbox.checked = false; - - this.matrix_destination_checkbox = $el("input", { type: 'checkbox', id: "matrix_destination" }, []) - const matrix_destination_checkbox_text = $el("label", {}, [" ComfyUI Matrix server"]) - this.matrix_destination_checkbox.style.color = "var(--fg-color)"; - this.matrix_destination_checkbox.checked = true; - - this.comfyworkflows_destination_checkbox = $el("input", { type: 'checkbox', id: "comfyworkflows_destination" }, []) - const comfyworkflows_destination_checkbox_text = $el("label", {}, [" ComfyWorkflows.com"]) - this.comfyworkflows_destination_checkbox.style.color = "var(--fg-color)"; - this.comfyworkflows_destination_checkbox.checked = true; - - this.matrix_homeserver_input = $el("input", { type: 'text', id: "matrix_homeserver", placeholder: "matrix.org", value: ShareDialog.matrix_auth.homeserver || 'matrix.org' }, []); - this.matrix_username_input = $el("input", { type: 'text', placeholder: "Username", value: ShareDialog.matrix_auth.username || '' }, []); - this.matrix_password_input = $el("input", { type: 'password', placeholder: "Password", value: ShareDialog.matrix_auth.password || '' }, []); - - this.cw_sharekey_input = $el("input", { type: 'text', placeholder: "Share key (found on your profile page)", value: ShareDialog.cw_sharekey || '' }, []); - this.cw_sharekey_input.style.width = "100%"; - - this.credits_input = $el("input", { - type: "text", - placeholder: "This will be used to give credits", - required: false, - }, []); - - this.title_input = $el("input", { - type: "text", - placeholder: "ex: My awesome art", - required: false, - }, []); - - this.description_input = $el("textarea", { - placeholder: "ex: Trying out a new workflow... ", - required: false, - }, []); - - this.share_button = $el("button", { - type: "button", - textContent: "Share", - }, []); - - this.final_message = $el("div", {}, []); - - // get the user's existing matrix auth and share key - ShareDialog.matrix_auth = { homeserver: "matrix.org", username: "", password: "" }; - try { - api.fetchApi(`/manager/get_matrix_auth`) - .then(response => response.json()) - .then(data => { - ShareDialog.matrix_auth = data; - this.matrix_homeserver_input.value = ShareDialog.matrix_auth.homeserver; - this.matrix_username_input.value = ShareDialog.matrix_auth.username; - this.matrix_password_input.value = ShareDialog.matrix_auth.password; - }) - .catch(error => { - // console.log(error); - }); - } catch (error) { - // console.log(error); - } - - // get the user's existing comfyworkflows share key - ShareDialog.cw_sharekey = ""; - try { - console.log("Fetching comfyworkflows share key") - api.fetchApi(`/manager/get_comfyworkflows_auth`) - .then(response => response.json()) - .then(data => { - ShareDialog.cw_sharekey = data.comfyworkflows_sharekey; - this.cw_sharekey_input.value = ShareDialog.cw_sharekey; - }) - .catch(error => { - // console.log(error); - }); - } catch (error) { - // console.log(error); - } - - this.share_button.onclick = async () => { - const prompt = await app.graphToPrompt(); - const nodes = app.graph._nodes; - - const destinations = []; - if (this.matrix_destination_checkbox.checked) { - destinations.push("matrix"); - } - if (this.comfyworkflows_destination_checkbox.checked) { - destinations.push("comfyworkflows"); - } - - // if destinations includes matrix, make an api call to /manager/check_matrix to ensure that the user has configured their matrix settings - if (destinations.includes("matrix")) { - let definedMatrixAuth = !!this.matrix_homeserver_input.value && !!this.matrix_username_input.value && !!this.matrix_password_input.value; - if (!definedMatrixAuth) { - alert("Please set your Matrix account details."); - return; - } - } - - if (destinations.includes("comfyworkflows") && !this.cw_sharekey_input.value && !confirm("You have NOT set your ComfyWorkflows.com share key. Your art will NOT be connected to your account (it will be shared anonymously). Continue?")) { - return; - } - - const potential_outputs = []; - const potential_output_nodes = []; - - // iterate over the array of nodes to find the ones that are marked as SaveImage - // TODO: Add support for AnimateDiffCombine, etc. nodes that save videos/gifs, etc. - for (let i = 0; i < nodes.length; i++) { - const node = nodes[i]; - if (node.type !== "SaveImage") { - continue; - } - - if (node.type === "SaveImage") { - potential_output_nodes.push(node); - - // check if node has an 'images' array property - if (node.hasOwnProperty("images") && Array.isArray(node.images)) { - // iterate over the images array and add each image to the potential_outputs array - for (let j = 0; j < node.images.length; j++) { - potential_outputs.push({ "type": "image", "image": node.images[j] }); - } - } - } - } - - if (potential_outputs.length === 0) { - if (potential_output_nodes.length === 0) { - // todo: add support for other output node types (animatediff combine, etc.) - alert("No SaveImage node found. To share this workflow, please run a SaveImage node to your graph and re-run your prompt."); - } else { - alert("To share this, first run a prompt. Once it's done, click 'Share'."); - } - this.close(); - return; - } - - // Change the text of the share button to "Sharing..." to indicate that the share process has started - this.share_button.textContent = "Sharing..."; - - const response = await api.fetchApi(`/manager/share`, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ - matrix_auth: { - homeserver: this.matrix_homeserver_input.value, - username: this.matrix_username_input.value, - password: this.matrix_password_input.value, - }, - cw_auth: { - cw_sharekey: this.cw_sharekey_input.value, - }, - share_destinations: destinations, - credits: this.credits_input.value, - title: this.title_input.value, - description: this.description_input.value, - is_nsfw: this.is_nsfw_checkbox.checked, - prompt, - potential_outputs, - // potential_output_nodes - }) - }); - - if (response.status != 200) { - try { - const response_json = await response.json(); - if (response_json.error) { - alert(response_json.error); - this.close(); - return; - } else { - alert("Failed to share your art. Please try again."); - this.close(); - return; - } - } catch (e) { - alert("Failed to share your art. Please try again."); - this.close(); - return; - } - } - - const response_json = await response.json(); - - if (response_json.comfyworkflows.url) { - this.final_message.innerHTML = "Your art has been shared: " + response_json.comfyworkflows.url + ""; - if (response_json.matrix.success) { - this.final_message.innerHTML += "
Your art has been shared in the ComfyUI Matrix server's #share channel!"; - } - } else { - if (response_json.matrix.success) { - this.final_message.innerHTML = "Your art has been shared in the ComfyUI Matrix server's #share channel!"; - } - } - - this.final_message.style.color = "green"; - - // hide the share button - this.share_button.textContent = "Shared!"; - this.share_button.style.display = "none"; - // this.close(); - } - - const res = - [ - $el("tr.td", { width: "100%" }, [ - $el("font", { size: 6, color: "white" }, [`Share your art`]), - ]), - $el("br", {}, []), - - $el("details", { - style: { - border: "1px solid #999", - padding: "5px", - borderRadius: "5px", - backgroundColor: "#222" - } - }, [ - $el("summary", { - style: { - color: "white", - cursor: "pointer", - } - }, [`Matrix account`]), - $el("div", { - style: { - display: "flex", - flexDirection: "row", - } - }, [ - $el("div", { - textContent: "Homeserver", - style: { - marginRight: "10px", - } - }, []), - this.matrix_homeserver_input, - ]), - - $el("div", { - style: { - display: "flex", - flexDirection: "row", - } - }, [ - $el("div", { - textContent: "Username", - style: { - marginRight: "10px", - } - }, []), - this.matrix_username_input, - ]), - - $el("div", { - style: { - display: "flex", - flexDirection: "row", - } - }, [ - $el("div", { - textContent: "Password", - style: { - marginRight: "10px", - } - }, []), - this.matrix_password_input, - ]), - - ]), - $el("details", { - style: { - border: "1px solid #999", - marginTop: "10px", - padding: "5px", - borderRadius: "5px", - backgroundColor: "#222" - } - }, [ - $el("summary", { - style: { - color: "white", - cursor: "pointer", - } - }, [`Comfyworkflows.com account`]), - $el("h4", { - textContent: "Share key (found on your profile page)", - }, []), - $el("p", { size: 3, color: "white" }, ["When provided, your art will be saved to your account."]), - this.cw_sharekey_input, - ]), - - $el("div", {}, [ - $el("p", { size: 3, color: "white" }, [`Select where to share your art:`]), - this.matrix_destination_checkbox, - matrix_destination_checkbox_text, - $el("br", {}, []), - this.comfyworkflows_destination_checkbox, - comfyworkflows_destination_checkbox_text, - ]), - - $el("h4", { - textContent: "Credits (optional)", - size: 3, - color: "white" - }, []), - this.credits_input, - // $el("br", {}, []), - - $el("h4", { - textContent: "Title (optional)", - size: 3, - color: "white" - }, []), - this.title_input, - // $el("br", {}, []), - - $el("h4", { - textContent: "Description (optional)", - size: 3, - color: "white" - }, []), - this.description_input, - $el("br", {}, []), - - $el("div", {}, [this.is_nsfw_checkbox, is_nsfw_checkbox_text]), - this.final_message, - - $el("br", {}, []), - this.share_button, - - $el("button", { - type: "button", - textContent: "Close", - onclick: () => { - // Reset state - this.matrix_destination_checkbox.checked = true; - this.comfyworkflows_destination_checkbox.checked = true; - this.share_button.textContent = "Share"; - this.share_button.style.display = "inline-block"; - this.final_message.innerHTML = ""; - this.final_message.style.color = "white"; - this.credits_input.value = ""; - this.title_input.value = ""; - this.description_input.value = ""; - this.is_nsfw_checkbox.checked = false; - this.close() - } - }), - $el("br", {}, []), - ]; - - res[0].style.padding = "10px 10px 10px 10px"; - res[0].style.backgroundColor = "black"; //"linear-gradient(90deg, #00C9FF 0%, #92FE9D 100%)"; - res[0].style.textAlign = "center"; - res[0].style.height = "45px"; - return res; - } - - show() { - this.element.style.display = "block"; - } -} - - app.registerExtension({ name: "Comfy.ManagerMenu", diff --git a/js/comfyui-share.js b/js/comfyui-share.js new file mode 100644 index 00000000..81892891 --- /dev/null +++ b/js/comfyui-share.js @@ -0,0 +1,391 @@ +import { app } from "../../scripts/app.js"; +import { api } from "../../scripts/api.js" +import { ComfyDialog, $el } from "../../scripts/ui.js"; + +export class ShareDialog extends ComfyDialog { + static instance = null; + static matrix_auth = { homeserver: "matrix.org", username: "", password: "" }; + static cw_sharekey = ""; + + constructor() { + super(); + + this.element = $el("div.comfy-modal", { parent: document.body }, + [$el("div.comfy-modal-content", + { + style: { + overflowY: "auto", + } + }, + [...this.createButtons()]), + ]); + } + + createButtons() { + this.is_nsfw_checkbox = $el("input", { type: 'checkbox', id: "is_nsfw" }, []) + const is_nsfw_checkbox_text = $el("label", {}, [" Is this NSFW?"]) + this.is_nsfw_checkbox.style.color = "var(--fg-color)"; + this.is_nsfw_checkbox.checked = false; + + this.matrix_destination_checkbox = $el("input", { type: 'checkbox', id: "matrix_destination" }, []) + const matrix_destination_checkbox_text = $el("label", {}, [" ComfyUI Matrix server"]) + this.matrix_destination_checkbox.style.color = "var(--fg-color)"; + this.matrix_destination_checkbox.checked = true; + + this.comfyworkflows_destination_checkbox = $el("input", { type: 'checkbox', id: "comfyworkflows_destination" }, []) + const comfyworkflows_destination_checkbox_text = $el("label", {}, [" ComfyWorkflows.com"]) + this.comfyworkflows_destination_checkbox.style.color = "var(--fg-color)"; + this.comfyworkflows_destination_checkbox.checked = true; + + this.matrix_homeserver_input = $el("input", { type: 'text', id: "matrix_homeserver", placeholder: "matrix.org", value: ShareDialog.matrix_auth.homeserver || 'matrix.org' }, []); + this.matrix_username_input = $el("input", { type: 'text', placeholder: "Username", value: ShareDialog.matrix_auth.username || '' }, []); + this.matrix_password_input = $el("input", { type: 'password', placeholder: "Password", value: ShareDialog.matrix_auth.password || '' }, []); + + this.cw_sharekey_input = $el("input", { type: 'text', placeholder: "Share key (found on your profile page)", value: ShareDialog.cw_sharekey || '' }, []); + this.cw_sharekey_input.style.width = "100%"; + + this.credits_input = $el("input", { + type: "text", + placeholder: "This will be used to give credits", + required: false, + }, []); + + this.title_input = $el("input", { + type: "text", + placeholder: "ex: My awesome art", + required: false, + }, []); + + this.description_input = $el("textarea", { + placeholder: "ex: Trying out a new workflow... ", + required: false, + }, []); + + this.share_button = $el("button", { + type: "button", + textContent: "Share", + }, []); + + this.final_message = $el("div", {}, []); + + // get the user's existing matrix auth and share key + ShareDialog.matrix_auth = { homeserver: "matrix.org", username: "", password: "" }; + try { + api.fetchApi(`/manager/get_matrix_auth`) + .then(response => response.json()) + .then(data => { + ShareDialog.matrix_auth = data; + this.matrix_homeserver_input.value = ShareDialog.matrix_auth.homeserver; + this.matrix_username_input.value = ShareDialog.matrix_auth.username; + this.matrix_password_input.value = ShareDialog.matrix_auth.password; + }) + .catch(error => { + // console.log(error); + }); + } catch (error) { + // console.log(error); + } + + // get the user's existing comfyworkflows share key + ShareDialog.cw_sharekey = ""; + try { + console.log("Fetching comfyworkflows share key") + api.fetchApi(`/manager/get_comfyworkflows_auth`) + .then(response => response.json()) + .then(data => { + ShareDialog.cw_sharekey = data.comfyworkflows_sharekey; + this.cw_sharekey_input.value = ShareDialog.cw_sharekey; + }) + .catch(error => { + // console.log(error); + }); + } catch (error) { + // console.log(error); + } + + this.share_button.onclick = async () => { + const prompt = await app.graphToPrompt(); + const nodes = app.graph._nodes; + + const destinations = []; + if (this.matrix_destination_checkbox.checked) { + destinations.push("matrix"); + } + if (this.comfyworkflows_destination_checkbox.checked) { + destinations.push("comfyworkflows"); + } + + // if destinations includes matrix, make an api call to /manager/check_matrix to ensure that the user has configured their matrix settings + if (destinations.includes("matrix")) { + let definedMatrixAuth = !!this.matrix_homeserver_input.value && !!this.matrix_username_input.value && !!this.matrix_password_input.value; + if (!definedMatrixAuth) { + alert("Please set your Matrix account details."); + return; + } + } + + if (destinations.includes("comfyworkflows") && !this.cw_sharekey_input.value && !confirm("You have NOT set your ComfyWorkflows.com share key. Your art will NOT be connected to your account (it will be shared anonymously). Continue?")) { + return; + } + + const potential_outputs = []; + const potential_output_nodes = []; + + // iterate over the array of nodes to find the ones that are marked as SaveImage + // TODO: Add support for AnimateDiffCombine, etc. nodes that save videos/gifs, etc. + for (let i = 0; i < nodes.length; i++) { + const node = nodes[i]; + if (node.type !== "SaveImage") { + continue; + } + + if (node.type === "SaveImage") { + potential_output_nodes.push(node); + + // check if node has an 'images' array property + if (node.hasOwnProperty("images") && Array.isArray(node.images)) { + // iterate over the images array and add each image to the potential_outputs array + for (let j = 0; j < node.images.length; j++) { + potential_outputs.push({ "type": "image", "image": node.images[j] }); + } + } + } + } + + if (potential_outputs.length === 0) { + if (potential_output_nodes.length === 0) { + // todo: add support for other output node types (animatediff combine, etc.) + alert("No SaveImage node found. To share this workflow, please run a SaveImage node to your graph and re-run your prompt."); + } else { + alert("To share this, first run a prompt. Once it's done, click 'Share'."); + } + this.close(); + return; + } + + // Change the text of the share button to "Sharing..." to indicate that the share process has started + this.share_button.textContent = "Sharing..."; + + const response = await api.fetchApi(`/manager/share`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + matrix_auth: { + homeserver: this.matrix_homeserver_input.value, + username: this.matrix_username_input.value, + password: this.matrix_password_input.value, + }, + cw_auth: { + cw_sharekey: this.cw_sharekey_input.value, + }, + share_destinations: destinations, + credits: this.credits_input.value, + title: this.title_input.value, + description: this.description_input.value, + is_nsfw: this.is_nsfw_checkbox.checked, + prompt, + potential_outputs, + // potential_output_nodes + }) + }); + + if (response.status != 200) { + try { + const response_json = await response.json(); + if (response_json.error) { + alert(response_json.error); + this.close(); + return; + } else { + alert("Failed to share your art. Please try again."); + this.close(); + return; + } + } catch (e) { + alert("Failed to share your art. Please try again."); + this.close(); + return; + } + } + + const response_json = await response.json(); + + if (response_json.comfyworkflows.url) { + this.final_message.innerHTML = "Your art has been shared: " + response_json.comfyworkflows.url + ""; + if (response_json.matrix.success) { + this.final_message.innerHTML += "
Your art has been shared in the ComfyUI Matrix server's #share channel!"; + } + } else { + if (response_json.matrix.success) { + this.final_message.innerHTML = "Your art has been shared in the ComfyUI Matrix server's #share channel!"; + } + } + + this.final_message.style.color = "green"; + + // hide the share button + this.share_button.textContent = "Shared!"; + this.share_button.style.display = "none"; + // this.close(); + } + + const res = + [ + $el("tr.td", { width: "100%" }, [ + $el("font", { size: 6, color: "white" }, [`Share your art`]), + ]), + $el("br", {}, []), + + $el("details", { + style: { + border: "1px solid #999", + padding: "5px", + borderRadius: "5px", + backgroundColor: "#222" + } + }, [ + $el("summary", { + style: { + color: "white", + cursor: "pointer", + } + }, [`Matrix account`]), + $el("div", { + style: { + display: "flex", + flexDirection: "row", + } + }, [ + $el("div", { + textContent: "Homeserver", + style: { + marginRight: "10px", + } + }, []), + this.matrix_homeserver_input, + ]), + + $el("div", { + style: { + display: "flex", + flexDirection: "row", + } + }, [ + $el("div", { + textContent: "Username", + style: { + marginRight: "10px", + } + }, []), + this.matrix_username_input, + ]), + + $el("div", { + style: { + display: "flex", + flexDirection: "row", + } + }, [ + $el("div", { + textContent: "Password", + style: { + marginRight: "10px", + } + }, []), + this.matrix_password_input, + ]), + + ]), + $el("details", { + style: { + border: "1px solid #999", + marginTop: "10px", + padding: "5px", + borderRadius: "5px", + backgroundColor: "#222" + } + }, [ + $el("summary", { + style: { + color: "white", + cursor: "pointer", + } + }, [`Comfyworkflows.com account`]), + $el("h4", { + textContent: "Share key (found on your profile page)", + }, []), + $el("p", { size: 3, color: "white" }, ["When provided, your art will be saved to your account."]), + this.cw_sharekey_input, + ]), + + $el("div", {}, [ + $el("p", { size: 3, color: "white" }, [`Select where to share your art:`]), + this.matrix_destination_checkbox, + matrix_destination_checkbox_text, + $el("br", {}, []), + this.comfyworkflows_destination_checkbox, + comfyworkflows_destination_checkbox_text, + ]), + + $el("h4", { + textContent: "Credits (optional)", + size: 3, + color: "white" + }, []), + this.credits_input, + // $el("br", {}, []), + + $el("h4", { + textContent: "Title (optional)", + size: 3, + color: "white" + }, []), + this.title_input, + // $el("br", {}, []), + + $el("h4", { + textContent: "Description (optional)", + size: 3, + color: "white" + }, []), + this.description_input, + $el("br", {}, []), + + $el("div", {}, [this.is_nsfw_checkbox, is_nsfw_checkbox_text]), + this.final_message, + + $el("br", {}, []), + this.share_button, + + $el("button", { + type: "button", + textContent: "Close", + onclick: () => { + // Reset state + this.matrix_destination_checkbox.checked = true; + this.comfyworkflows_destination_checkbox.checked = true; + this.share_button.textContent = "Share"; + this.share_button.style.display = "inline-block"; + this.final_message.innerHTML = ""; + this.final_message.style.color = "white"; + this.credits_input.value = ""; + this.title_input.value = ""; + this.description_input.value = ""; + this.is_nsfw_checkbox.checked = false; + this.close() + } + }), + $el("br", {}, []), + ]; + + res[0].style.padding = "10px 10px 10px 10px"; + res[0].style.backgroundColor = "black"; //"linear-gradient(90deg, #00C9FF 0%, #92FE9D 100%)"; + res[0].style.textAlign = "center"; + res[0].style.height = "45px"; + return res; + } + + show() { + this.element.style.display = "block"; + } +} \ No newline at end of file