From 86fe6b317eb563c0e5fdfecfac37853b90e392b1 Mon Sep 17 00:00:00 2001 From: "Dr.Lt.Data" Date: Mon, 27 Nov 2023 12:40:45 +0900 Subject: [PATCH] fix: log file permission issue when reboot on windows enhance: pretty conflict nodes message --- __init__.py | 10 +- js/comfyui-manager.js | 224 +++++++++++++++--------------- js/common.js | 2 +- js/custom-nodes-downloader.js | 248 +++++++++++++++++----------------- js/snapshot.js | 2 +- prestartup_script.py | 11 +- 6 files changed, 259 insertions(+), 238 deletions(-) diff --git a/__init__.py b/__init__.py index 775100b..9a9f0f6 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 f5ee2c0..dabd011 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.
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]}` }, [])); - } - - api.fetchApi('/manager/share_option') + // 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') .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; - - // 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, + 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); + } + + 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 86290e8..024008f 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 91e3aed..baa32cf 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; - - 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; - } - } - } - - 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; - - for(let j in buttons) { - buttons[j].style.display = null; - } - } - - 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; - } - } - - 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; - - for(let j in buttons) { - buttons[j].style.display = null; - } - } - - this.checkbox_all.disabled = true; - } - } + 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; + + 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 + } + + // 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; + } + } + + 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; + } + } + + 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; + + for(let j in buttons) { + buttons[j].style.display = null; + } + } + + 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 = '

Conflicted Nodes:
'; 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 += "
"; + buf += "

"; data4.innerHTML += buf; } @@ -537,7 +537,7 @@ export class CustomNodesInstaller extends ComfyDialog { installBtn.style.color = 'white'; } - let j = i; + let j = i; if(installBtn2 != null) { installBtn2.style.width = "120px"; installBtn2.addEventListener('click', function() { @@ -587,28 +587,28 @@ export class CustomNodesInstaller extends ComfyDialog { let buttons = []; if(installBtn) { - buttons.push(installBtn); - } + buttons.push(installBtn); + } if(installBtn2) { - buttons.push(installBtn2); - } + buttons.push(installBtn2); + } if(installBtn3) { - buttons.push(installBtn3); - } + buttons.push(installBtn3); + } this.grid_rows[i] = {data:data, buttons:buttons, checkbox:checkbox, control:dataRow}; } const panel = document.createElement('div'); - panel.style.width = "100%"; + panel.style.width = "100%"; panel.appendChild(grid); - function handleResize() { - const parentHeight = self.element.clientHeight; - const gridHeight = parentHeight - 200; + function handleResize() { + const parentHeight = self.element.clientHeight; + const gridHeight = parentHeight - 200; - grid.style.height = gridHeight + "px"; - } + grid.style.height = gridHeight + "px"; + } window.addEventListener("resize", handleResize); grid.style.position = "relative"; @@ -620,7 +620,7 @@ export class CustomNodesInstaller extends ComfyDialog { this.element.style.width = "80%"; this.element.appendChild(panel); - handleResize(); + handleResize(); } createFilterCombo() { @@ -658,8 +658,8 @@ export class CustomNodesInstaller extends ComfyDialog { self.apply_searchbox(); }); - if(self.filter) { - combo.value = self.filter; + if(self.filter) { + combo.value = self.filter; } return combo; diff --git a/js/snapshot.js b/js/snapshot.js index f9e06dc..ba379dd 100644 --- a/js/snapshot.js +++ b/js/snapshot.js @@ -23,7 +23,7 @@ async function restore_snapshot(target) { } finally { await SnapshotManager.instance.invalidateControl(); - SnapshotManager.instance.updateMessage("
To apply the snapshot, please ComfyUI.", 'cm-reboot-button'); + SnapshotManager.instance.updateMessage("
To apply the snapshot, please ComfyUI. And refresh browser.", 'cm-reboot-button'); } } } diff --git a/prestartup_script.py b/prestartup_script.py index c86a17c..9dfc013 100644 --- a/prestartup_script.py +++ b/prestartup_script.py @@ -173,11 +173,18 @@ try: def reconfigure(self, *args, **kwargs): pass + + # You can close through sys.stderr.close_log() + def close_log(self): + sys.stderr = original_stderr + sys.stdout = original_stdout + log_file.close() def close_log(): + sys.stderr = original_stderr + sys.stdout = original_stdout log_file.close() - - + sys.stdout = ComfyUIManagerLogger(True) sys.stderr = ComfyUIManagerLogger(False)