mirror of
https://github.com/lllyasviel/stable-diffusion-webui-forge.git
synced 2026-07-21 21:01:24 +08:00
lint
This commit is contained in:
parent
598e10784b
commit
fa4155fc2e
316
modules/ui.py
316
modules/ui.py
@ -2,83 +2,74 @@ import datetime
|
||||
import mimetypes
|
||||
import os
|
||||
import sys
|
||||
from functools import reduce
|
||||
import warnings
|
||||
from contextlib import ExitStack
|
||||
from functools import reduce
|
||||
|
||||
import gradio as gr
|
||||
import gradio.utils
|
||||
from gradio.components.image_editor import Brush
|
||||
from PIL import Image, PngImagePlugin # noqa: F401
|
||||
from modules.call_queue import wrap_gradio_gpu_call, wrap_queued_call, wrap_gradio_call, wrap_gradio_call_no_job # noqa: F401
|
||||
|
||||
from modules import gradio_extensions, sd_schedulers # noqa: F401
|
||||
from modules import sd_hijack, sd_models, script_callbacks, paths_internal, ui_extensions, extra_networks, ui_common, ui_postprocessing, progress, ui_loadsave, shared_items, ui_settings, timer, sysinfo, ui_checkpoint_merger, scripts, sd_samplers, processing, ui_extra_networks, ui_toprow, launch_utils
|
||||
from modules.ui_components import FormRow, FormGroup, ToolButton, FormHTML, InputAccordion, ResizeHandleRow
|
||||
from modules.paths import script_path
|
||||
from modules.ui_common import create_refresh_button
|
||||
from modules.ui_gradio_extensions import reload_javascript
|
||||
|
||||
from modules.shared import opts, cmd_opts
|
||||
|
||||
import modules.infotext_utils as parameters_copypaste
|
||||
import modules.shared as shared
|
||||
from modules import prompt_parser
|
||||
from modules.infotext_utils import image_from_url_text, PasteField
|
||||
from modules_forge.forge_canvas.canvas import ForgeCanvas, canvas_head
|
||||
from modules_forge import main_entry
|
||||
import modules.processing_scripts.comments as comments
|
||||
|
||||
import modules.shared as shared
|
||||
from modules import extra_networks, gradio_extensions, launch_utils, paths_internal, processing, progress, prompt_parser, script_callbacks, scripts, sd_hijack, sd_models, sd_samplers, sd_schedulers, shared_items, sysinfo, timer, ui_checkpoint_merger, ui_common, ui_extensions, ui_extra_networks, ui_loadsave, ui_postprocessing, ui_settings, ui_toprow # noqa: F401
|
||||
from modules.call_queue import wrap_gradio_call, wrap_gradio_call_no_job, wrap_gradio_gpu_call, wrap_queued_call # noqa: F401
|
||||
from modules.infotext_utils import PasteField, image_from_url_text
|
||||
from modules.paths import script_path
|
||||
from modules.shared import cmd_opts, opts
|
||||
from modules.ui_common import create_refresh_button # noqa: F401
|
||||
from modules.ui_components import FormGroup, FormHTML, FormRow, InputAccordion, ResizeHandleRow, ToolButton
|
||||
from modules.ui_gradio_extensions import reload_javascript
|
||||
from modules_forge import main_entry
|
||||
from modules_forge.forge_canvas.canvas import ForgeCanvas, canvas_head
|
||||
|
||||
create_setting_component = ui_settings.create_setting_component
|
||||
|
||||
warnings.filterwarnings("default" if opts.show_warnings else "ignore", category=UserWarning)
|
||||
warnings.filterwarnings("default" if opts.show_gradio_deprecation_warnings else "ignore", category=gradio_extensions.GradioDeprecationWarning)
|
||||
if not opts.show_warnings:
|
||||
warnings.filterwarnings("ignore", category=UserWarning)
|
||||
warnings.filterwarnings("ignore", category=FutureWarning)
|
||||
if not opts.show_gradio_deprecation_warnings:
|
||||
warnings.filterwarnings("ignore", category=gradio_extensions.GradioDeprecationWarning)
|
||||
|
||||
# this is a fix for Windows users. Without it, javascript files will be served with text/html content-type and the browser will not show any UI
|
||||
mimetypes.init()
|
||||
mimetypes.add_type('application/javascript', '.js')
|
||||
mimetypes.add_type('application/javascript', '.mjs')
|
||||
mimetypes.add_type("application/javascript", ".js")
|
||||
mimetypes.add_type("application/javascript", ".mjs")
|
||||
|
||||
# Likewise, add explicit content-type header for certain missing image types
|
||||
mimetypes.add_type('image/webp', '.webp')
|
||||
mimetypes.add_type('image/avif', '.avif')
|
||||
mimetypes.add_type("image/webp", ".webp")
|
||||
mimetypes.add_type("image/avif", ".avif")
|
||||
|
||||
if not cmd_opts.share and not cmd_opts.listen:
|
||||
# fix gradio phoning home
|
||||
gradio.utils.version_check = lambda: None
|
||||
gradio.utils.get_local_ip_address = lambda: '127.0.0.1'
|
||||
gradio.utils.get_local_ip_address = lambda: "127.0.0.1"
|
||||
|
||||
if cmd_opts.ngrok is not None:
|
||||
import modules.ngrok as ngrok
|
||||
print('ngrok authtoken detected, trying to connect...')
|
||||
ngrok.connect(
|
||||
cmd_opts.ngrok,
|
||||
cmd_opts.port if cmd_opts.port is not None else 7860,
|
||||
cmd_opts.ngrok_options
|
||||
)
|
||||
|
||||
print("ngrok authtoken detected, trying to connect...")
|
||||
ngrok.connect(cmd_opts.ngrok, cmd_opts.port if cmd_opts.port is not None else 7860, cmd_opts.ngrok_options)
|
||||
|
||||
|
||||
def gr_show(visible=True):
|
||||
return {"visible": visible, "__type__": "update"}
|
||||
|
||||
|
||||
sample_img2img = "assets/stable-samples/img2img/sketch-mountains-input.jpg"
|
||||
sample_img2img = sample_img2img if os.path.exists(sample_img2img) else None
|
||||
|
||||
# Using constants for these since the variation selector isn't visible.
|
||||
# Important that they exactly match script.js for tooltip to work.
|
||||
random_symbol = '\U0001f3b2\ufe0f' # 🎲️
|
||||
reuse_symbol = '\u267b\ufe0f' # ♻️
|
||||
paste_symbol = '\u2199\ufe0f' # ↙
|
||||
refresh_symbol = '\U0001f504' # 🔄
|
||||
save_style_symbol = '\U0001f4be' # 💾
|
||||
apply_style_symbol = '\U0001f4cb' # 📋
|
||||
clear_prompt_symbol = '\U0001f5d1\ufe0f' # 🗑️
|
||||
extra_networks_symbol = '\U0001F3B4' # 🎴
|
||||
switch_values_symbol = '\U000021C5' # ⇅
|
||||
restore_progress_symbol = '\U0001F300' # 🌀
|
||||
detect_image_size_symbol = '\U0001F4D0' # 📐
|
||||
random_symbol = "\U0001f3b2\ufe0f" # 🎲️
|
||||
reuse_symbol = "\u267b\ufe0f" # ♻️
|
||||
paste_symbol = "\u2199\ufe0f" # ↙
|
||||
refresh_symbol = "\U0001f504" # 🔄
|
||||
save_style_symbol = "\U0001f4be" # 💾
|
||||
apply_style_symbol = "\U0001f4cb" # 📋
|
||||
clear_prompt_symbol = "\U0001f5d1\ufe0f" # 🗑️
|
||||
extra_networks_symbol = "\U0001f3b4" # 🎴
|
||||
switch_values_symbol = "\U000021c5" # ⇅
|
||||
restore_progress_symbol = "\U0001f300" # 🌀
|
||||
detect_image_size_symbol = "\U0001f4d0" # 📐
|
||||
|
||||
|
||||
plaintext_to_html = ui_common.plaintext_to_html
|
||||
@ -100,7 +91,7 @@ def calc_resolution_hires(enable, width, height, hr_scale, hr_resize_x, hr_resiz
|
||||
new_width = p.hr_resize_x or p.hr_upscale_to_x
|
||||
new_height = p.hr_resize_y or p.hr_upscale_to_y
|
||||
|
||||
new_width -= new_width % 8 # note: hardcoded latent size 8
|
||||
new_width -= new_width % 8 # note: hardcoded latent size 8
|
||||
new_height -= new_height % 8
|
||||
|
||||
return f"from <span class='resolution'>{p.width}x{p.height}</span> to <span class='resolution'>{new_width}x{new_height}</span>"
|
||||
@ -113,22 +104,12 @@ def resize_from_to_html(width, height, scale_by):
|
||||
if not target_width or not target_height:
|
||||
return "no image selected"
|
||||
|
||||
target_width -= target_width % 8 # note: hardcoded latent size 8
|
||||
target_width -= target_width % 8 # note: hardcoded latent size 8
|
||||
target_height -= target_height % 8
|
||||
|
||||
return f"resize: from <span class='resolution'>{width}x{height}</span> to <span class='resolution'>{target_width}x{target_height}</span>"
|
||||
|
||||
|
||||
def connect_clear_prompt(button):
|
||||
"""Given clear button, prompt, and token_counter objects, setup clear prompt button click event"""
|
||||
button.click(
|
||||
_js="clear_prompt",
|
||||
fn=None,
|
||||
inputs=[],
|
||||
outputs=[],
|
||||
)
|
||||
|
||||
|
||||
def update_token_counter(text, steps, styles, *, is_positive=True):
|
||||
params = script_callbacks.BeforeTokenCounterParams(text, steps, styles, is_positive=is_positive)
|
||||
script_callbacks.before_token_counter_callback(params)
|
||||
@ -164,7 +145,7 @@ def update_token_counter(text, steps, styles, *, is_positive=True):
|
||||
except Exception:
|
||||
return f"<span class='gr-box gr-text-input'>?/?</span>"
|
||||
|
||||
flat_prompts = reduce(lambda list1, list2: list1+list2, prompt_schedules)
|
||||
flat_prompts = reduce(lambda list1, list2: list1 + list2, prompt_schedules)
|
||||
prompts = [prompt_text for step, prompt_text in flat_prompts]
|
||||
token_count, max_length = max([get_prompt_lengths_on_ui(prompt) for prompt in prompts], key=lambda args: args[0])
|
||||
return f"<span class='gr-box gr-text-input'>{token_count}/{max_length}</span>"
|
||||
@ -174,10 +155,6 @@ def update_negative_prompt_token_counter(*args):
|
||||
return update_token_counter(*args, is_positive=False)
|
||||
|
||||
|
||||
def setup_progressbar(*args, **kwargs):
|
||||
pass
|
||||
|
||||
|
||||
def apply_setting(key, value):
|
||||
if value is None:
|
||||
return gr.update()
|
||||
@ -198,7 +175,7 @@ def apply_setting(key, value):
|
||||
return gr.update()
|
||||
|
||||
comp_args = opts.data_labels[key].component_args
|
||||
if comp_args and isinstance(comp_args, dict) and comp_args.get('visible') is False:
|
||||
if comp_args and isinstance(comp_args, dict) and comp_args.get("visible") is False:
|
||||
return
|
||||
|
||||
valtype = type(opts.data_labels[key].default)
|
||||
@ -261,7 +238,7 @@ def create_ui():
|
||||
with ExitStack() as stack:
|
||||
if shared.opts.txt2img_settings_accordion:
|
||||
stack.enter_context(gr.Accordion("Open for Settings", open=False))
|
||||
stack.enter_context(gr.Column(variant='compact', elem_id="txt2img_settings"))
|
||||
stack.enter_context(gr.Column(variant="compact", elem_id="txt2img_settings"))
|
||||
|
||||
scripts.scripts_txt2img.prepare_ui()
|
||||
|
||||
@ -280,20 +257,16 @@ def create_ui():
|
||||
|
||||
if opts.dimensions_and_batch_together:
|
||||
with gr.Column(elem_id="txt2img_column_batch"):
|
||||
batch_count = gr.Slider(minimum=1, step=1, label='Batch count', value=1, elem_id="txt2img_batch_count")
|
||||
batch_size = gr.Slider(minimum=1, maximum=8, step=1, label='Batch size', value=1, elem_id="txt2img_batch_size")
|
||||
batch_count = gr.Slider(minimum=1, step=1, label="Batch count", value=1, elem_id="txt2img_batch_count")
|
||||
batch_size = gr.Slider(minimum=1, maximum=8, step=1, label="Batch size", value=1, elem_id="txt2img_batch_size")
|
||||
|
||||
elif category == "cfg":
|
||||
with gr.Row():
|
||||
distilled_cfg_scale = gr.Slider(minimum=0.0, maximum=30.0, step=0.1, label='Distilled CFG Scale', value=3.5, elem_id="txt2img_distilled_cfg_scale", scale=4)
|
||||
cfg_scale = gr.Slider(minimum=1.0, maximum=30.0, step=0.1, label='CFG Scale', value=7.0, elem_id="txt2img_cfg_scale", scale=4)
|
||||
distilled_cfg_scale = gr.Slider(minimum=0.0, maximum=30.0, step=0.1, label="Distilled CFG Scale", value=3.5, elem_id="txt2img_distilled_cfg_scale", scale=4)
|
||||
cfg_scale = gr.Slider(minimum=1.0, maximum=30.0, step=0.1, label="CFG Scale", value=7.0, elem_id="txt2img_cfg_scale", scale=4)
|
||||
cfg_scale.change(lambda x: gr.update(interactive=(x != 1)), inputs=[cfg_scale], outputs=[toprow.negative_prompt], queue=False, show_progress=False)
|
||||
scripts.scripts_txt2img.setup_ui_for_section(category)
|
||||
|
||||
# elif category == "checkboxes":
|
||||
# with FormRow(elem_classes="checkboxes-row", variant="compact"):
|
||||
# pass
|
||||
|
||||
elif category == "accordions":
|
||||
with gr.Row(elem_id="txt2img_accordions", elem_classes="accordions"):
|
||||
with InputAccordion(False, label="Hires. fix", elem_id="txt2img_hr") as enable_hr:
|
||||
@ -302,8 +275,8 @@ def create_ui():
|
||||
|
||||
with FormRow(elem_id="txt2img_hires_fix_row1", variant="compact"):
|
||||
hr_upscaler = gr.Dropdown(label="Upscaler", elem_id="txt2img_hr_upscaler", choices=[*shared.latent_upscale_modes, *[x.name for x in shared.sd_upscalers]], value=shared.latent_upscale_default_mode)
|
||||
hr_second_pass_steps = gr.Slider(minimum=0, maximum=150, step=1, label='Hires steps', value=0, elem_id="txt2img_hires_steps")
|
||||
denoising_strength = gr.Slider(minimum=0.0, maximum=1.0, step=0.01, label='Denoising strength', value=0.7, elem_id="txt2img_denoising_strength")
|
||||
hr_second_pass_steps = gr.Slider(minimum=0, maximum=150, step=1, label="Hires steps", value=0, elem_id="txt2img_hires_steps")
|
||||
denoising_strength = gr.Slider(minimum=0.0, maximum=1.0, step=0.01, label="Denoising strength", value=0.7, elem_id="txt2img_denoising_strength")
|
||||
|
||||
with FormRow(elem_id="txt2img_hires_fix_row2", variant="compact"):
|
||||
hr_scale = gr.Slider(minimum=1.0, maximum=4.0, step=0.05, label="Upscale by", value=2.0, elem_id="txt2img_hr_scale")
|
||||
@ -315,12 +288,12 @@ def create_ui():
|
||||
hr_cfg = gr.Slider(minimum=1.0, maximum=30.0, step=0.1, label="Hires CFG Scale", value=7.0, elem_id="txt2img_hr_cfg")
|
||||
|
||||
with FormRow(elem_id="txt2img_hires_fix_row3", variant="compact", visible=shared.opts.hires_fix_show_sampler) as hr_checkpoint_container:
|
||||
hr_checkpoint_name = gr.Dropdown(label='Hires Checkpoint', elem_id="hr_checkpoint", choices=["Use same checkpoint"] + modules.sd_models.checkpoint_tiles(use_short=True), value="Use same checkpoint", scale=2)
|
||||
hr_checkpoint_name = gr.Dropdown(label="Hires Checkpoint", elem_id="hr_checkpoint", choices=["Use same checkpoint"] + modules.sd_models.checkpoint_tiles(use_short=True), value="Use same checkpoint", scale=2)
|
||||
|
||||
hr_checkpoint_refresh = ToolButton(value=refresh_symbol)
|
||||
|
||||
def get_additional_modules():
|
||||
modules_list = ['Use same choices']
|
||||
modules_list = ["Use same choices"]
|
||||
if main_entry.module_list == {}:
|
||||
_, modules = main_entry.refresh_models()
|
||||
modules_list += list(modules)
|
||||
@ -334,13 +307,13 @@ def create_ui():
|
||||
modules_list = get_additional_modules()
|
||||
return gr.update(choices=["Use same checkpoint"] + modules.sd_models.checkpoint_tiles(use_short=True)), gr.update(choices=modules_list)
|
||||
|
||||
hr_additional_modules = gr.Dropdown(label='Hires VAE / Text Encoder', elem_id="hr_vae_te", choices=modules_list, value=["Use same choices"], multiselect=True, scale=3)
|
||||
hr_additional_modules = gr.Dropdown(label="Hires VAE / Text Encoder", elem_id="hr_vae_te", choices=modules_list, value=["Use same choices"], multiselect=True, scale=3)
|
||||
|
||||
hr_checkpoint_refresh.click(fn=refresh_model_and_modules, outputs=[hr_checkpoint_name, hr_additional_modules], show_progress=False)
|
||||
|
||||
with FormRow(elem_id="txt2img_hires_fix_row3b", variant="compact", visible=shared.opts.hires_fix_show_sampler) as hr_sampler_container:
|
||||
hr_sampler_name = gr.Dropdown(label='Hires sampling method', elem_id="hr_sampler", choices=["Use same sampler"] + sd_samplers.visible_sampler_names(), value="Use same sampler")
|
||||
hr_scheduler = gr.Dropdown(label='Hires schedule type', elem_id="hr_scheduler", choices=["Use same scheduler"] + [x.label for x in sd_schedulers.schedulers], value="Use same scheduler")
|
||||
hr_sampler_name = gr.Dropdown(label="Hires sampling method", elem_id="hr_sampler", choices=["Use same sampler"] + sd_samplers.visible_sampler_names(), value="Use same sampler")
|
||||
hr_scheduler = gr.Dropdown(label="Hires schedule type", elem_id="hr_scheduler", choices=["Use same scheduler"] + [x.label for x in sd_schedulers.schedulers], value="Use same scheduler")
|
||||
|
||||
with FormRow(elem_id="txt2img_hires_fix_row4", variant="compact", visible=shared.opts.hires_fix_show_prompts) as hr_prompts_container:
|
||||
with gr.Column():
|
||||
@ -355,12 +328,12 @@ def create_ui():
|
||||
elif category == "batch":
|
||||
if not opts.dimensions_and_batch_together:
|
||||
with FormRow(elem_id="txt2img_column_batch"):
|
||||
batch_count = gr.Slider(minimum=1, step=1, label='Batch count', value=1, elem_id="txt2img_batch_count")
|
||||
batch_size = gr.Slider(minimum=1, maximum=8, step=1, label='Batch size', value=1, elem_id="txt2img_batch_size")
|
||||
batch_count = gr.Slider(minimum=1, step=1, label="Batch count", value=1, elem_id="txt2img_batch_count")
|
||||
batch_size = gr.Slider(minimum=1, maximum=8, step=1, label="Batch size", value=1, elem_id="txt2img_batch_size")
|
||||
|
||||
elif category == "override_settings":
|
||||
with FormRow(elem_id="txt2img_override_settings_row") as row:
|
||||
override_settings = create_override_settings_dropdown('txt2img', row)
|
||||
override_settings = create_override_settings_dropdown("txt2img", row)
|
||||
|
||||
elif category == "scripts":
|
||||
with FormGroup(elem_id="txt2img_script_container"):
|
||||
@ -384,7 +357,6 @@ def create_ui():
|
||||
None,
|
||||
_js="onCalcResolutionHires",
|
||||
inputs=hr_resolution_preview_inputs,
|
||||
outputs=[],
|
||||
show_progress=False,
|
||||
)
|
||||
|
||||
@ -440,7 +412,7 @@ def create_ui():
|
||||
|
||||
def select_gallery_image(index):
|
||||
index = int(index)
|
||||
if getattr(shared.opts, 'hires_button_gallery_insert', False):
|
||||
if getattr(shared.opts, "hires_button_gallery_insert", False):
|
||||
index += 1
|
||||
return gr.update(selected_index=index)
|
||||
|
||||
@ -499,21 +471,26 @@ def create_ui():
|
||||
PasteField(hr_cfg, "Hires CFG Scale", api="hr_cfg"),
|
||||
PasteField(hr_distilled_cfg, "Hires Distilled CFG Scale", api="hr_distilled_cfg"),
|
||||
PasteField(hr_prompts_container, lambda d: gr.update(visible=True) if d.get("Hires prompt", "") != "" or d.get("Hires negative prompt", "") != "" else gr.update()),
|
||||
*scripts.scripts_txt2img.infotext_fields
|
||||
*scripts.scripts_txt2img.infotext_fields,
|
||||
]
|
||||
parameters_copypaste.add_paste_fields("txt2img", None, txt2img_paste_fields, override_settings)
|
||||
parameters_copypaste.register_paste_params_button(parameters_copypaste.ParamBinding(
|
||||
paste_button=toprow.paste, tabname="txt2img", source_text_component=toprow.prompt, source_image_component=None,
|
||||
))
|
||||
parameters_copypaste.register_paste_params_button(
|
||||
parameters_copypaste.ParamBinding(
|
||||
paste_button=toprow.paste,
|
||||
tabname="txt2img",
|
||||
source_text_component=toprow.prompt,
|
||||
source_image_component=None,
|
||||
)
|
||||
)
|
||||
|
||||
steps = scripts.scripts_txt2img.script('Sampler').steps
|
||||
steps = scripts.scripts_txt2img.script("Sampler").steps
|
||||
|
||||
toprow.ui_styles.dropdown.change(fn=wrap_queued_call(update_token_counter), inputs=[toprow.prompt, steps, toprow.ui_styles.dropdown], outputs=[toprow.token_counter])
|
||||
toprow.ui_styles.dropdown.change(fn=wrap_queued_call(update_negative_prompt_token_counter), inputs=[toprow.negative_prompt, steps, toprow.ui_styles.dropdown], outputs=[toprow.negative_token_counter])
|
||||
toprow.token_button.click(fn=wrap_queued_call(update_token_counter), inputs=[toprow.prompt, steps, toprow.ui_styles.dropdown], outputs=[toprow.token_counter])
|
||||
toprow.negative_token_button.click(fn=wrap_queued_call(update_negative_prompt_token_counter), inputs=[toprow.negative_prompt, steps, toprow.ui_styles.dropdown], outputs=[toprow.negative_token_counter])
|
||||
|
||||
extra_networks_ui = ui_extra_networks.create_ui(txt2img_interface, [txt2img_generation_tab], 'txt2img')
|
||||
extra_networks_ui = ui_extra_networks.create_ui(txt2img_interface, [txt2img_generation_tab], "txt2img")
|
||||
ui_extra_networks.setup_ui(extra_networks_ui, output_panel.gallery)
|
||||
|
||||
extra_tabs.__exit__()
|
||||
@ -534,14 +511,14 @@ def create_ui():
|
||||
with ExitStack() as stack:
|
||||
if shared.opts.img2img_settings_accordion:
|
||||
stack.enter_context(gr.Accordion("Open for Settings", open=False))
|
||||
stack.enter_context(gr.Column(variant='compact', elem_id="img2img_settings"))
|
||||
stack.enter_context(gr.Column(variant="compact", elem_id="img2img_settings"))
|
||||
|
||||
copy_image_buttons = []
|
||||
copy_image_destinations = {}
|
||||
|
||||
def add_copy_image_controls(tab_name, elem):
|
||||
with gr.Row(variant="compact", elem_id=f"img2img_copy_to_{tab_name}"):
|
||||
for title, name in zip(['to img2img', 'to sketch', 'to inpaint', 'to inpaint sketch'], ['img2img', 'sketch', 'inpaint', 'inpaint_sketch']):
|
||||
for title, name in zip(["to img2img", "to sketch", "to inpaint", "to inpaint sketch"], ["img2img", "sketch", "inpaint", "inpaint_sketch"]):
|
||||
if name == tab_name:
|
||||
gr.Button(title, interactive=False)
|
||||
copy_image_destinations[name] = elem
|
||||
@ -560,44 +537,39 @@ def create_ui():
|
||||
with gr.Tabs(elem_id="mode_img2img"):
|
||||
img2img_selected_tab = gr.Number(value=0, visible=False)
|
||||
|
||||
with gr.TabItem('img2img', id='img2img', elem_id="img2img_img2img_tab") as tab_img2img:
|
||||
with gr.TabItem("img2img", id="img2img", elem_id="img2img_img2img_tab") as tab_img2img:
|
||||
init_img = ForgeCanvas(elem_id="img2img_image", height=512, no_scribbles=True)
|
||||
add_copy_image_controls('img2img', init_img)
|
||||
add_copy_image_controls("img2img", init_img)
|
||||
|
||||
with gr.TabItem('Sketch', id='img2img_sketch', elem_id="img2img_img2img_sketch_tab") as tab_sketch:
|
||||
with gr.TabItem("Sketch", id="img2img_sketch", elem_id="img2img_img2img_sketch_tab") as tab_sketch:
|
||||
sketch = ForgeCanvas(elem_id="img2img_sketch", height=512, scribble_color=opts.img2img_sketch_default_brush_color)
|
||||
add_copy_image_controls('sketch', sketch)
|
||||
add_copy_image_controls("sketch", sketch)
|
||||
|
||||
with gr.TabItem('Inpaint', id='inpaint', elem_id="img2img_inpaint_tab") as tab_inpaint:
|
||||
with gr.TabItem("Inpaint", id="inpaint", elem_id="img2img_inpaint_tab") as tab_inpaint:
|
||||
init_img_with_mask = ForgeCanvas(elem_id="img2maskimg", height=512, contrast_scribbles=opts.img2img_inpaint_mask_high_contrast, scribble_color=opts.img2img_inpaint_mask_brush_color, scribble_color_fixed=True, scribble_alpha=opts.img2img_inpaint_mask_scribble_alpha, scribble_alpha_fixed=True, scribble_softness_fixed=True)
|
||||
add_copy_image_controls('inpaint', init_img_with_mask)
|
||||
add_copy_image_controls("inpaint", init_img_with_mask)
|
||||
|
||||
with gr.TabItem('Inpaint sketch', id='inpaint_sketch', elem_id="img2img_inpaint_sketch_tab") as tab_inpaint_color:
|
||||
with gr.TabItem("Inpaint sketch", id="inpaint_sketch", elem_id="img2img_inpaint_sketch_tab") as tab_inpaint_color:
|
||||
inpaint_color_sketch = ForgeCanvas(elem_id="inpaint_sketch", height=512, scribble_color=opts.img2img_inpaint_sketch_default_brush_color)
|
||||
add_copy_image_controls('inpaint_sketch', inpaint_color_sketch)
|
||||
add_copy_image_controls("inpaint_sketch", inpaint_color_sketch)
|
||||
|
||||
with gr.TabItem('Inpaint upload', id='inpaint_upload', elem_id="img2img_inpaint_upload_tab") as tab_inpaint_upload:
|
||||
with gr.TabItem("Inpaint upload", id="inpaint_upload", elem_id="img2img_inpaint_upload_tab") as tab_inpaint_upload:
|
||||
init_img_inpaint = gr.Image(label="Image for img2img", show_label=False, source="upload", interactive=True, type="pil", elem_id="img_inpaint_base")
|
||||
init_mask_inpaint = gr.Image(label="Mask", source="upload", interactive=True, type="pil", image_mode="RGBA", elem_id="img_inpaint_mask")
|
||||
|
||||
with gr.TabItem('Batch', id='batch', elem_id="img2img_batch_tab") as tab_batch:
|
||||
with gr.TabItem("Batch", id="batch", elem_id="img2img_batch_tab") as tab_batch:
|
||||
with gr.Tabs(elem_id="img2img_batch_source"):
|
||||
img2img_batch_source_type = gr.Textbox(visible=False, value="upload")
|
||||
with gr.TabItem('Upload', id='batch_upload', elem_id="img2img_batch_upload_tab") as tab_batch_upload:
|
||||
with gr.TabItem("Upload", id="batch_upload", elem_id="img2img_batch_upload_tab") as tab_batch_upload:
|
||||
img2img_batch_upload = gr.Files(label="Files", interactive=True, elem_id="img2img_batch_upload")
|
||||
with gr.TabItem('From directory', id='batch_from_dir', elem_id="img2img_batch_from_dir_tab") as tab_batch_from_dir:
|
||||
hidden = '<br>Disabled when launched with --hide-ui-dir-config.' if shared.cmd_opts.hide_ui_dir_config else ''
|
||||
gr.HTML(
|
||||
"<p style='padding-bottom: 1em;' class=\"text-gray-500\">Process images in a directory on the same machine where the server is running." +
|
||||
"<br>Use an empty output directory to save pictures normally instead of writing to the output directory." +
|
||||
f"<br>Add inpaint batch mask directory to enable inpaint batch processing."
|
||||
f"{hidden}</p>"
|
||||
)
|
||||
with gr.TabItem("From directory", id="batch_from_dir", elem_id="img2img_batch_from_dir_tab") as tab_batch_from_dir:
|
||||
hidden = "<br>Disabled when launched with --hide-ui-dir-config." if shared.cmd_opts.hide_ui_dir_config else ""
|
||||
gr.HTML("<p style='padding-bottom: 1em;' class=\"text-gray-500\">Process images in a directory on the same machine where the server is running." + "<br>Use an empty output directory to save pictures normally instead of writing to the output directory." + f"<br>Add inpaint batch mask directory to enable inpaint batch processing." f"{hidden}</p>")
|
||||
img2img_batch_input_dir = gr.Textbox(label="Input directory", **shared.hide_dirs, elem_id="img2img_batch_input_dir")
|
||||
img2img_batch_output_dir = gr.Textbox(label="Output directory", **shared.hide_dirs, elem_id="img2img_batch_output_dir")
|
||||
img2img_batch_inpaint_mask_dir = gr.Textbox(label="Inpaint batch mask directory (required for inpaint batch processing only)", **shared.hide_dirs, elem_id="img2img_batch_inpaint_mask_dir")
|
||||
tab_batch_upload.select(fn=lambda: "upload", inputs=[], outputs=[img2img_batch_source_type])
|
||||
tab_batch_from_dir.select(fn=lambda: "from dir", inputs=[], outputs=[img2img_batch_source_type])
|
||||
tab_batch_upload.select(fn=lambda: "upload", outputs=[img2img_batch_source_type])
|
||||
tab_batch_from_dir.select(fn=lambda: "from dir", outputs=[img2img_batch_source_type])
|
||||
with gr.Accordion("PNG info", open=False):
|
||||
img2img_batch_use_png_info = gr.Checkbox(label="Append png info to prompts", elem_id="img2img_batch_use_png_info")
|
||||
img2img_batch_png_info_dir = gr.Textbox(label="PNG info directory", **shared.hide_dirs, placeholder="Leave empty to use input directory", elem_id="img2img_batch_png_info_dir")
|
||||
@ -606,10 +578,10 @@ def create_ui():
|
||||
img2img_tabs = [tab_img2img, tab_sketch, tab_inpaint, tab_inpaint_color, tab_inpaint_upload, tab_batch]
|
||||
|
||||
for i, tab in enumerate(img2img_tabs):
|
||||
tab.select(fn=lambda tabnum=i: tabnum, inputs=[], outputs=[img2img_selected_tab])
|
||||
tab.select(fn=lambda tabnum=i: tabnum, outputs=[img2img_selected_tab])
|
||||
|
||||
def copyCanvas_img2img (background, foreground, source):
|
||||
if source == 1 or source == 3: # 1 is sketch, 3 is Inpaint sketch
|
||||
def copyCanvas_img2img(background, foreground, source):
|
||||
if source == 1 or source == 3: # 1 is sketch; 3 is Inpaint sketch
|
||||
bg = Image.alpha_composite(background, foreground)
|
||||
return bg, None
|
||||
return background, None
|
||||
@ -623,8 +595,6 @@ def create_ui():
|
||||
button.click(
|
||||
fn=None,
|
||||
_js=f"switch_to_{name.replace(' ', '_')}",
|
||||
inputs=[],
|
||||
outputs=[],
|
||||
)
|
||||
|
||||
with FormRow():
|
||||
@ -664,7 +634,7 @@ def create_ui():
|
||||
scale_by.change(**on_change_args)
|
||||
button_update_resize_to.click(**on_change_args)
|
||||
|
||||
def updateWH (img, w, h):
|
||||
def updateWH(img, w, h):
|
||||
if img and shared.opts.img2img_autosize == True:
|
||||
return img.size[0], img.size[1]
|
||||
else:
|
||||
@ -672,32 +642,28 @@ def create_ui():
|
||||
|
||||
img_sources = [init_img.background, sketch.background, init_img_with_mask.background, inpaint_color_sketch.background, init_img_inpaint]
|
||||
for i in img_sources:
|
||||
i.change(fn=updateWH, inputs=[i, width, height], outputs=[width, height], show_progress='hidden')
|
||||
i.change(fn=updateWH, inputs=[i, width, height], outputs=[width, height], show_progress="hidden")
|
||||
i.change(**on_change_args)
|
||||
|
||||
tab_scale_to.select(fn=lambda: 0, inputs=[], outputs=[selected_scale_tab])
|
||||
tab_scale_by.select(fn=lambda: 1, inputs=[], outputs=[selected_scale_tab])
|
||||
tab_scale_to.select(fn=lambda: 0, outputs=[selected_scale_tab])
|
||||
tab_scale_by.select(fn=lambda: 1, outputs=[selected_scale_tab])
|
||||
|
||||
if opts.dimensions_and_batch_together:
|
||||
with gr.Column(elem_id="img2img_column_batch"):
|
||||
batch_count = gr.Slider(minimum=1, step=1, label='Batch count', value=1, elem_id="img2img_batch_count")
|
||||
batch_size = gr.Slider(minimum=1, maximum=8, step=1, label='Batch size', value=1, elem_id="img2img_batch_size")
|
||||
batch_count = gr.Slider(minimum=1, step=1, label="Batch count", value=1, elem_id="img2img_batch_count")
|
||||
batch_size = gr.Slider(minimum=1, maximum=8, step=1, label="Batch size", value=1, elem_id="img2img_batch_size")
|
||||
|
||||
elif category == "denoising":
|
||||
denoising_strength = gr.Slider(minimum=0.0, maximum=1.0, step=0.01, label='Denoising strength', value=0.75, elem_id="img2img_denoising_strength")
|
||||
denoising_strength = gr.Slider(minimum=0.0, maximum=1.0, step=0.01, label="Denoising strength", value=0.75, elem_id="img2img_denoising_strength")
|
||||
|
||||
elif category == "cfg":
|
||||
with gr.Row():
|
||||
distilled_cfg_scale = gr.Slider(minimum=0.0, maximum=30.0, step=0.1, label='Distilled CFG Scale', value=3.5, elem_id="img2img_distilled_cfg_scale", scale=4)
|
||||
cfg_scale = gr.Slider(minimum=1.0, maximum=30.0, step=0.1, label='CFG Scale', value=7.0, elem_id="img2img_cfg_scale", scale=4)
|
||||
image_cfg_scale = gr.Slider(minimum=0, maximum=3.0, step=0.05, label='Image CFG Scale', value=1.5, elem_id="img2img_image_cfg_scale", visible=False)
|
||||
distilled_cfg_scale = gr.Slider(minimum=0.0, maximum=30.0, step=0.1, label="Distilled CFG Scale", value=3.5, elem_id="img2img_distilled_cfg_scale", scale=4)
|
||||
cfg_scale = gr.Slider(minimum=1.0, maximum=30.0, step=0.1, label="CFG Scale", value=7.0, elem_id="img2img_cfg_scale", scale=4)
|
||||
image_cfg_scale = gr.Slider(minimum=0, maximum=3.0, step=0.05, label="Image CFG Scale", value=1.5, elem_id="img2img_image_cfg_scale", visible=False)
|
||||
cfg_scale.change(lambda x: gr.update(interactive=(x != 1)), inputs=[cfg_scale], outputs=[toprow.negative_prompt], queue=False, show_progress=False)
|
||||
scripts.scripts_img2img.setup_ui_for_section(category)
|
||||
|
||||
# elif category == "checkboxes":
|
||||
# with FormRow(elem_classes="checkboxes-row", variant="compact"):
|
||||
# pass
|
||||
|
||||
elif category == "accordions":
|
||||
with gr.Row(elem_id="img2img_accordions", elem_classes="accordions"):
|
||||
scripts.scripts_img2img.setup_ui_for_section(category)
|
||||
@ -705,12 +671,12 @@ def create_ui():
|
||||
elif category == "batch":
|
||||
if not opts.dimensions_and_batch_together:
|
||||
with FormRow(elem_id="img2img_column_batch"):
|
||||
batch_count = gr.Slider(minimum=1, step=1, label='Batch count', value=1, elem_id="img2img_batch_count")
|
||||
batch_size = gr.Slider(minimum=1, maximum=8, step=1, label='Batch size', value=1, elem_id="img2img_batch_size")
|
||||
batch_count = gr.Slider(minimum=1, step=1, label="Batch count", value=1, elem_id="img2img_batch_count")
|
||||
batch_size = gr.Slider(minimum=1, maximum=8, step=1, label="Batch size", value=1, elem_id="img2img_batch_size")
|
||||
|
||||
elif category == "override_settings":
|
||||
with FormRow(elem_id="img2img_override_settings_row") as row:
|
||||
override_settings = create_override_settings_dropdown('img2img', row)
|
||||
override_settings = create_override_settings_dropdown("img2img", row)
|
||||
|
||||
elif category == "scripts":
|
||||
with FormGroup(elem_id="img2img_script_container"):
|
||||
@ -719,32 +685,34 @@ def create_ui():
|
||||
elif category == "inpaint":
|
||||
with FormGroup(elem_id="inpaint_controls", visible=False) as inpaint_controls:
|
||||
with FormRow():
|
||||
mask_blur = gr.Slider(label='Mask blur', minimum=0, maximum=64, step=1, value=4, elem_id="img2img_mask_blur")
|
||||
mask_blur = gr.Slider(label="Mask blur", minimum=0, maximum=64, step=1, value=4, elem_id="img2img_mask_blur")
|
||||
mask_alpha = gr.Slider(label="Mask transparency", visible=False, elem_id="img2img_mask_alpha")
|
||||
|
||||
with FormRow():
|
||||
inpainting_mask_invert = gr.Radio(label='Mask mode', choices=['Inpaint masked', 'Inpaint not masked'], value='Inpaint masked', type="index", elem_id="img2img_mask_mode")
|
||||
inpainting_mask_invert = gr.Radio(label="Mask mode", choices=["Inpaint masked", "Inpaint not masked"], value="Inpaint masked", type="index", elem_id="img2img_mask_mode")
|
||||
|
||||
with FormRow():
|
||||
inpainting_fill = gr.Radio(label='Masked content', choices=['fill', 'original', 'latent noise', 'latent nothing'], value='original', type="index", elem_id="img2img_inpainting_fill")
|
||||
inpainting_fill = gr.Radio(label="Masked content", choices=["fill", "original", "latent noise", "latent nothing"], value="original", type="index", elem_id="img2img_inpainting_fill")
|
||||
|
||||
with FormRow():
|
||||
with gr.Column():
|
||||
inpaint_full_res = gr.Radio(label="Inpaint area", choices=["Whole picture", "Only masked"], type="index", value="Whole picture", elem_id="img2img_inpaint_full_res")
|
||||
|
||||
with gr.Column(scale=4):
|
||||
inpaint_full_res_padding = gr.Slider(label='Only masked padding, pixels', minimum=0, maximum=256, step=4, value=32, elem_id="img2img_inpaint_full_res_padding")
|
||||
inpaint_full_res_padding = gr.Slider(label="Only masked padding, pixels", minimum=0, maximum=256, step=4, value=32, elem_id="img2img_inpaint_full_res_padding")
|
||||
|
||||
if category not in {"accordions", "cfg"}:
|
||||
scripts.scripts_img2img.setup_ui_for_section(category)
|
||||
|
||||
def select_img2img_tab(tab):
|
||||
return gr.update(visible=tab in [2, 3, 4]), gr.update(visible=tab == 3),
|
||||
return (
|
||||
gr.update(visible=tab in [2, 3, 4]),
|
||||
gr.update(visible=tab == 3),
|
||||
)
|
||||
|
||||
for i, elem in enumerate(img2img_tabs):
|
||||
elem.select(
|
||||
fn=lambda tab=i: select_img2img_tab(tab),
|
||||
inputs=[],
|
||||
outputs=[inpaint_controls, mask_alpha],
|
||||
)
|
||||
|
||||
@ -833,38 +801,26 @@ def create_ui():
|
||||
show_progress=False,
|
||||
)
|
||||
|
||||
steps = scripts.scripts_img2img.script('Sampler').steps
|
||||
steps = scripts.scripts_img2img.script("Sampler").steps
|
||||
|
||||
toprow.ui_styles.dropdown.change(fn=wrap_queued_call(update_token_counter), inputs=[toprow.prompt, steps, toprow.ui_styles.dropdown], outputs=[toprow.token_counter])
|
||||
toprow.ui_styles.dropdown.change(fn=wrap_queued_call(update_negative_prompt_token_counter), inputs=[toprow.negative_prompt, steps, toprow.ui_styles.dropdown], outputs=[toprow.negative_token_counter])
|
||||
toprow.token_button.click(fn=update_token_counter, inputs=[toprow.prompt, steps, toprow.ui_styles.dropdown], outputs=[toprow.token_counter])
|
||||
toprow.negative_token_button.click(fn=wrap_queued_call(update_negative_prompt_token_counter), inputs=[toprow.negative_prompt, steps, toprow.ui_styles.dropdown], outputs=[toprow.negative_token_counter])
|
||||
|
||||
img2img_paste_fields = [
|
||||
(toprow.prompt, "Prompt"),
|
||||
(toprow.negative_prompt, "Negative prompt"),
|
||||
(cfg_scale, "CFG scale"),
|
||||
(distilled_cfg_scale, "Distilled CFG Scale"),
|
||||
(image_cfg_scale, "Image CFG scale"),
|
||||
(width, "Size-1"),
|
||||
(height, "Size-2"),
|
||||
(batch_size, "Batch size"),
|
||||
(toprow.ui_styles.dropdown, lambda d: d["Styles array"] if isinstance(d.get("Styles array"), list) else gr.update()),
|
||||
(denoising_strength, "Denoising strength"),
|
||||
(mask_blur, "Mask blur"),
|
||||
(inpainting_mask_invert, 'Mask mode'),
|
||||
(inpainting_fill, 'Masked content'),
|
||||
(inpaint_full_res, 'Inpaint area'),
|
||||
(inpaint_full_res_padding, 'Masked area padding'),
|
||||
*scripts.scripts_img2img.infotext_fields
|
||||
]
|
||||
img2img_paste_fields = [(toprow.prompt, "Prompt"), (toprow.negative_prompt, "Negative prompt"), (cfg_scale, "CFG scale"), (distilled_cfg_scale, "Distilled CFG Scale"), (image_cfg_scale, "Image CFG scale"), (width, "Size-1"), (height, "Size-2"), (batch_size, "Batch size"), (toprow.ui_styles.dropdown, lambda d: d["Styles array"] if isinstance(d.get("Styles array"), list) else gr.update()), (denoising_strength, "Denoising strength"), (mask_blur, "Mask blur"), (inpainting_mask_invert, "Mask mode"), (inpainting_fill, "Masked content"), (inpaint_full_res, "Inpaint area"), (inpaint_full_res_padding, "Masked area padding"), *scripts.scripts_img2img.infotext_fields]
|
||||
parameters_copypaste.add_paste_fields("img2img", init_img.background, img2img_paste_fields, override_settings)
|
||||
parameters_copypaste.add_paste_fields("inpaint", init_img_with_mask.background, img2img_paste_fields, override_settings)
|
||||
parameters_copypaste.register_paste_params_button(parameters_copypaste.ParamBinding(
|
||||
paste_button=toprow.paste, tabname="img2img", source_text_component=toprow.prompt, source_image_component=None,
|
||||
))
|
||||
parameters_copypaste.register_paste_params_button(
|
||||
parameters_copypaste.ParamBinding(
|
||||
paste_button=toprow.paste,
|
||||
tabname="img2img",
|
||||
source_text_component=toprow.prompt,
|
||||
source_image_component=None,
|
||||
)
|
||||
)
|
||||
|
||||
extra_networks_ui_img2img = ui_extra_networks.create_ui(img2img_interface, [img2img_generation_tab], 'img2img')
|
||||
extra_networks_ui_img2img = ui_extra_networks.create_ui(img2img_interface, [img2img_generation_tab], "img2img")
|
||||
ui_extra_networks.setup_ui(extra_networks_ui_img2img, output_panel.gallery)
|
||||
|
||||
extra_tabs.__exit__()
|
||||
@ -879,10 +835,10 @@ def create_ui():
|
||||
|
||||
with gr.Blocks(analytics_enabled=False) as pnginfo_interface:
|
||||
with ResizeHandleRow(equal_height=False):
|
||||
with gr.Column(variant='panel'):
|
||||
with gr.Column(variant="panel"):
|
||||
image = gr.Image(elem_id="pnginfo_image", label="Source", source="upload", interactive=True, type="pil", height="50vh", image_mode="RGBA")
|
||||
|
||||
with gr.Column(variant='panel'):
|
||||
with gr.Column(variant="panel"):
|
||||
html = gr.HTML()
|
||||
generation_info = gr.Textbox(visible=False, elem_id="pnginfo_generation_info")
|
||||
html2 = gr.HTML()
|
||||
@ -890,9 +846,14 @@ def create_ui():
|
||||
buttons = parameters_copypaste.create_buttons(["txt2img", "img2img", "inpaint", "extras"])
|
||||
|
||||
for tabname, button in buttons.items():
|
||||
parameters_copypaste.register_paste_params_button(parameters_copypaste.ParamBinding(
|
||||
paste_button=button, tabname=tabname, source_text_component=generation_info, source_image_component=image,
|
||||
))
|
||||
parameters_copypaste.register_paste_params_button(
|
||||
parameters_copypaste.ParamBinding(
|
||||
paste_button=button,
|
||||
tabname=tabname,
|
||||
source_text_component=generation_info,
|
||||
source_image_component=image,
|
||||
)
|
||||
)
|
||||
|
||||
image.change(
|
||||
fn=wrap_gradio_call_no_job(modules.extras.run_pnginfo),
|
||||
@ -908,8 +869,8 @@ def create_ui():
|
||||
settings.create_ui(loadsave, dummy_component)
|
||||
|
||||
interfaces = [
|
||||
(txt2img_interface, "Txt2img", "txt2img"),
|
||||
(img2img_interface, "Img2img", "img2img"),
|
||||
(txt2img_interface, "txt2img", "txt2img"),
|
||||
(img2img_interface, "img2img", "img2img"),
|
||||
(extras_interface, "Extras", "extras"),
|
||||
(pnginfo_interface, "PNG Info", "pnginfo"),
|
||||
(modelmerger_ui.blocks, "Checkpoint Merger", "modelmerger"),
|
||||
@ -926,7 +887,7 @@ def create_ui():
|
||||
shared.tab_names.append(label)
|
||||
|
||||
with gr.Blocks(theme=shared.gradio_theme, analytics_enabled=False, title="Stable Diffusion", head=canvas_head) as demo:
|
||||
quicksettings_row = settings.add_quicksettings()
|
||||
settings.add_quicksettings()
|
||||
|
||||
parameters_copypaste.connect_paste_params_buttons()
|
||||
|
||||
@ -957,8 +918,8 @@ def create_ui():
|
||||
settings.add_functionality(demo)
|
||||
|
||||
update_image_cfg_scale_visibility = lambda: gr.update(visible=False)
|
||||
settings.text_settings.change(fn=update_image_cfg_scale_visibility, inputs=[], outputs=[image_cfg_scale])
|
||||
demo.load(fn=update_image_cfg_scale_visibility, inputs=[], outputs=[image_cfg_scale])
|
||||
settings.text_settings.change(fn=update_image_cfg_scale_visibility, outputs=[image_cfg_scale])
|
||||
demo.load(fn=update_image_cfg_scale_visibility, outputs=[image_cfg_scale])
|
||||
|
||||
modelmerger_ui.setup_ui(dummy_component=dummy_component, sd_model_checkpoint_component=main_entry.ui_checkpoint)
|
||||
|
||||
@ -972,10 +933,12 @@ def create_ui():
|
||||
|
||||
|
||||
def versions_html():
|
||||
from backend.memory_management import sage_enabled, flash_enabled, xformers_enabled
|
||||
import importlib.metadata
|
||||
|
||||
import torch
|
||||
|
||||
from backend.memory_management import flash_enabled, sage_enabled, xformers_enabled
|
||||
|
||||
python_version = ".".join([str(x) for x in sys.version_info[0:3]])
|
||||
_versions = [f"torch: {getattr(torch, '__long_version__', torch.__version__)}"]
|
||||
|
||||
@ -1021,10 +984,11 @@ def setup_ui_api(app):
|
||||
text = sysinfo.get()
|
||||
filename = f"sysinfo-{datetime.datetime.now(datetime.timezone.utc).strftime('%Y-%m-%d-%H-%M')}.json"
|
||||
|
||||
return PlainTextResponse(text, headers={'Content-Disposition': f'{"attachment" if attachment else "inline"}; filename="{filename}"'})
|
||||
return PlainTextResponse(text, headers={"Content-Disposition": f'{"attachment" if attachment else "inline"}; filename="{filename}"'})
|
||||
|
||||
app.add_api_route("/internal/sysinfo", download_sysinfo, methods=["GET"])
|
||||
app.add_api_route("/internal/sysinfo-download", lambda: download_sysinfo(attachment=True), methods=["GET"])
|
||||
|
||||
import fastapi.staticfiles
|
||||
|
||||
app.mount("/webui-assets", fastapi.staticfiles.StaticFiles(directory=os.path.join(paths_internal.modules_path, "web")), name="webui-assets")
|
||||
|
||||
Loading…
Reference in New Issue
Block a user