Files
bentoml-comfy-pack/web/main.js
T
2024-11-20 14:42:12 +08:00

235 lines
5.6 KiB
JavaScript

import { app } from "../../scripts/app.js";
import { api } from "../../scripts/api.js";
function createInputModal() {
return new Promise((resolve) => {
const modal = document.createElement("div");
modal.style.cssText = `
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: #1a1a1a;
padding: 20px;
border-radius: 8px;
z-index: 1000;
min-width: 300px;
`;
const title = document.createElement("h3");
title.textContent = "Package Worlflow";
title.style.cssText = `
margin-bottom: 15px;
color: #fff;
`;
const input = document.createElement("input");
input.type = "text";
input.value = "package";
input.style.cssText = `
width: 100%;
padding: 8px;
margin-bottom: 15px;
background: #333;
border: 1px solid #444;
border-radius: 4px;
color: #fff;
box-sizing: border-box;
`;
const buttonContainer = document.createElement("div");
buttonContainer.style.cssText = `
display: flex;
justify-content: flex-end;
gap: 10px;
`;
const confirmButton = document.createElement("button");
confirmButton.textContent = "Confirm";
confirmButton.style.cssText = `
padding: 6px 12px;
background: #00a67d;
border: none;
border-radius: 4px;
color: white;
cursor: pointer;
`;
const cancelButton = document.createElement("button");
cancelButton.textContent = "Cancel";
cancelButton.style.cssText = `
padding: 6px 12px;
background: #666;
border: none;
border-radius: 4px;
color: white;
cursor: pointer;
`;
const overlay = document.createElement("div");
overlay.style.cssText = `
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
z-index: 999;
`;
buttonContainer.appendChild(cancelButton);
buttonContainer.appendChild(confirmButton);
modal.appendChild(title);
modal.appendChild(input);
modal.appendChild(buttonContainer);
document.body.appendChild(overlay);
document.body.appendChild(modal);
const cleanup = () => {
modal.remove();
overlay.remove();
};
confirmButton.onclick = () => {
const filename = input.value.trim();
if (filename) {
cleanup();
resolve(filename);
}
};
cancelButton.onclick = () => {
cleanup();
resolve(null);
};
input.addEventListener("keyup", (e) => {
if (e.key === "Enter") {
confirmButton.click();
}
});
input.select();
});
}
function createDownloadModal() {
const modal = document.createElement("div");
modal.style.cssText = `
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: #1a1a1a;
padding: 20px;
border-radius: 8px;
z-index: 1000;
min-width: 300px;
`;
const title = document.createElement("h3");
title.textContent = "Packaging...";
title.style.marginBottom = "15px";
title.style.color = "#fff";
const progress = document.createElement("div");
progress.style.cssText = `
width: 100%;
height: 20px;
background: #333;
border-radius: 10px;
overflow: hidden;
`;
const progressBar = document.createElement("div");
progressBar.style.cssText = `
width: 0%;
height: 100%;
background: #00a67d;
transition: width 0.3s ease;
`;
progress.appendChild(progressBar);
modal.appendChild(title);
modal.appendChild(progress);
const overlay = document.createElement("div");
overlay.style.cssText = `
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
z-index: 999;
`;
document.body.appendChild(overlay);
document.body.appendChild(modal);
return {
modal,
overlay,
progressBar,
updateProgress: (percent) => {
progressBar.style.width = `${percent}%`;
},
close: () => {
modal.remove();
overlay.remove();
}
};
}
app.registerExtension({
name: "Comfy.CPackExtension",
async setup() {
const menu = document.querySelector(".comfy-menu");
const separator = document.createElement("hr");
separator.style.margin = "20px 0";
separator.style.width = "100%";
menu.append(separator);
const packButton = document.createElement("button");
packButton.textContent = "Package";
packButton.onclick = async () => {
const filename = await createInputModal();
if (!filename) return;
packButton.disabled = true;
const downloadModal = createDownloadModal();
try {
downloadModal.updateProgress(20);
const { workflow, output: workflow_api } = await app.graphToPrompt();
downloadModal.updateProgress(40);
const body = JSON.stringify({ workflow, workflow_api });
downloadModal.updateProgress(60);
const resp = await api.fetchApi("/bentoml/pack", { method: "POST", body, headers: { "Content-Type": "application/json" } });
downloadModal.updateProgress(80);
const downloadUrl = (await resp.json())["download_url"];
downloadModal.updateProgress(100);
const link = document.createElement("a");
link.href = downloadUrl;
link.download = filename + ".cpack.zip";
link.click();
setTimeout(() => {
downloadModal.close();
}, 1000);
} catch (error) {
console.error("Package failed:", error);
downloadModal.close();
} finally {
packButton.disabled = false;
}
}
menu.append(packButton);
}
});