Merge dd3546164a into ae05379cc9
This commit is contained in:
commit
668c64d3be
|
|
@ -267,7 +267,7 @@ temp_path_cleanup_on_launch = get_config_item_or_set_default(
|
||||||
)
|
)
|
||||||
default_base_model_name = default_model = get_config_item_or_set_default(
|
default_base_model_name = default_model = get_config_item_or_set_default(
|
||||||
key='default_model',
|
key='default_model',
|
||||||
default_value='model.safetensors',
|
default_value='None',
|
||||||
validator=lambda x: isinstance(x, str),
|
validator=lambda x: isinstance(x, str),
|
||||||
expected_type=str
|
expected_type=str
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -267,12 +267,15 @@ def refresh_everything(refiner_model_name, base_model_name, loras,
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
refresh_everything(
|
if modules.config.default_base_model_name != 'None':
|
||||||
refiner_model_name=modules.config.default_refiner_model_name,
|
refresh_everything(
|
||||||
base_model_name=modules.config.default_base_model_name,
|
refiner_model_name=modules.config.default_refiner_model_name,
|
||||||
loras=get_enabled_loras(modules.config.default_loras),
|
base_model_name=modules.config.default_base_model_name,
|
||||||
vae_name=modules.config.default_vae,
|
loras=get_enabled_loras(modules.config.default_loras),
|
||||||
)
|
vae_name=modules.config.default_vae,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
print('[Startup] Skipping model load (default_base_model_name is "None").')
|
||||||
|
|
||||||
|
|
||||||
@torch.no_grad()
|
@torch.no_grad()
|
||||||
|
|
|
||||||
|
|
@ -103,7 +103,7 @@ sdxl_aspect_ratios = [
|
||||||
'896*1152', '896*1088', '960*1088', '960*1024', '1024*1024', '1024*960',
|
'896*1152', '896*1088', '960*1088', '960*1024', '1024*1024', '1024*960',
|
||||||
'1088*960', '1088*896', '1152*896', '1152*832', '1216*832', '1280*768',
|
'1088*960', '1088*896', '1152*896', '1152*832', '1216*832', '1280*768',
|
||||||
'1344*768', '1344*704', '1408*704', '1472*704', '1536*640', '1600*640',
|
'1344*768', '1344*704', '1408*704', '1472*704', '1536*640', '1600*640',
|
||||||
'1664*576', '1728*576'
|
'1664*576', '1728*576', '1080*1920', '1920*1080'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,60 +1,13 @@
|
||||||
{
|
{
|
||||||
"default_model": "juggernautXL_v8Rundiffusion.safetensors",
|
|
||||||
"default_refiner": "None",
|
|
||||||
"default_refiner_switch": 0.5,
|
"default_refiner_switch": 0.5,
|
||||||
"default_loras": [
|
|
||||||
[
|
|
||||||
true,
|
|
||||||
"sd_xl_offset_example-lora_1.0.safetensors",
|
|
||||||
0.1
|
|
||||||
],
|
|
||||||
[
|
|
||||||
true,
|
|
||||||
"None",
|
|
||||||
1.0
|
|
||||||
],
|
|
||||||
[
|
|
||||||
true,
|
|
||||||
"None",
|
|
||||||
1.0
|
|
||||||
],
|
|
||||||
[
|
|
||||||
true,
|
|
||||||
"None",
|
|
||||||
1.0
|
|
||||||
],
|
|
||||||
[
|
|
||||||
true,
|
|
||||||
"None",
|
|
||||||
1.0
|
|
||||||
]
|
|
||||||
],
|
|
||||||
"default_cfg_scale": 4.0,
|
"default_cfg_scale": 4.0,
|
||||||
"default_sample_sharpness": 2.0,
|
"default_sample_sharpness": 2.0,
|
||||||
"default_sampler": "dpmpp_2m_sde_gpu",
|
"default_sampler": "dpmpp_2m_sde_gpu",
|
||||||
"default_scheduler": "karras",
|
"default_scheduler": "karras",
|
||||||
"default_performance": "Speed",
|
"default_performance": "Quality",
|
||||||
"default_prompt": "",
|
"default_prompt": "",
|
||||||
"default_prompt_negative": "",
|
"default_prompt_negative": "",
|
||||||
"default_styles": [
|
"default_styles": [],
|
||||||
"Fooocus V2",
|
"default_aspect_ratio": "1080*1920",
|
||||||
"Fooocus Enhance",
|
"default_overwrite_step": -1
|
||||||
"Fooocus Sharp"
|
|
||||||
],
|
|
||||||
"default_aspect_ratio": "1152*896",
|
|
||||||
"default_overwrite_step": -1,
|
|
||||||
"checkpoint_downloads": {
|
|
||||||
"juggernautXL_v8Rundiffusion.safetensors": "https://huggingface.co/lllyasviel/fav_models/resolve/main/fav/juggernautXL_v8Rundiffusion.safetensors"
|
|
||||||
},
|
|
||||||
"embeddings_downloads": {},
|
|
||||||
"lora_downloads": {
|
|
||||||
"sd_xl_offset_example-lora_1.0.safetensors": "https://huggingface.co/stabilityai/stable-diffusion-xl-base-1.0/resolve/main/sd_xl_offset_example-lora_1.0.safetensors"
|
|
||||||
},
|
|
||||||
"previous_default_models": [
|
|
||||||
"juggernautXL_version8Rundiffusion.safetensors",
|
|
||||||
"juggernautXL_version7Rundiffusion.safetensors",
|
|
||||||
"juggernautXL_v7Rundiffusion.safetensors",
|
|
||||||
"juggernautXL_version6Rundiffusion.safetensors",
|
|
||||||
"juggernautXL_v6Rundiffusion.safetensors"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
52
webui.py
52
webui.py
|
|
@ -24,6 +24,11 @@ from modules.ui_gradio_extensions import reload_javascript
|
||||||
from modules.auth import auth_enabled, check_auth
|
from modules.auth import auth_enabled, check_auth
|
||||||
from modules.util import is_json
|
from modules.util import is_json
|
||||||
|
|
||||||
|
import webui_others
|
||||||
|
import os
|
||||||
|
from urllib.parse import urlparse, unquote
|
||||||
|
from modules.model_loader import load_file_from_url
|
||||||
|
|
||||||
def get_task(*args):
|
def get_task(*args):
|
||||||
args = list(args)
|
args = list(args)
|
||||||
args.pop(0)
|
args.pop(0)
|
||||||
|
|
@ -556,7 +561,7 @@ with shared.gradio_root:
|
||||||
outputs=enhance_input_panel, queue=False, show_progress=False, _js=switch_js)
|
outputs=enhance_input_panel, queue=False, show_progress=False, _js=switch_js)
|
||||||
|
|
||||||
with gr.Column(scale=1, visible=modules.config.default_advanced_checkbox) as advanced_column:
|
with gr.Column(scale=1, visible=modules.config.default_advanced_checkbox) as advanced_column:
|
||||||
with gr.Tab(label='Settings'):
|
with gr.Tab(label='Settings') as settings_tab:
|
||||||
if not args_manager.args.disable_preset_selection:
|
if not args_manager.args.disable_preset_selection:
|
||||||
preset_selection = gr.Dropdown(label='Preset',
|
preset_selection = gr.Dropdown(label='Preset',
|
||||||
choices=modules.config.available_presets,
|
choices=modules.config.available_presets,
|
||||||
|
|
@ -651,10 +656,10 @@ with shared.gradio_root:
|
||||||
show_progress=False).then(
|
show_progress=False).then(
|
||||||
lambda: None, _js='()=>{refresh_style_localization();}')
|
lambda: None, _js='()=>{refresh_style_localization();}')
|
||||||
|
|
||||||
with gr.Tab(label='Models'):
|
with gr.Tab(label='Models') as model_tab:
|
||||||
with gr.Group():
|
with gr.Group():
|
||||||
with gr.Row():
|
with gr.Row():
|
||||||
base_model = gr.Dropdown(label='Base Model (SDXL only)', choices=modules.config.model_filenames, value=modules.config.default_base_model_name, show_label=True)
|
base_model = gr.Dropdown(label='Base Model (SDXL only)', choices=['None'] + modules.config.model_filenames, value=modules.config.default_base_model_name, show_label=True)
|
||||||
refiner_model = gr.Dropdown(label='Refiner (SDXL or SD 1.5)', choices=['None'] + modules.config.model_filenames, value=modules.config.default_refiner_model_name, show_label=True)
|
refiner_model = gr.Dropdown(label='Refiner (SDXL or SD 1.5)', choices=['None'] + modules.config.model_filenames, value=modules.config.default_refiner_model_name, show_label=True)
|
||||||
|
|
||||||
refiner_switch = gr.Slider(label='Refiner Switch At', minimum=0.1, maximum=1.0, step=0.0001,
|
refiner_switch = gr.Slider(label='Refiner Switch At', minimum=0.1, maximum=1.0, step=0.0001,
|
||||||
|
|
@ -870,7 +875,7 @@ with shared.gradio_root:
|
||||||
|
|
||||||
def refresh_files_clicked():
|
def refresh_files_clicked():
|
||||||
modules.config.update_files()
|
modules.config.update_files()
|
||||||
results = [gr.update(choices=modules.config.model_filenames)]
|
results = [gr.update(choices=['None'] + modules.config.model_filenames)]
|
||||||
results += [gr.update(choices=['None'] + modules.config.model_filenames)]
|
results += [gr.update(choices=['None'] + modules.config.model_filenames)]
|
||||||
results += [gr.update(choices=[flags.default_vae] + modules.config.vae_filenames)]
|
results += [gr.update(choices=[flags.default_vae] + modules.config.vae_filenames)]
|
||||||
if not args_manager.args.disable_preset_selection:
|
if not args_manager.args.disable_preset_selection:
|
||||||
|
|
@ -885,6 +890,43 @@ with shared.gradio_root:
|
||||||
refresh_files_output += [preset_selection]
|
refresh_files_output += [preset_selection]
|
||||||
refresh_files.click(refresh_files_clicked, [], refresh_files_output + lora_ctrls,
|
refresh_files.click(refresh_files_clicked, [], refresh_files_output + lora_ctrls,
|
||||||
queue=False, show_progress=False)
|
queue=False, show_progress=False)
|
||||||
|
|
||||||
|
advanced_checkbox.select(
|
||||||
|
fn=refresh_files_clicked,
|
||||||
|
inputs=[],
|
||||||
|
outputs=refresh_files_output + lora_ctrls,
|
||||||
|
queue=False,
|
||||||
|
show_progress=False
|
||||||
|
)
|
||||||
|
|
||||||
|
settings_tab.select(
|
||||||
|
fn=refresh_files_clicked,
|
||||||
|
inputs=[],
|
||||||
|
outputs=refresh_files_output + lora_ctrls,
|
||||||
|
queue=False,
|
||||||
|
show_progress=False
|
||||||
|
)
|
||||||
|
|
||||||
|
model_tab.select(
|
||||||
|
fn=refresh_files_clicked,
|
||||||
|
inputs=[],
|
||||||
|
outputs=refresh_files_output + lora_ctrls,
|
||||||
|
queue=False,
|
||||||
|
show_progress=False
|
||||||
|
)
|
||||||
|
|
||||||
|
webui_others.build_others_tab(
|
||||||
|
prompt=prompt,
|
||||||
|
negative_prompt=negative_prompt,
|
||||||
|
aspect_ratio=aspect_ratios_selection,
|
||||||
|
performance=performance_selection,
|
||||||
|
styles=style_selections,
|
||||||
|
base_model=base_model,
|
||||||
|
refiner_model=refiner_model,
|
||||||
|
refiner_switch=refiner_switch,
|
||||||
|
image_number=image_number,
|
||||||
|
lora_ctrls=lora_ctrls
|
||||||
|
)
|
||||||
|
|
||||||
state_is_generating = gr.State(False)
|
state_is_generating = gr.State(False)
|
||||||
|
|
||||||
|
|
@ -1125,4 +1167,4 @@ shared.gradio_root.launch(
|
||||||
auth=check_auth if (args_manager.args.share or args_manager.args.listen) and auth_enabled else None,
|
auth=check_auth if (args_manager.args.share or args_manager.args.listen) and auth_enabled else None,
|
||||||
allowed_paths=[modules.config.path_outputs],
|
allowed_paths=[modules.config.path_outputs],
|
||||||
blocked_paths=[constants.AUTH_FILENAME]
|
blocked_paths=[constants.AUTH_FILENAME]
|
||||||
)
|
)
|
||||||
|
|
@ -0,0 +1,280 @@
|
||||||
|
# webui_others.py
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import requests
|
||||||
|
from urllib.parse import urlparse, unquote
|
||||||
|
import gradio as gr
|
||||||
|
import modules.config
|
||||||
|
from modules.model_loader import load_file_from_url
|
||||||
|
|
||||||
|
def build_others_tab(
|
||||||
|
prompt,
|
||||||
|
negative_prompt,
|
||||||
|
aspect_ratio,
|
||||||
|
performance,
|
||||||
|
styles,
|
||||||
|
base_model,
|
||||||
|
refiner_model,
|
||||||
|
refiner_switch,
|
||||||
|
image_number,
|
||||||
|
lora_ctrls
|
||||||
|
):
|
||||||
|
with gr.Tab(label="Others") as others_tab:
|
||||||
|
with gr.Tab(label="Download"):
|
||||||
|
file_input_path = gr.Textbox(
|
||||||
|
label="File Path or URL",
|
||||||
|
placeholder="Enter full path to file or downloadable URL",
|
||||||
|
lines=1,
|
||||||
|
)
|
||||||
|
|
||||||
|
destination_folder = gr.Dropdown(
|
||||||
|
label="Target Folder",
|
||||||
|
choices=[
|
||||||
|
modules.config.paths_checkpoints[0],
|
||||||
|
modules.config.paths_loras[0],
|
||||||
|
modules.config.path_embeddings,
|
||||||
|
modules.config.path_vae,
|
||||||
|
],
|
||||||
|
value=modules.config.paths_checkpoints[0],
|
||||||
|
)
|
||||||
|
|
||||||
|
download_result_text = gr.Textbox(
|
||||||
|
label="Download Status", interactive=False
|
||||||
|
)
|
||||||
|
download_file_button = gr.Button(
|
||||||
|
value="\u2b07 Download",
|
||||||
|
variant="secondary",
|
||||||
|
elem_classes="refresh_button",
|
||||||
|
)
|
||||||
|
|
||||||
|
def perform_download(file_url_or_path, target_directory):
|
||||||
|
try:
|
||||||
|
if isinstance(target_directory, tuple):
|
||||||
|
target_directory = target_directory[1]
|
||||||
|
|
||||||
|
if file_url_or_path.startswith(("http://", "https://")):
|
||||||
|
response = requests.get(file_url_or_path, stream=True)
|
||||||
|
response.raise_for_status()
|
||||||
|
content_disposition = response.headers.get(
|
||||||
|
"Content-Disposition", ""
|
||||||
|
)
|
||||||
|
if "filename=" in content_disposition:
|
||||||
|
filename = content_disposition.split("filename=")[
|
||||||
|
-1
|
||||||
|
].strip('"')
|
||||||
|
else:
|
||||||
|
parsed_url = urlparse(file_url_or_path)
|
||||||
|
filename = unquote(os.path.basename(parsed_url.path))
|
||||||
|
downloaded_path = load_file_from_url(
|
||||||
|
file_url_or_path,
|
||||||
|
model_dir=target_directory,
|
||||||
|
progress=True,
|
||||||
|
file_name=filename,
|
||||||
|
)
|
||||||
|
return f"\u2705 Downloaded to: {downloaded_path}"
|
||||||
|
|
||||||
|
if os.path.isfile(file_url_or_path):
|
||||||
|
filename = os.path.basename(file_url_or_path)
|
||||||
|
destination_path = os.path.join(target_directory, filename)
|
||||||
|
shutil.copy(file_url_or_path, destination_path)
|
||||||
|
return f"\u2705 Copied to: {destination_path}"
|
||||||
|
|
||||||
|
return "\u274c Error: File not found or invalid input."
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
return f"\u274c Failed: {str(e)}"
|
||||||
|
|
||||||
|
download_file_button.click(
|
||||||
|
fn=perform_download,
|
||||||
|
inputs=[file_input_path, destination_folder],
|
||||||
|
outputs=[download_result_text],
|
||||||
|
)
|
||||||
|
|
||||||
|
with gr.Tab(label="Delete"):
|
||||||
|
delete_folder_dropdown = gr.Dropdown(
|
||||||
|
label="Select Folder",
|
||||||
|
choices=[
|
||||||
|
modules.config.paths_checkpoints[0],
|
||||||
|
modules.config.paths_loras[0],
|
||||||
|
modules.config.path_embeddings,
|
||||||
|
modules.config.path_vae,
|
||||||
|
modules.config.get_dir_or_set_default("path_presets", "../presets"),
|
||||||
|
],
|
||||||
|
value=modules.config.paths_checkpoints[0],
|
||||||
|
)
|
||||||
|
|
||||||
|
file_list_dropdown = gr.Dropdown(
|
||||||
|
label="Select File to Delete", choices=[], multiselect=True
|
||||||
|
)
|
||||||
|
delete_button = gr.Button(
|
||||||
|
value="\U0001f5d1 Delete Selected File(s)", variant="stop"
|
||||||
|
)
|
||||||
|
delete_status = gr.Textbox(
|
||||||
|
visible=True, interactive=False, label="Delete Status"
|
||||||
|
)
|
||||||
|
|
||||||
|
def update_file_list(folder):
|
||||||
|
try:
|
||||||
|
files = [
|
||||||
|
f
|
||||||
|
for f in os.listdir(folder)
|
||||||
|
if os.path.isfile(os.path.join(folder, f))
|
||||||
|
]
|
||||||
|
return gr.update(choices=files, value=[])
|
||||||
|
except Exception as e:
|
||||||
|
return gr.update(choices=[], value=[])
|
||||||
|
|
||||||
|
def delete_selected_files(folder, selected_files):
|
||||||
|
deleted = []
|
||||||
|
errors = []
|
||||||
|
|
||||||
|
for fname in selected_files:
|
||||||
|
try:
|
||||||
|
file_path = os.path.join(folder, fname)
|
||||||
|
if os.path.isfile(file_path):
|
||||||
|
os.remove(file_path)
|
||||||
|
deleted.append(fname)
|
||||||
|
else:
|
||||||
|
errors.append(fname)
|
||||||
|
except Exception as e:
|
||||||
|
errors.append(f"{fname} (error: {e})")
|
||||||
|
|
||||||
|
status = ""
|
||||||
|
if deleted:
|
||||||
|
status += f"\u2705 Deleted: {', '.join(deleted)}. "
|
||||||
|
if errors:
|
||||||
|
status += f"\u274c Failed: {', '.join(errors)}"
|
||||||
|
if not deleted and not errors:
|
||||||
|
status = "\u26a0\ufe0f No files selected."
|
||||||
|
|
||||||
|
try:
|
||||||
|
files = [
|
||||||
|
f
|
||||||
|
for f in os.listdir(folder)
|
||||||
|
if os.path.isfile(os.path.join(folder, f))
|
||||||
|
]
|
||||||
|
except Exception:
|
||||||
|
files = []
|
||||||
|
|
||||||
|
return status.strip(), gr.update(choices=files, value=[])
|
||||||
|
|
||||||
|
delete_folder_dropdown.change(
|
||||||
|
update_file_list,
|
||||||
|
inputs=[delete_folder_dropdown],
|
||||||
|
outputs=[file_list_dropdown],
|
||||||
|
)
|
||||||
|
delete_button.click(
|
||||||
|
delete_selected_files,
|
||||||
|
inputs=[delete_folder_dropdown, file_list_dropdown],
|
||||||
|
outputs=[delete_status, file_list_dropdown],
|
||||||
|
)
|
||||||
|
|
||||||
|
with gr.Tab(label="Backup/Restore"):
|
||||||
|
with gr.Tab(label="Preset"):
|
||||||
|
with gr.Row():
|
||||||
|
backup_name = gr.Textbox(label="Backup Filename (no extension)", placeholder="e.g. my_config_backup")
|
||||||
|
backup_button = gr.Button(value="\u2B06 Backup Settings")
|
||||||
|
backup_file = gr.File(label="Download .json", interactive=False)
|
||||||
|
|
||||||
|
def clean_aspect_ratio(value):
|
||||||
|
if not value:
|
||||||
|
return None
|
||||||
|
raw = value.split(" ")[0]
|
||||||
|
return raw.replace("×", "*") # convert Unicode × to ASCII *
|
||||||
|
|
||||||
|
def backup_selected_settings(
|
||||||
|
filename,
|
||||||
|
prompt, negative_prompt, aspect_ratio, performance, styles,
|
||||||
|
base_model, refiner_model, refiner_switch, image_number,
|
||||||
|
*lora_ctrls
|
||||||
|
):
|
||||||
|
import json
|
||||||
|
if not filename:
|
||||||
|
return None
|
||||||
|
|
||||||
|
config = {
|
||||||
|
"default_prompt": prompt,
|
||||||
|
"default_prompt_negative": negative_prompt,
|
||||||
|
"default_aspect_ratio": clean_aspect_ratio(aspect_ratio),
|
||||||
|
"default_performance": performance,
|
||||||
|
"default_styles": styles,
|
||||||
|
"default_model": base_model,
|
||||||
|
"default_refiner": refiner_model,
|
||||||
|
"default_refiner_switch": refiner_switch,
|
||||||
|
"default_image_number": image_number
|
||||||
|
}
|
||||||
|
|
||||||
|
loras = []
|
||||||
|
for i in range(0, len(lora_ctrls), 3):
|
||||||
|
enabled = lora_ctrls[i]
|
||||||
|
model = lora_ctrls[i + 1]
|
||||||
|
weight = lora_ctrls[i + 2]
|
||||||
|
if model and model != "None":
|
||||||
|
loras.append([enabled, model, weight])
|
||||||
|
|
||||||
|
if loras:
|
||||||
|
config["default_loras"] = loras
|
||||||
|
|
||||||
|
config = {k: v for k, v in config.items() if v not in [None, "", [], "None"]}
|
||||||
|
|
||||||
|
out_path = os.path.join("outputs", f"{filename}.json")
|
||||||
|
with open(out_path, "w") as f:
|
||||||
|
json.dump(config, f, indent=2)
|
||||||
|
|
||||||
|
return out_path
|
||||||
|
|
||||||
|
backup_button.click(
|
||||||
|
fn=backup_selected_settings,
|
||||||
|
inputs=[
|
||||||
|
backup_name,
|
||||||
|
prompt,
|
||||||
|
negative_prompt,
|
||||||
|
aspect_ratio,
|
||||||
|
performance,
|
||||||
|
styles,
|
||||||
|
base_model,
|
||||||
|
refiner_model,
|
||||||
|
refiner_switch,
|
||||||
|
image_number,
|
||||||
|
] + lora_ctrls,
|
||||||
|
outputs=[backup_file],
|
||||||
|
)
|
||||||
|
|
||||||
|
with gr.Tab(label="Restore"):
|
||||||
|
with gr.Row():
|
||||||
|
restore_file = gr.File(label="Upload Config File (.json)", file_types=[".json"])
|
||||||
|
restore_button = gr.Button(value="\u267B️ Restore to Presets Folder")
|
||||||
|
restore_status = gr.Textbox(label="Status", interactive=False)
|
||||||
|
|
||||||
|
def restore_config_file(file_obj):
|
||||||
|
try:
|
||||||
|
if file_obj is None:
|
||||||
|
return "\u26A0 No file selected."
|
||||||
|
filename = os.path.basename(file_obj.name)
|
||||||
|
presets_dir = os.path.join("presets")
|
||||||
|
os.makedirs(presets_dir, exist_ok=True)
|
||||||
|
destination = os.path.join(presets_dir, filename)
|
||||||
|
shutil.copy(file_obj.name, destination)
|
||||||
|
return f"\u2705 Saved to presets/{filename}"
|
||||||
|
except Exception as e:
|
||||||
|
return f"\u274C Failed to restore: {e}"
|
||||||
|
|
||||||
|
restore_button.click(
|
||||||
|
fn=restore_config_file,
|
||||||
|
inputs=[restore_file],
|
||||||
|
outputs=[restore_status]
|
||||||
|
)
|
||||||
|
|
||||||
|
gr.Markdown(
|
||||||
|
"You can backup your current settings and restore them later. "
|
||||||
|
"This is useful for saving configurations or sharing with others."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
others_tab.select(
|
||||||
|
fn=update_file_list,
|
||||||
|
inputs=[delete_folder_dropdown],
|
||||||
|
outputs=[file_list_dropdown],
|
||||||
|
queue=False,
|
||||||
|
show_progress=False,
|
||||||
|
)
|
||||||
Loading…
Reference in New Issue