diff --git a/__init__.py b/__init__.py
index 775100bb..9a9f0f6a 100644
--- a/__init__.py
+++ b/__init__.py
@@ -15,8 +15,9 @@ import ssl
from urllib.parse import urlparse
import http.client
import re
+import signal
-version = "V1.5"
+version = "V1.5.1"
print(f"### Loading: ComfyUI-Manager ({version})")
@@ -1479,7 +1480,12 @@ async def get_notice(request):
@server.PromptServer.instance.routes.get("/manager/reboot")
def restart(self):
- return os.execv(sys.executable, ['python'] + sys.argv)
+ try:
+ sys.stdout.close_log()
+ except Exception as e:
+ pass
+
+ return os.execv(sys.executable, [sys.executable] + sys.argv)
@server.PromptServer.instance.routes.get("/manager/share_option")
diff --git a/js/comfyui-manager.js b/js/comfyui-manager.js
index f5ee2c0b..dabd011f 100644
--- a/js/comfyui-manager.js
+++ b/js/comfyui-manager.js
@@ -12,15 +12,15 @@ import { manager_instance, setManagerInstance, install_via_git_url, rebootAPI }
var docStyle = document.createElement('style');
docStyle.innerHTML = `
.cm-menu-container {
- column-gap: 20px;
- display: flex;
- flex-wrap: wrap;
- justify-content: center;
+ column-gap: 20px;
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
}
.cm-menu-column {
- display: flex;
- flex-direction: column;
+ display: flex;
+ flex-direction: column;
}
.cm-title {
@@ -38,7 +38,15 @@ docStyle.innerHTML = `
border: 1px solid #ccc;
padding: 10px;
overflow-x: hidden;
-};
+}
+
+.cm-conflicted-nodes-text {
+ background-color: #CCCC55 !important;
+ color: #AA3333 !important;
+ font-size: 10px;
+ border-radius: 5px;
+ padding: 5px;
+}
`;
document.head.appendChild(docStyle);
@@ -56,17 +64,17 @@ const style = `
overflow: hidden;
}
.pysssss-workflow-arrow-2 {
- position: absolute;
- top: 0;
- bottom: 0;
- right: 0;
- font-size: 12px;
- display: flex;
- align-items: center;
- width: 24px;
- justify-content: center;
- background: rgba(255,255,255,0.1);
- content: "▼";
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ right: 0;
+ font-size: 12px;
+ display: flex;
+ align-items: center;
+ width: 24px;
+ justify-content: center;
+ background: rgba(255,255,255,0.1);
+ content: "▼";
}
.pysssss-workflow-arrow-2:after {
content: "▼";
@@ -92,10 +100,10 @@ async function init_badge_mode() {
}
async function init_share_option() {
- api.fetchApi('/manager/share_option')
- .then(response => response.text())
+ api.fetchApi('/manager/share_option')
+ .then(response => response.text())
.then(data => {
- share_option = data || 'all';
+ share_option = data || 'all';
});
}
@@ -184,8 +192,8 @@ async function fetchUpdates(update_check_checkbox) {
try {
var mode = "url";
- if(manager_instance.local_mode_checkbox.checked)
- mode = "local";
+ if(manager_instance.local_mode_checkbox.checked)
+ mode = "local";
const response = await api.fetchApi(`/customnode/fetch_updates?mode=${mode}`);
@@ -227,8 +235,8 @@ async function updateAll(update_check_checkbox, manager_dialog) {
try {
var mode = "url";
- if(manager_instance.local_mode_checkbox.checked)
- mode = "local";
+ if(manager_instance.local_mode_checkbox.checked)
+ mode = "local";
update_all_button.innerText = "Updating all...";
const response1 = await api.fetchApi('/comfyui_manager/update_comfyui');
@@ -240,7 +248,7 @@ async function updateAll(update_check_checkbox, manager_dialog) {
return false;
}
if(response1.status == 201 || response2.status == 201) {
- app.ui.dialog.show("ComfyUI and all extensions have been updated to the latest version. Conflicted Nodes:
To apply the updated custom node, please ComfyUI.");
+ app.ui.dialog.show("ComfyUI and all extensions have been updated to the latest version.
To apply the updated custom node, please ComfyUI. And refresh browser.");
const rebootButton = document.getElementById('cm-reboot-button');
rebootButton.onclick = function() {
@@ -253,8 +261,8 @@ async function updateAll(update_check_checkbox, manager_dialog) {
}
else {
app.ui.dialog.show('ComfyUI and all extensions are already up-to-date with the latest versions.');
- app.ui.dialog.element.style.zIndex = 10010;
- }
+ app.ui.dialog.element.style.zIndex = 10010;
+ }
return true;
}
@@ -275,25 +283,25 @@ function newDOMTokenList(initialTokens) {
const classList = tmp.classList;
if (initialTokens) {
- initialTokens.forEach(token => {
+ initialTokens.forEach(token => {
classList.add(token);
- });
+ });
}
return classList;
- }
+ }
/**
* Check whether the node is a potential output node (img, gif or video output)
*/
const isOutputNode = (node) => {
- return [
- "VHS_VideoCombine",
- "PreviewImage",
- "SaveImage",
- "ADE_AnimateDiffCombine",
- "SaveAnimatedWEBP",
- ].includes(node.type);
+ return [
+ "VHS_VideoCombine",
+ "PreviewImage",
+ "SaveImage",
+ "ADE_AnimateDiffCombine",
+ "SaveAnimatedWEBP",
+ ].includes(node.type);
}
// -----------
@@ -362,7 +370,7 @@ class ManagerMenuDialog extends ComfyDialog {
}
}),
- $el("br", {}, []),
+ $el("br", {}, []),
update_all_button,
update_comfyui_button,
fetch_updates_button,
@@ -454,37 +462,37 @@ class ManagerMenuDialog extends ComfyDialog {
}
});
- // share
- let share_combo = document.createElement("select");
- const share_options = [
- ['none', 'None'],
- ['openart', 'OpenArt AI'],
- ['matrix', 'Matrix Server'],
- ['comfyworkflows', 'ComfyWorkflows'],
- ['all', 'All'],
- ];
- for (const option of share_options) {
- share_combo.appendChild($el('option', { value: option[0], text: `Share: ${option[1]}` }, []));
- }
+ // share
+ let share_combo = document.createElement("select");
+ const share_options = [
+ ['none', 'None'],
+ ['openart', 'OpenArt AI'],
+ ['matrix', 'Matrix Server'],
+ ['comfyworkflows', 'ComfyWorkflows'],
+ ['all', 'All'],
+ ];
+ for (const option of share_options) {
+ share_combo.appendChild($el('option', { value: option[0], text: `Share: ${option[1]}` }, []));
+ }
- api.fetchApi('/manager/share_option')
+ api.fetchApi('/manager/share_option')
.then(response => response.text())
.then(data => {
- share_combo.value = data || 'all';
- share_option = data || 'all';
+ share_combo.value = data || 'all';
+ share_option = data || 'all';
});
- share_combo.addEventListener('change', function (event) {
- const value = event.target.value;
- share_option = value;
- api.fetchApi(`/manager/share_option?value=${value}`);
- const shareButton = document.getElementById("shareButton");
- if (value === 'none') {
- shareButton.style.display = "none";
- } else {
- shareButton.style.display = "inline-block";
- }
- });
+ share_combo.addEventListener('change', function (event) {
+ const value = event.target.value;
+ share_option = value;
+ api.fetchApi(`/manager/share_option?value=${value}`);
+ const shareButton = document.getElementById("shareButton");
+ if (value === 'none') {
+ shareButton.style.display = "none";
+ } else {
+ shareButton.style.display = "inline-block";
+ }
+ });
return [
$el("div", {}, [this.local_mode_checkbox, checkbox_text, this.update_check_checkbox, uc_checkbox_text]),
@@ -682,13 +690,13 @@ app.registerExtension({
shareButton.id = "shareButton";
shareButton.textContent = "Share";
shareButton.onclick = () => {
- if (share_option === 'openart') {
- showOpenArtShareDialog();
- return;
- } else if (share_option === 'matrix' || share_option === 'comfyworkflows') {
- showShareDialog(share_option);
- return;
- }
+ if (share_option === 'openart') {
+ showOpenArtShareDialog();
+ return;
+ } else if (share_option === 'matrix' || share_option === 'comfyworkflows') {
+ showShareDialog(share_option);
+ return;
+ }
if(!ShareDialogChooser.instance) {
ShareDialogChooser.instance = new ShareDialogChooser();
@@ -753,11 +761,11 @@ app.registerExtension({
return r;
};
- this._addExtraNodeContextMenu(nodeType, app);
+ this._addExtraNodeContextMenu(nodeType, app);
},
async loadedGraphNode(node, app) {
- if (node.has_errors) {
+ if (node.has_errors) {
const onDrawForeground = node.onDrawForeground;
node.onDrawForeground = function (ctx) {
const r = onDrawForeground?.apply?.(this, arguments);
@@ -814,42 +822,42 @@ app.registerExtension({
},
_addExtraNodeContextMenu(node, app) {
- const origGetExtraMenuOptions = node.prototype.getExtraMenuOptions;
- node.prototype.getExtraMenuOptions = function (_, options) {
- origGetExtraMenuOptions?.apply?.(this, arguments);
- if (isOutputNode(node)) {
- const { potential_outputs } = getPotentialOutputsAndOutputNodes([this]);
- const hasOutput = potential_outputs.length > 0;
+ const origGetExtraMenuOptions = node.prototype.getExtraMenuOptions;
+ node.prototype.getExtraMenuOptions = function (_, options) {
+ origGetExtraMenuOptions?.apply?.(this, arguments);
+ if (isOutputNode(node)) {
+ const { potential_outputs } = getPotentialOutputsAndOutputNodes([this]);
+ const hasOutput = potential_outputs.length > 0;
- // Check if the previous menu option is `null`. If it's not,
- // then we need to add a `null` as a separator.
- if (options[options.length - 1] !== null) {
- options.push(null);
- }
+ // Check if the previous menu option is `null`. If it's not,
+ // then we need to add a `null` as a separator.
+ if (options[options.length - 1] !== null) {
+ options.push(null);
+ }
- options.push({
- content: "🏞️ Share Output",
- disabled: !hasOutput,
+ options.push({
+ content: "🏞️ Share Output",
+ disabled: !hasOutput,
callback: (obj) => {
- if (!ShareDialog.instance) {
- ShareDialog.instance = new ShareDialog();
- }
- const shareButton = document.getElementById("shareButton");
- if (shareButton) {
- const currentNode = this;
- if (!OpenArtShareDialog.instance) {
- OpenArtShareDialog.instance = new OpenArtShareDialog();
- }
- OpenArtShareDialog.instance.selectedNodeId = currentNode.id;
- if (!ShareDialog.instance) {
- ShareDialog.instance = new ShareDialog(share_option);
- }
- ShareDialog.instance.selectedNodeId = currentNode.id;
- shareButton.click();
- }
+ if (!ShareDialog.instance) {
+ ShareDialog.instance = new ShareDialog();
+ }
+ const shareButton = document.getElementById("shareButton");
+ if (shareButton) {
+ const currentNode = this;
+ if (!OpenArtShareDialog.instance) {
+ OpenArtShareDialog.instance = new OpenArtShareDialog();
+ }
+ OpenArtShareDialog.instance.selectedNodeId = currentNode.id;
+ if (!ShareDialog.instance) {
+ ShareDialog.instance = new ShareDialog(share_option);
+ }
+ ShareDialog.instance.selectedNodeId = currentNode.id;
+ shareButton.click();
+ }
}
}, null);
}
- }
+ }
},
});
diff --git a/js/common.js b/js/common.js
index 86290e81..024008f0 100644
--- a/js/common.js
+++ b/js/common.js
@@ -65,7 +65,7 @@ export async function install_checked_custom_node(grid_rows, target_i, caller, m
}
await caller.invalidateControl();
- caller.updateMessage("
To apply the installed/updated/disabled/enabled custom node, please ComfyUI.", 'cm-reboot-button');
+ caller.updateMessage("
To apply the installed/updated/disabled/enabled custom node, please ComfyUI. And refresh browser.", 'cm-reboot-button');
}
};
diff --git a/js/custom-nodes-downloader.js b/js/custom-nodes-downloader.js
index 91e3aedc..baa32cf5 100644
--- a/js/custom-nodes-downloader.js
+++ b/js/custom-nodes-downloader.js
@@ -259,89 +259,89 @@ export class CustomNodesInstaller extends ComfyDialog {
}
}
- invalidate_checks(is_checked, install_state) {
- if(is_checked) {
- for(let i in this.grid_rows) {
- let data = this.grid_rows[i].data;
- let checkbox = this.grid_rows[i].checkbox;
- let buttons = this.grid_rows[i].buttons;
+ invalidate_checks(is_checked, install_state) {
+ if(is_checked) {
+ for(let i in this.grid_rows) {
+ let data = this.grid_rows[i].data;
+ let checkbox = this.grid_rows[i].checkbox;
+ let buttons = this.grid_rows[i].buttons;
- checkbox.disabled = data.installed != install_state;
+ checkbox.disabled = data.installed != install_state;
- if(checkbox.disabled) {
- for(let j in buttons) {
- buttons[j].style.display = 'none';
- }
- }
- else {
- for(let j in buttons) {
- buttons[j].style.display = null;
- }
- }
- }
+ if(checkbox.disabled) {
+ for(let j in buttons) {
+ buttons[j].style.display = 'none';
+ }
+ }
+ else {
+ for(let j in buttons) {
+ buttons[j].style.display = null;
+ }
+ }
+ }
- this.checkbox_all.disabled = false;
- }
- else {
- for(let i in this.grid_rows) {
- let checkbox = this.grid_rows[i].checkbox;
- if(checkbox.check)
- return; // do nothing
- }
+ this.checkbox_all.disabled = false;
+ }
+ else {
+ for(let i in this.grid_rows) {
+ let checkbox = this.grid_rows[i].checkbox;
+ if(checkbox.check)
+ return; // do nothing
+ }
- // every checkbox is unchecked -> enable all checkbox
- for(let i in this.grid_rows) {
- let checkbox = this.grid_rows[i].checkbox;
- let buttons = this.grid_rows[i].buttons;
- checkbox.disabled = false;
+ // every checkbox is unchecked -> enable all checkbox
+ for(let i in this.grid_rows) {
+ let checkbox = this.grid_rows[i].checkbox;
+ let buttons = this.grid_rows[i].buttons;
+ checkbox.disabled = false;
- for(let j in buttons) {
- buttons[j].style.display = null;
- }
- }
+ for(let j in buttons) {
+ buttons[j].style.display = null;
+ }
+ }
- this.checkbox_all.checked = false;
- this.checkbox_all.disabled = true;
- }
- }
+ this.checkbox_all.checked = false;
+ this.checkbox_all.disabled = true;
+ }
+ }
- check_all(is_checked) {
- if(is_checked) {
- // lookup first checked item's state
- let check_state = null;
- for(let i in this.grid_rows) {
- let checkbox = this.grid_rows[i].checkbox;
- if(checkbox.checked) {
- check_state = this.grid_rows[i].data.installed;
- }
- }
+ check_all(is_checked) {
+ if(is_checked) {
+ // lookup first checked item's state
+ let check_state = null;
+ for(let i in this.grid_rows) {
+ let checkbox = this.grid_rows[i].checkbox;
+ if(checkbox.checked) {
+ check_state = this.grid_rows[i].data.installed;
+ }
+ }
- if(check_state == null)
- return;
+ if(check_state == null)
+ return;
- // check only same state items
- for(let i in this.grid_rows) {
- let checkbox = this.grid_rows[i].checkbox;
- if(this.grid_rows[i].data.installed == check_state)
- checkbox.checked = true;
- }
- }
- else {
- // uncheck all
- for(let i in this.grid_rows) {
- let checkbox = this.grid_rows[i].checkbox;
- let buttons = this.grid_rows[i].buttons;
- checkbox.checked = false;
- checkbox.disabled = false;
+ // check only same state items
+ for(let i in this.grid_rows) {
+ let checkbox = this.grid_rows[i].checkbox;
+ if(this.grid_rows[i].data.installed == check_state)
+ checkbox.checked = true;
+ }
+ }
+ else {
+ // uncheck all
+ for(let i in this.grid_rows) {
+ let checkbox = this.grid_rows[i].checkbox;
+ let buttons = this.grid_rows[i].buttons;
+ checkbox.checked = false;
+ checkbox.disabled = false;
- for(let j in buttons) {
- buttons[j].style.display = null;
- }
- }
+ for(let j in buttons) {
+ buttons[j].style.display = null;
+ }
+ }
- this.checkbox_all.disabled = true;
- }
- }
+ this.checkbox_all.disabled = true;
+ }
+ }
async createGrid() {
var grid = document.createElement('table');
@@ -349,24 +349,24 @@ export class CustomNodesInstaller extends ComfyDialog {
this.grid_rows = {};
- let self = this;
+ let self = this;
- var thead = document.createElement('thead');
- var tbody = document.createElement('tbody');
+ var thead = document.createElement('thead');
+ var tbody = document.createElement('tbody');
var headerRow = document.createElement('tr');
thead.style.position = "sticky";
thead.style.top = "0px";
- thead.style.borderCollapse = "collapse";
- thead.style.tableLayout = "fixed";
+ thead.style.borderCollapse = "collapse";
+ thead.style.tableLayout = "fixed";
var header0 = document.createElement('th');
header0.style.width = "20px";
- this.checkbox_all = $el("input",{type:'checkbox', id:'check_all'},[]);
- header0.appendChild(this.checkbox_all);
- this.checkbox_all.checked = false;
- this.checkbox_all.disabled = true;
- this.checkbox_all.addEventListener('change', function() { self.check_all.call(self, self.checkbox_all.checked); });
+ this.checkbox_all = $el("input",{type:'checkbox', id:'check_all'},[]);
+ header0.appendChild(this.checkbox_all);
+ this.checkbox_all.checked = false;
+ this.checkbox_all.disabled = true;
+ this.checkbox_all.addEventListener('change', function() { self.check_all.call(self, self.checkbox_all.checked); });
var header1 = document.createElement('th');
header1.innerHTML = ' ID ';
@@ -380,7 +380,7 @@ export class CustomNodesInstaller extends ComfyDialog {
var header4 = document.createElement('th');
header4.innerHTML = 'Description';
header4.style.width = "60%";
-// header4.classList.add('expandable-column');
+// header4.classList.add('expandable-column');
var header5 = document.createElement('th');
header5.innerHTML = 'Install';
header5.style.width = "130px";
@@ -398,7 +398,7 @@ export class CustomNodesInstaller extends ComfyDialog {
header5.style.position = "sticky";
header5.style.top = "0px";
- thead.appendChild(headerRow);
+ thead.appendChild(headerRow);
headerRow.appendChild(header0);
headerRow.appendChild(header1);
headerRow.appendChild(header2);
@@ -421,28 +421,28 @@ export class CustomNodesInstaller extends ComfyDialog {
let dataRow = document.createElement('tr');
let data0 = document.createElement('td');
- let checkbox = $el("input",{type:'checkbox', id:`check_${i}`},[]);
- data0.appendChild(checkbox);
- checkbox.checked = false;
- checkbox.addEventListener('change', function() { self.invalidate_checks.call(self, checkbox.checked, data.installed); });
+ let checkbox = $el("input",{type:'checkbox', id:`check_${i}`},[]);
+ data0.appendChild(checkbox);
+ checkbox.checked = false;
+ checkbox.addEventListener('change', function() { self.invalidate_checks.call(self, checkbox.checked, data.installed); });
var data1 = document.createElement('td');
data1.style.textAlign = "center";
data1.innerHTML = i+1;
var data2 = document.createElement('td');
- data2.style.maxWidth = "100px";
+ data2.style.maxWidth = "100px";
data2.className = "cm-node-author"
data2.textContent = ` ${data.author}`;
data2.style.whiteSpace = "nowrap";
- data2.style.overflow = "hidden";
+ data2.style.overflow = "hidden";
data2.style.textOverflow = "ellipsis";
- var data3 = document.createElement('td');
- data3.style.maxWidth = "200px";
- data3.style.wordWrap = "break-word";
+ var data3 = document.createElement('td');
+ data3.style.maxWidth = "200px";
+ data3.style.wordWrap = "break-word";
data3.className = "cm-node-name"
- data3.innerHTML = ` ${data.title}`;
+ data3.innerHTML = ` ${data.title}`;
if(data.installed == 'Fail')
data3.innerHTML = ' (IMPORT FAILED)' + data3.innerHTML;
@@ -452,7 +452,7 @@ export class CustomNodesInstaller extends ComfyDialog {
let conflicts = this.conflict_mappings[data.files[0]];
if(conflicts) {
- let buf = '
Conflicted Nodes:
';
+ let buf = '
';
for(let k in conflicts) {
let node_name = conflicts[k][0];
@@ -464,13 +464,13 @@ export class CustomNodesInstaller extends ComfyDialog {
extension_name = extension_name.slice(0, -4);
}
- buf += `${node_name} [${extension_name}], `;
+ buf += `${node_name} [${extension_name}], `;
}
if(buf.endsWith(', ')) {
buf = buf.slice(0, -2);
}
- buf += "