mirror of
https://github.com/Comfy-Org/ComfyUI-Manager.git
synced 2025-12-22 21:00:49 +08:00
feat: update, uninstall for custom nodes
This commit is contained in:
parent
c920b10aa8
commit
4d54ef7738
149
__init__.py
149
__init__.py
@ -9,7 +9,7 @@ sys.path.append('../..')
|
|||||||
from torchvision.datasets.utils import download_url
|
from torchvision.datasets.utils import download_url
|
||||||
|
|
||||||
# ensure .js
|
# ensure .js
|
||||||
print("### Loading: ComfyUI-Manager (V0.1)")
|
print("### Loading: ComfyUI-Manager (V0.2)")
|
||||||
|
|
||||||
comfy_path = os.path.dirname(folder_paths.__file__)
|
comfy_path = os.path.dirname(folder_paths.__file__)
|
||||||
custom_nodes_path = os.path.join(comfy_path, 'custom_nodes')
|
custom_nodes_path = os.path.join(comfy_path, 'custom_nodes')
|
||||||
@ -21,6 +21,33 @@ local_db_alter = os.path.join(comfyui_manager_path, "alter-list.json")
|
|||||||
local_db_custom_node_list = os.path.join(comfyui_manager_path, "custom-node-list.json")
|
local_db_custom_node_list = os.path.join(comfyui_manager_path, "custom-node-list.json")
|
||||||
|
|
||||||
|
|
||||||
|
def git_repo_has_updates(path):
|
||||||
|
# Check if the path is a git repository
|
||||||
|
if not os.path.exists(os.path.join(path, '.git')):
|
||||||
|
raise ValueError('Not a git repository')
|
||||||
|
|
||||||
|
# Fetch the latest commits from the remote repository
|
||||||
|
subprocess.run(['git', 'fetch'], check=True, cwd=path)
|
||||||
|
|
||||||
|
# Get the current commit hash and the commit hash of the remote branch
|
||||||
|
commit_hash = subprocess.check_output(['git', 'rev-parse', 'HEAD'], encoding='utf-8', cwd=path).strip()
|
||||||
|
remote_commit_hash = subprocess.check_output(['git', 'rev-parse', '@{u}'], encoding='utf-8', cwd=path).strip()
|
||||||
|
|
||||||
|
# Compare the commit hashes to determine if the local repository is behind the remote repository
|
||||||
|
if commit_hash != remote_commit_hash:
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def git_pull(path):
|
||||||
|
print(f"path: {path}")
|
||||||
|
if not os.path.exists(os.path.join(path, '.git')):
|
||||||
|
raise ValueError('Not a git repository')
|
||||||
|
|
||||||
|
subprocess.run(['git', 'pull'], check=True, cwd=path)
|
||||||
|
|
||||||
|
|
||||||
async def get_data(uri):
|
async def get_data(uri):
|
||||||
print(f"FECTH DATA from: {uri}")
|
print(f"FECTH DATA from: {uri}")
|
||||||
if uri.startswith("http"):
|
if uri.startswith("http"):
|
||||||
@ -101,7 +128,14 @@ def check_a_custom_node_installed(item):
|
|||||||
dir_name = os.path.splitext(os.path.basename(item['files'][0]))[0].replace(".git", "")
|
dir_name = os.path.splitext(os.path.basename(item['files'][0]))[0].replace(".git", "")
|
||||||
dir_path = os.path.join(custom_nodes_path, dir_name)
|
dir_path = os.path.join(custom_nodes_path, dir_name)
|
||||||
if os.path.exists(dir_path):
|
if os.path.exists(dir_path):
|
||||||
|
try:
|
||||||
|
if git_repo_has_updates(dir_path):
|
||||||
|
item['installed'] = 'Update'
|
||||||
|
else:
|
||||||
item['installed'] = 'True'
|
item['installed'] = 'True'
|
||||||
|
except:
|
||||||
|
item['installed'] = 'True'
|
||||||
|
|
||||||
else:
|
else:
|
||||||
item['installed'] = 'False'
|
item['installed'] = 'False'
|
||||||
|
|
||||||
@ -208,7 +242,7 @@ def unzip_install(files):
|
|||||||
print(f"Install(unzip) error: {url} / {e}")
|
print(f"Install(unzip) error: {url} / {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
print("Installation successful.")
|
print("Installation was successful.")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
@ -228,7 +262,7 @@ def download_url_with_agent(url, save_path):
|
|||||||
print(f"Download error: {url} / {e}")
|
print(f"Download error: {url} / {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
print("Installation successful.")
|
print("Installation was successful.")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
@ -247,7 +281,23 @@ def copy_install(files, js_path_name=None):
|
|||||||
print(f"Install(copy) error: {url} / {e}")
|
print(f"Install(copy) error: {url} / {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
print("Installation successful.")
|
print("Installation was successful.")
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def copy_uninstall(files, js_path_name=None):
|
||||||
|
for url in files:
|
||||||
|
dir_name = os.path.basename(url)
|
||||||
|
base_path = custom_nodes_path if url.endswith('.py') else js_path
|
||||||
|
file_path = os.path.join(base_path, dir_name)
|
||||||
|
|
||||||
|
try:
|
||||||
|
os.remove(file_path)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"UnInstall(copy) error: {url} / {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
print("Uninstallation was successful.")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
@ -291,7 +341,50 @@ def gitclone_install(files):
|
|||||||
print(f"Install(git-clone) error: {url} / {e}")
|
print(f"Install(git-clone) error: {url} / {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
print("Installation successful.")
|
print("Installation was successful.")
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def gitclone_uninstall(files):
|
||||||
|
import shutil
|
||||||
|
import os
|
||||||
|
|
||||||
|
print(f"uninstall: {files}")
|
||||||
|
for url in files:
|
||||||
|
try:
|
||||||
|
dir_name = os.path.splitext(os.path.basename(url))[0].replace(".git", "")
|
||||||
|
dir_path = os.path.join(custom_nodes_path, dir_name)
|
||||||
|
|
||||||
|
# safey check
|
||||||
|
if dir_path == '/' or dir_path[1:] == ":/" or dir_path == '':
|
||||||
|
print(f"Uninstall(git-clone) error: invalid path '{dir_path}' for '{url}'")
|
||||||
|
return False
|
||||||
|
|
||||||
|
shutil.rmtree(dir_path)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Uninstall(git-clone) error: {url} / {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
print("Uninstallation was successful.")
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def gitclone_update(files):
|
||||||
|
import shutil
|
||||||
|
import os
|
||||||
|
|
||||||
|
print(f"uninstall: {files}")
|
||||||
|
for url in files:
|
||||||
|
try:
|
||||||
|
dir_name = os.path.splitext(os.path.basename(url))[0].replace(".git", "")
|
||||||
|
dir_path = os.path.join(custom_nodes_path, dir_name)
|
||||||
|
git_pull(dir_path)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Update(git-clone) error: {url} / {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
print("Uninstallation was successful.")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
@ -321,6 +414,48 @@ async def install_custom_node(request):
|
|||||||
return web.Response(status=400)
|
return web.Response(status=400)
|
||||||
|
|
||||||
|
|
||||||
|
@server.PromptServer.instance.routes.post("/customnode/uninstall")
|
||||||
|
async def install_custom_node(request):
|
||||||
|
json_data = await request.json()
|
||||||
|
|
||||||
|
install_type = json_data['install_type']
|
||||||
|
|
||||||
|
print(f"Uninstall custom node '{json_data['title']}'")
|
||||||
|
|
||||||
|
res = False
|
||||||
|
|
||||||
|
if install_type == "copy":
|
||||||
|
js_path_name = json_data['js_path'] if 'js_path' in json_data else None
|
||||||
|
res = copy_uninstall(json_data['files'], js_path_name)
|
||||||
|
|
||||||
|
elif install_type == "git-clone":
|
||||||
|
res = gitclone_uninstall(json_data['files'])
|
||||||
|
|
||||||
|
if res:
|
||||||
|
return web.json_response({}, content_type='application/json')
|
||||||
|
|
||||||
|
return web.Response(status=400)
|
||||||
|
|
||||||
|
|
||||||
|
@server.PromptServer.instance.routes.post("/customnode/update")
|
||||||
|
async def install_custom_node(request):
|
||||||
|
json_data = await request.json()
|
||||||
|
|
||||||
|
install_type = json_data['install_type']
|
||||||
|
|
||||||
|
print(f"Update custom node '{json_data['title']}'")
|
||||||
|
|
||||||
|
res = False
|
||||||
|
|
||||||
|
if install_type == "git-clone":
|
||||||
|
res = gitclone_update(json_data['files'])
|
||||||
|
|
||||||
|
if res:
|
||||||
|
return web.json_response({}, content_type='application/json')
|
||||||
|
|
||||||
|
return web.Response(status=400)
|
||||||
|
|
||||||
|
|
||||||
@server.PromptServer.instance.routes.post("/model/install")
|
@server.PromptServer.instance.routes.post("/model/install")
|
||||||
async def install_model(request):
|
async def install_model(request):
|
||||||
json_data = await request.json()
|
json_data = await request.json()
|
||||||
@ -339,3 +474,7 @@ async def install_model(request):
|
|||||||
return web.json_response({}, content_type='application/json')
|
return web.json_response({}, content_type='application/json')
|
||||||
|
|
||||||
return web.Response(status=400)
|
return web.Response(status=400)
|
||||||
|
|
||||||
|
|
||||||
|
NODE_CLASS_MAPPINGS = {}
|
||||||
|
__all__ = ['NODE_CLASS_MAPPINGS']
|
||||||
@ -12,8 +12,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id":"https://github.com/ltdrdata/ComfyUI-Impact-Pack",
|
"id":"https://github.com/ltdrdata/ComfyUI-Impact-Pack",
|
||||||
"tags":"ddetailer, adetailer, ddsd, DD",
|
"tags":"ddetailer, adetailer, ddsd, DD, loopback scaler",
|
||||||
"description": "To implement the feature of automatically detecting faces and enhancing details, various detection nodes and detailers provided by the Impact Pack can be applied."
|
"description": "To implement the feature of automatically detecting faces and enhancing details, various detection nodes and detailers provided by the Impact Pack can be applied. Similarly to Loopback Scaler, it also provides various custom workflows that can apply Ksampler while gradually scaling up."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id":"https://github.com/biegert/ComfyUI-CLIPSeg/raw/main/custom_nodes/clipseg.py",
|
"id":"https://github.com/biegert/ComfyUI-CLIPSeg/raw/main/custom_nodes/clipseg.py",
|
||||||
|
|||||||
@ -8,7 +8,7 @@
|
|||||||
"https://github.com/ltdrdata/ComfyUI-Impact-Pack"
|
"https://github.com/ltdrdata/ComfyUI-Impact-Pack"
|
||||||
],
|
],
|
||||||
"install_type": "git-clone",
|
"install_type": "git-clone",
|
||||||
"description": "This extension offers various detector nodes and detailer nodes that allow you to configure a workflow that automatically enhances facial details."
|
"description": "This extension offers various detector nodes and detailer nodes that allow you to configure a workflow that automatically enhances facial details. And provide iterative upscaler."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"author": "comfyanonymous",
|
"author": "comfyanonymous",
|
||||||
@ -82,7 +82,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"author": "BlenderNeko",
|
"author": "BlenderNeko",
|
||||||
"title": "(WIP) Tiled sampling for ComfyUI",
|
"title": "Tiled sampling for ComfyUI",
|
||||||
"reference": "https://github.com/BlenderNeko/ComfyUI_TiledKSampler",
|
"reference": "https://github.com/BlenderNeko/ComfyUI_TiledKSampler",
|
||||||
"files": [
|
"files": [
|
||||||
"https://github.com/BlenderNeko/ComfyUI_TiledKSampler"
|
"https://github.com/BlenderNeko/ComfyUI_TiledKSampler"
|
||||||
|
|||||||
@ -35,24 +35,30 @@ async function getModelList() {
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function install_custom_node(target, caller) {
|
async function install_custom_node(target, caller, mode) {
|
||||||
if(caller) {
|
if(caller) {
|
||||||
caller.startInstall(target);
|
caller.startInstall(target);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch('/customnode/install', {
|
const response = await fetch(`/customnode/${mode}`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
body: JSON.stringify(target)
|
body: JSON.stringify(target)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if(response.status == 400) {
|
||||||
|
app.ui.dialog.show(`${mode} failed: ${target.title}`);
|
||||||
|
app.ui.dialog.element.style.zIndex = 9999;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
const status = await response.json();
|
const status = await response.json();
|
||||||
app.ui.dialog.close();
|
app.ui.dialog.close();
|
||||||
target.installed = 'True';
|
target.installed = 'True';
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch(exception) {
|
catch(exception) {
|
||||||
app.ui.dialog.show(`Install failed: ${target.title} / ${exception}`);
|
app.ui.dialog.show(`${mode} failed: ${target.title} / ${exception}`);
|
||||||
app.ui.dialog.element.style.zIndex = 9999;
|
app.ui.dialog.element.style.zIndex = 9999;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -112,18 +118,37 @@ class CustomNodesInstaller extends ComfyDialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
startInstall(target) {
|
startInstall(target) {
|
||||||
this.updateMessage(`<BR><font color="green">Installing '${target.title}'</font>`);
|
const self = CustomNodesInstaller.instance;
|
||||||
|
|
||||||
for(let i in this.install_buttons) {
|
self.updateMessage(`<BR><font color="green">Installing '${target.title}'</font>`);
|
||||||
this.install_buttons[i].disabled = true;
|
|
||||||
this.install_buttons[i].style.backgroundColor = 'gray';
|
for(let i in self.install_buttons) {
|
||||||
|
self.install_buttons[i].disabled = true;
|
||||||
|
self.install_buttons[i].style.backgroundColor = 'gray';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async invalidateControl() {
|
async invalidateControl() {
|
||||||
this.clear();
|
this.clear();
|
||||||
|
|
||||||
|
// splash
|
||||||
|
while (this.element.children.length) {
|
||||||
|
this.element.removeChild(this.element.children[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const msg = $el('div', {id:'custom-message'},
|
||||||
|
[$el('br'),
|
||||||
|
'The custom node DB is currently being updated, and updates to custom nodes are being checked for.',
|
||||||
|
$el('br')]);
|
||||||
|
msg.style.height = '100px';
|
||||||
|
msg.style.verticalAlign = 'middle';
|
||||||
|
this.element.appendChild(msg);
|
||||||
|
|
||||||
|
// invalidate
|
||||||
this.data = (await getCustomNodes()).custom_nodes;
|
this.data = (await getCustomNodes()).custom_nodes;
|
||||||
|
|
||||||
|
this.element.removeChild(msg);
|
||||||
|
|
||||||
while (this.element.children.length) {
|
while (this.element.children.length) {
|
||||||
this.element.removeChild(this.element.children[0]);
|
this.element.removeChild(this.element.children[0]);
|
||||||
}
|
}
|
||||||
@ -190,14 +215,23 @@ class CustomNodesInstaller extends ComfyDialog {
|
|||||||
data5.style.textAlign = "center";
|
data5.style.textAlign = "center";
|
||||||
|
|
||||||
var installBtn = document.createElement('button');
|
var installBtn = document.createElement('button');
|
||||||
|
var installBtn2 = null;
|
||||||
|
|
||||||
this.install_buttons.push(installBtn);
|
this.install_buttons.push(installBtn);
|
||||||
|
|
||||||
switch(data.installed) {
|
switch(data.installed) {
|
||||||
|
case 'Update':
|
||||||
|
installBtn2 = document.createElement('button');
|
||||||
|
installBtn2.innerHTML = 'Update';
|
||||||
|
installBtn2.style.backgroundColor = 'blue';
|
||||||
|
this.install_buttons.push(installBtn2);
|
||||||
|
|
||||||
|
installBtn.innerHTML = 'Uninstall';
|
||||||
|
installBtn.style.backgroundColor = 'red';
|
||||||
|
break;
|
||||||
case 'True':
|
case 'True':
|
||||||
installBtn.innerHTML = 'Installed';
|
installBtn.innerHTML = 'Uninstall';
|
||||||
installBtn.style.backgroundColor = 'green';
|
installBtn.style.backgroundColor = 'red';
|
||||||
installBtn.disabled = true;
|
|
||||||
break;
|
break;
|
||||||
case 'False':
|
case 'False':
|
||||||
installBtn.innerHTML = 'Install';
|
installBtn.innerHTML = 'Install';
|
||||||
@ -205,11 +239,26 @@ class CustomNodesInstaller extends ComfyDialog {
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
installBtn.innerHTML = 'Try Install';
|
installBtn.innerHTML = 'Try Install';
|
||||||
installBtn.style.backgroundColor = 'brown';
|
installBtn.style.backgroundColor = 'silver';
|
||||||
|
}
|
||||||
|
|
||||||
|
if(installBtn2 != null) {
|
||||||
|
installBtn2.addEventListener('click', function() {
|
||||||
|
install_custom_node(data, CustomNodesInstaller.instance, 'update');
|
||||||
|
});
|
||||||
|
|
||||||
|
data5.appendChild(installBtn2);
|
||||||
}
|
}
|
||||||
|
|
||||||
installBtn.addEventListener('click', function() {
|
installBtn.addEventListener('click', function() {
|
||||||
install_custom_node(data, CustomNodesInstaller.instance);
|
if(this.innerHTML == 'Uninstall') {
|
||||||
|
if (confirm(`Are you sure uninstall ${data.title}?`)) {
|
||||||
|
install_custom_node(data, CustomNodesInstaller.instance, 'uninstall');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
install_custom_node(data, CustomNodesInstaller.instance, 'install');
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
data5.appendChild(installBtn);
|
data5.appendChild(installBtn);
|
||||||
@ -281,18 +330,37 @@ class AlternativesInstaller extends ComfyDialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
startInstall(target) {
|
startInstall(target) {
|
||||||
this.updateMessage(`<BR><font color="green">Installing '${target.title}'</font>`);
|
const self = AlternativesInstaller.instance;
|
||||||
|
|
||||||
for(let i in this.install_buttons) {
|
self.updateMessage(`<BR><font color="green">Installing '${target.title}'</font>`);
|
||||||
this.install_buttons[i].disabled = true;
|
|
||||||
this.install_buttons[i].style.backgroundColor = 'gray';
|
for(let i in self.install_buttons) {
|
||||||
|
self.install_buttons[i].disabled = true;
|
||||||
|
self.install_buttons[i].style.backgroundColor = 'gray';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async invalidateControl() {
|
async invalidateControl() {
|
||||||
this.clear();
|
this.clear();
|
||||||
|
|
||||||
|
// splash
|
||||||
|
while (this.element.children.length) {
|
||||||
|
this.element.removeChild(this.element.children[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const msg = $el('div', {id:'custom-message'},
|
||||||
|
[$el('br'),
|
||||||
|
'The custom node DB is currently being updated, and updates to custom nodes are being checked for.',
|
||||||
|
$el('br')]);
|
||||||
|
msg.style.height = '100px';
|
||||||
|
msg.style.verticalAlign = 'middle';
|
||||||
|
this.element.appendChild(msg);
|
||||||
|
|
||||||
|
// invalidate
|
||||||
this.data = (await getAlterList()).items;
|
this.data = (await getAlterList()).items;
|
||||||
|
|
||||||
|
this.element.removeChild(msg);
|
||||||
|
|
||||||
while (this.element.children.length) {
|
while (this.element.children.length) {
|
||||||
this.element.removeChild(this.element.children[0]);
|
this.element.removeChild(this.element.children[0]);
|
||||||
}
|
}
|
||||||
@ -372,14 +440,23 @@ class AlternativesInstaller extends ComfyDialog {
|
|||||||
|
|
||||||
if(data.custom_node) {
|
if(data.custom_node) {
|
||||||
var installBtn = document.createElement('button');
|
var installBtn = document.createElement('button');
|
||||||
|
var installBtn2 = null;
|
||||||
|
|
||||||
this.install_buttons.push(installBtn);
|
this.install_buttons.push(installBtn);
|
||||||
|
|
||||||
switch(data.custom_node.installed) {
|
switch(data.custom_node.installed) {
|
||||||
|
case 'Update':
|
||||||
|
installBtn2 = document.createElement('button');
|
||||||
|
installBtn2.innerHTML = 'Update';
|
||||||
|
installBtn2.style.backgroundColor = 'blue';
|
||||||
|
this.install_buttons.push(installBtn2);
|
||||||
|
|
||||||
|
installBtn.innerHTML = 'Uninstall';
|
||||||
|
installBtn.style.backgroundColor = 'red';
|
||||||
|
break;
|
||||||
case 'True':
|
case 'True':
|
||||||
installBtn.innerHTML = 'Installed';
|
installBtn.innerHTML = 'Uninstall';
|
||||||
installBtn.style.backgroundColor = 'green';
|
installBtn.style.backgroundColor = 'red';
|
||||||
installBtn.disabled = true;
|
|
||||||
break;
|
break;
|
||||||
case 'False':
|
case 'False':
|
||||||
installBtn.innerHTML = 'Install';
|
installBtn.innerHTML = 'Install';
|
||||||
@ -387,11 +464,26 @@ class AlternativesInstaller extends ComfyDialog {
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
installBtn.innerHTML = 'Try Install';
|
installBtn.innerHTML = 'Try Install';
|
||||||
installBtn.style.backgroundColor = 'brown';
|
installBtn.style.backgroundColor = 'silver';
|
||||||
|
}
|
||||||
|
|
||||||
|
if(installBtn2 != null) {
|
||||||
|
installBtn2.addEventListener('click', function() {
|
||||||
|
install_custom_node(data.custom_node, AlternativesInstaller.instance, 'update');
|
||||||
|
});
|
||||||
|
|
||||||
|
data6.appendChild(installBtn2);
|
||||||
}
|
}
|
||||||
|
|
||||||
installBtn.addEventListener('click', function() {
|
installBtn.addEventListener('click', function() {
|
||||||
install_custom_node(data.custom_node, AlternativesInstaller.instance);
|
if(this.innerHTML == 'Uninstall') {
|
||||||
|
if (confirm(`Are you sure uninstall ${data.title}?`)) {
|
||||||
|
install_custom_node(data.custom_node, AlternativesInstaller.instance, 'uninstall');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
install_custom_node(data.custom_node, AlternativesInstaller.instance, 'install');
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
data6.appendChild(installBtn);
|
data6.appendChild(installBtn);
|
||||||
@ -476,11 +568,13 @@ class ModelInstaller extends ComfyDialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
startInstall(target) {
|
startInstall(target) {
|
||||||
this.updateMessage(`<BR><font color="green">Installing '${target.name}'</font>`);
|
const self = ModelInstaller.instance;
|
||||||
|
|
||||||
for(let i in this.install_buttons) {
|
self.updateMessage(`<BR><font color="green">Installing '${target.name}'</font>`);
|
||||||
this.install_buttons[i].disabled = true;
|
|
||||||
this.install_buttons[i].style.backgroundColor = 'gray';
|
for(let i in self.install_buttons) {
|
||||||
|
self.install_buttons[i].disabled = true;
|
||||||
|
self.install_buttons[i].style.backgroundColor = 'gray';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user