From 8ea8e712c43e493a9c96dcec7dfbc036a8630c97 Mon Sep 17 00:00:00 2001 From: AUTOMATIC <16777216c@gmail.com> Date: Mon, 20 Mar 2023 16:09:36 +0300 Subject: [PATCH 1/9] initial gradio 3.22 support --- .../javascript/prompt-bracket-checker.js | 15 +- javascript/hints.js | 2 +- javascript/imageviewer.js | 62 +- javascript/progressbar.js | 67 +- javascript/ui.js | 3 +- modules/scripts.py | 3 + modules/scripts_postprocessing.py | 2 +- modules/ui.py | 43 +- modules/ui_common.py | 3 +- modules/ui_components.py | 42 +- requirements.txt | 2 +- requirements_versions.txt | 2 +- script.js | 6 +- scripts/postprocessing_upscale.py | 28 +- style.css | 654 +++++------------- 15 files changed, 299 insertions(+), 635 deletions(-) diff --git a/extensions-builtin/prompt-bracket-checker/javascript/prompt-bracket-checker.js b/extensions-builtin/prompt-bracket-checker/javascript/prompt-bracket-checker.js index 4a85c8eb..f0918e26 100644 --- a/extensions-builtin/prompt-bracket-checker/javascript/prompt-bracket-checker.js +++ b/extensions-builtin/prompt-bracket-checker/javascript/prompt-bracket-checker.js @@ -89,22 +89,15 @@ function checkBrackets(evt, textArea, counterElt) { function setupBracketChecking(id_prompt, id_counter){ var textarea = gradioApp().querySelector("#" + id_prompt + " > label > textarea"); var counter = gradioApp().getElementById(id_counter) + textarea.addEventListener("input", function(evt){ checkBrackets(evt, textarea, counter) }); } -var shadowRootLoaded = setInterval(function() { - var shadowRoot = document.querySelector('gradio-app').shadowRoot; - if(! shadowRoot) return false; - - var shadowTextArea = shadowRoot.querySelectorAll('#txt2img_prompt > label > textarea'); - if(shadowTextArea.length < 1) return false; - - clearInterval(shadowRootLoaded); - +onUiLoaded(function(){ setupBracketChecking('txt2img_prompt', 'txt2img_token_counter') setupBracketChecking('txt2img_neg_prompt', 'txt2img_negative_token_counter') - setupBracketChecking('img2img_prompt', 'imgimg_token_counter') + setupBracketChecking('img2img_prompt', 'img2img_token_counter') setupBracketChecking('img2img_neg_prompt', 'img2img_negative_token_counter') -}, 1000); +}) \ No newline at end of file diff --git a/javascript/hints.js b/javascript/hints.js index 7f4101b2..61763e6b 100644 --- a/javascript/hints.js +++ b/javascript/hints.js @@ -18,7 +18,7 @@ titles = { "\u2199\ufe0f": "Read generation parameters from prompt or last generation if prompt is empty into user interface.", "\u{1f4c2}": "Open images output directory", "\u{1f4be}": "Save style", - "\u{1f5d1}": "Clear prompt", + "\u{1f5d1}\ufe0f": "Clear prompt", "\u{1f4cb}": "Apply selected styles to current prompt", "\u{1f4d2}": "Paste available values into the field", "\u{1f3b4}": "Show extra networks", diff --git a/javascript/imageviewer.js b/javascript/imageviewer.js index 28e748b7..7547e771 100644 --- a/javascript/imageviewer.js +++ b/javascript/imageviewer.js @@ -50,7 +50,7 @@ function updateOnBackgroundChange() { } function modalImageSwitch(offset) { - var allgalleryButtons = gradioApp().querySelectorAll(".gallery-item.transition-all") + var allgalleryButtons = gradioApp().querySelectorAll(".gradio-gallery .thumbnail-item") var galleryButtons = [] allgalleryButtons.forEach(function(elem) { if (elem.parentElement.offsetParent) { @@ -59,7 +59,7 @@ function modalImageSwitch(offset) { }) if (galleryButtons.length > 1) { - var allcurrentButtons = gradioApp().querySelectorAll(".gallery-item.transition-all.\\!ring-2") + var allcurrentButtons = gradioApp().querySelectorAll(".gradio-gallery .thumbnail-item.selected") var currentButton = null allcurrentButtons.forEach(function(elem) { if (elem.parentElement.offsetParent) { @@ -136,37 +136,29 @@ function modalKeyHandler(event) { } } -function showGalleryImage() { - setTimeout(function() { - fullImg_preview = gradioApp().querySelectorAll('img.w-full.object-contain') +function setupImageForLightbox(e) { + if (e.dataset.modded) + return; - if (fullImg_preview != null) { - fullImg_preview.forEach(function function_name(e) { - if (e.dataset.modded) - return; - e.dataset.modded = true; - if(e && e.parentElement.tagName == 'DIV'){ - e.style.cursor='pointer' - e.style.userSelect='none' + e.dataset.modded = true; + e.style.cursor='pointer' + e.style.userSelect='none' - var isFirefox = isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1 + var isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1 - // For Firefox, listening on click first switched to next image then shows the lightbox. - // If you know how to fix this without switching to mousedown event, please. - // For other browsers the event is click to make it possiblr to drag picture. - var event = isFirefox ? 'mousedown' : 'click' + // For Firefox, listening on click first switched to next image then shows the lightbox. + // If you know how to fix this without switching to mousedown event, please. + // For other browsers the event is click to make it possiblr to drag picture. + var event = isFirefox ? 'mousedown' : 'click' - e.addEventListener(event, function (evt) { - if(!opts.js_modal_lightbox || evt.button != 0) return; - modalZoomSet(gradioApp().getElementById('modalImage'), opts.js_modal_lightbox_initially_zoomed) - evt.preventDefault() - showModal(evt) - }, true); - } - }); - } + e.addEventListener(event, function (evt) { + if(!opts.js_modal_lightbox || evt.button != 0) return; + + modalZoomSet(gradioApp().getElementById('modalImage'), opts.js_modal_lightbox_initially_zoomed) + evt.preventDefault() + showModal(evt) + }, true); - }, 100); } function modalZoomSet(modalImage, enable) { @@ -199,21 +191,21 @@ function modalTileImageToggle(event) { } function galleryImageHandler(e) { - if (e && e.parentElement.tagName == 'BUTTON') { + //if (e && e.parentElement.tagName == 'BUTTON') { e.onclick = showGalleryImage; - } + //} } onUiUpdate(function() { - fullImg_preview = gradioApp().querySelectorAll('img.w-full') + fullImg_preview = gradioApp().querySelectorAll('.gradio-gallery > div > img') if (fullImg_preview != null) { - fullImg_preview.forEach(galleryImageHandler); + fullImg_preview.forEach(setupImageForLightbox); } updateOnBackgroundChange(); }) document.addEventListener("DOMContentLoaded", function() { - const modalFragment = document.createDocumentFragment(); + //const modalFragment = document.createDocumentFragment(); const modal = document.createElement('div') modal.onclick = closeModal; modal.id = "lightboxModal"; @@ -277,9 +269,9 @@ document.addEventListener("DOMContentLoaded", function() { modal.appendChild(modalNext) + gradioApp().appendChild(modal) - gradioApp().getRootNode().appendChild(modal) - document.body.appendChild(modalFragment); + document.body.appendChild(modal); }); diff --git a/javascript/progressbar.js b/javascript/progressbar.js index 9ccc9da4..4ac9b8db 100644 --- a/javascript/progressbar.js +++ b/javascript/progressbar.js @@ -1,78 +1,13 @@ // code related to showing and updating progressbar shown as the image is being made - -galleries = {} -storedGallerySelections = {} -galleryObservers = {} - function rememberGallerySelection(id_gallery){ - storedGallerySelections[id_gallery] = getGallerySelectedIndex(id_gallery) + } function getGallerySelectedIndex(id_gallery){ - let galleryButtons = gradioApp().querySelectorAll('#'+id_gallery+' .gallery-item') - let galleryBtnSelected = gradioApp().querySelector('#'+id_gallery+' .gallery-item.\\!ring-2') - let currentlySelectedIndex = -1 - galleryButtons.forEach(function(v, i){ if(v==galleryBtnSelected) { currentlySelectedIndex = i } }) - - return currentlySelectedIndex } -// this is a workaround for https://github.com/gradio-app/gradio/issues/2984 -function check_gallery(id_gallery){ - let gallery = gradioApp().getElementById(id_gallery) - // if gallery has no change, no need to setting up observer again. - if (gallery && galleries[id_gallery] !== gallery){ - galleries[id_gallery] = gallery; - if(galleryObservers[id_gallery]){ - galleryObservers[id_gallery].disconnect(); - } - - storedGallerySelections[id_gallery] = -1 - - galleryObservers[id_gallery] = new MutationObserver(function (){ - let galleryButtons = gradioApp().querySelectorAll('#'+id_gallery+' .gallery-item') - let galleryBtnSelected = gradioApp().querySelector('#'+id_gallery+' .gallery-item.\\!ring-2') - let currentlySelectedIndex = getGallerySelectedIndex(id_gallery) - prevSelectedIndex = storedGallerySelections[id_gallery] - storedGallerySelections[id_gallery] = -1 - - if (prevSelectedIndex !== -1 && galleryButtons.length>prevSelectedIndex && !galleryBtnSelected) { - // automatically re-open previously selected index (if exists) - activeElement = gradioApp().activeElement; - let scrollX = window.scrollX; - let scrollY = window.scrollY; - - galleryButtons[prevSelectedIndex].click(); - showGalleryImage(); - - // When the gallery button is clicked, it gains focus and scrolls itself into view - // We need to scroll back to the previous position - setTimeout(function (){ - window.scrollTo(scrollX, scrollY); - }, 50); - - if(activeElement){ - // i fought this for about an hour; i don't know why the focus is lost or why this helps recover it - // if someone has a better solution please by all means - setTimeout(function (){ - activeElement.focus({ - preventScroll: true // Refocus the element that was focused before the gallery was opened without scrolling to it - }) - }, 1); - } - } - }) - galleryObservers[id_gallery].observe( gallery, { childList:true, subtree:false }) - } -} - -onUiUpdate(function(){ - check_gallery('txt2img_gallery') - check_gallery('img2img_gallery') -}) - function request(url, data, handler, errorHandler){ var xhr = new XMLHttpRequest(); var url = url; diff --git a/javascript/ui.js b/javascript/ui.js index b7a8268a..fcaf5608 100644 --- a/javascript/ui.js +++ b/javascript/ui.js @@ -86,7 +86,7 @@ function get_tab_index(tabId){ var res = 0 gradioApp().getElementById(tabId).querySelector('div').querySelectorAll('button').forEach(function(button, i){ - if(button.className.indexOf('bg-white') != -1) + if(button.className.indexOf('selected') != -1) res = i }) @@ -255,7 +255,6 @@ onUiUpdate(function(){ } prompt.parentElement.insertBefore(counter, prompt) - counter.classList.add("token-counter") prompt.parentElement.style.position = "relative" promptTokecountUpdateFuncs[id] = function(){ update_token_counter(id_button); } diff --git a/modules/scripts.py b/modules/scripts.py index 8de19884..40d8dcc6 100644 --- a/modules/scripts.py +++ b/modules/scripts.py @@ -521,6 +521,9 @@ def IOComponent_init(self, *args, **kwargs): res = original_IOComponent_init(self, *args, **kwargs) + # this adds gradio-* to every component for css styling (ie gradio-button to gr.Button) + self.elem_classes = ["gradio-" + self.get_block_name(), *(self.elem_classes or [])] + script_callbacks.after_component_callback(self, **kwargs) if scripts_current is not None: diff --git a/modules/scripts_postprocessing.py b/modules/scripts_postprocessing.py index ce0ebb61..b11568c0 100644 --- a/modules/scripts_postprocessing.py +++ b/modules/scripts_postprocessing.py @@ -109,7 +109,7 @@ class ScriptPostprocessingRunner: inputs = [] for script in self.scripts_in_preferred_order(): - with gr.Box() as group: + with gr.Row() as group: self.create_script_ui(script, inputs) script.group = group diff --git a/modules/ui.py b/modules/ui.py index 7e603332..80807ce3 100644 --- a/modules/ui.py +++ b/modules/ui.py @@ -20,7 +20,7 @@ from PIL import Image, PngImagePlugin from modules.call_queue import wrap_gradio_gpu_call, wrap_queued_call, wrap_gradio_call from modules import sd_hijack, sd_models, localization, script_callbacks, ui_extensions, deepbooru, sd_vae, extra_networks, postprocessing, ui_components, ui_common, ui_postprocessing -from modules.ui_components import FormRow, FormGroup, ToolButton, FormHTML +from modules.ui_components import FormRow, FormColumn, FormGroup, ToolButton, FormHTML from modules.paths import script_path, data_path from modules.shared import opts, cmd_opts, restricted_opts @@ -89,7 +89,7 @@ paste_symbol = '\u2199\ufe0f' # ↙ refresh_symbol = '\U0001f504' # 🔄 save_style_symbol = '\U0001f4be' # 💾 apply_style_symbol = '\U0001f4cb' # 📋 -clear_prompt_symbol = '\U0001F5D1' # 🗑️ +clear_prompt_symbol = '\U0001f5d1\ufe0f' # 🗑️ extra_networks_symbol = '\U0001F3B4' # 🎴 switch_values_symbol = '\U000021C5' # ⇅ @@ -179,14 +179,13 @@ def interrogate_deepbooru(image): def create_seed_inputs(target_interface): - with FormRow(elem_id=target_interface + '_seed_row'): + with FormRow(elem_id=target_interface + '_seed_row', variant="compact"): seed = (gr.Textbox if cmd_opts.use_textbox_seed else gr.Number)(label='Seed', value=-1, elem_id=target_interface + '_seed') seed.style(container=False) - random_seed = gr.Button(random_symbol, elem_id=target_interface + '_random_seed') - reuse_seed = gr.Button(reuse_symbol, elem_id=target_interface + '_reuse_seed') + random_seed = ToolButton(random_symbol, elem_id=target_interface + '_random_seed') + reuse_seed = ToolButton(reuse_symbol, elem_id=target_interface + '_reuse_seed') - with gr.Group(elem_id=target_interface + '_subseed_show_box'): - seed_checkbox = gr.Checkbox(label='Extra', elem_id=target_interface + '_subseed_show', value=False) + seed_checkbox = gr.Checkbox(label='Extra', elem_id=target_interface + '_subseed_show', value=False) # Components to show/hide based on the 'Extra' checkbox seed_extras = [] @@ -195,8 +194,8 @@ def create_seed_inputs(target_interface): seed_extras.append(seed_extra_row_1) subseed = gr.Number(label='Variation seed', value=-1, elem_id=target_interface + '_subseed') subseed.style(container=False) - random_subseed = gr.Button(random_symbol, elem_id=target_interface + '_random_subseed') - reuse_subseed = gr.Button(reuse_symbol, elem_id=target_interface + '_reuse_subseed') + random_subseed = ToolButton(random_symbol, elem_id=target_interface + '_random_subseed') + reuse_subseed = ToolButton(reuse_symbol, elem_id=target_interface + '_reuse_subseed') subseed_strength = gr.Slider(label='Variation strength', value=0.0, minimum=0, maximum=1, step=0.01, elem_id=target_interface + '_subseed_strength') with FormRow(visible=False) as seed_extra_row_2: @@ -291,19 +290,19 @@ def create_toprow(is_img2img): with gr.Row(): with gr.Column(scale=80): with gr.Row(): - negative_prompt = gr.Textbox(label="Negative prompt", elem_id=f"{id_part}_neg_prompt", show_label=False, lines=2, placeholder="Negative prompt (press Ctrl+Enter or Alt+Enter to generate)") + negative_prompt = gr.Textbox(label="Negative prompt", elem_id=f"{id_part}_neg_prompt", show_label=False, lines=3, placeholder="Negative prompt (press Ctrl+Enter or Alt+Enter to generate)") button_interrogate = None button_deepbooru = None if is_img2img: - with gr.Column(scale=1, elem_id="interrogate_col"): + with gr.Column(scale=1, elem_classes="interrogate-col"): button_interrogate = gr.Button('Interrogate\nCLIP', elem_id="interrogate") button_deepbooru = gr.Button('Interrogate\nDeepBooru', elem_id="deepbooru") with gr.Column(scale=1, elem_id=f"{id_part}_actions_column"): - with gr.Row(elem_id=f"{id_part}_generate_box"): - interrupt = gr.Button('Interrupt', elem_id=f"{id_part}_interrupt") - skip = gr.Button('Skip', elem_id=f"{id_part}_skip") + with gr.Row(elem_id=f"{id_part}_generate_box", elem_classes="generate-box"): + interrupt = gr.Button('Interrupt', elem_id=f"{id_part}_interrupt", elem_classes="generate-box-interrupt") + skip = gr.Button('Skip', elem_id=f"{id_part}_skip", elem_classes="generate-box-skip") submit = gr.Button('Generate', elem_id=f"{id_part}_generate", variant='primary') skip.click( @@ -325,9 +324,9 @@ def create_toprow(is_img2img): prompt_style_apply = ToolButton(value=apply_style_symbol, elem_id=f"{id_part}_style_apply") save_style = ToolButton(value=save_style_symbol, elem_id=f"{id_part}_style_create") - token_counter = gr.HTML(value="", elem_id=f"{id_part}_token_counter") + token_counter = gr.HTML(value="0/75", elem_id=f"{id_part}_token_counter", elem_classes=["token-counter"]) token_button = gr.Button(visible=False, elem_id=f"{id_part}_token_button") - negative_token_counter = gr.HTML(value="", elem_id=f"{id_part}_negative_token_counter") + negative_token_counter = gr.HTML(value="0/75", elem_id=f"{id_part}_negative_token_counter", elem_classes=["token-counter"]) negative_token_button = gr.Button(visible=False, elem_id=f"{id_part}_negative_token_button") clear_prompt_button.click( @@ -479,7 +478,9 @@ def create_ui(): width = gr.Slider(minimum=64, maximum=2048, step=8, label="Width", value=512, elem_id="txt2img_width") height = gr.Slider(minimum=64, maximum=2048, step=8, label="Height", value=512, elem_id="txt2img_height") - res_switch_btn = ToolButton(value=switch_values_symbol, elem_id="txt2img_res_switch_btn") + with gr.Column(elem_id="txt2img_dimensions_row", scale=1): + res_switch_btn = ToolButton(value=switch_values_symbol, elem_id="txt2img_res_switch_btn") + 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") @@ -492,7 +493,7 @@ def create_ui(): seed, reuse_seed, subseed, reuse_subseed, subseed_strength, seed_resize_from_h, seed_resize_from_w, seed_checkbox = create_seed_inputs('txt2img') elif category == "checkboxes": - with FormRow(elem_id="txt2img_checkboxes", variant="compact"): + with FormRow(elem_classes="checkboxes-row", variant="compact"): restore_faces = gr.Checkbox(label='Restore faces', value=False, visible=len(shared.face_restorers) > 1, elem_id="txt2img_restore_faces") tiling = gr.Checkbox(label='Tiling', value=False, elem_id="txt2img_tiling") enable_hr = gr.Checkbox(label='Hires. fix', value=False, elem_id="txt2img_enable_hr") @@ -757,7 +758,9 @@ def create_ui(): width = gr.Slider(minimum=64, maximum=2048, step=8, label="Width", value=512, elem_id="img2img_width") height = gr.Slider(minimum=64, maximum=2048, step=8, label="Height", value=512, elem_id="img2img_height") - res_switch_btn = ToolButton(value=switch_values_symbol, elem_id="img2img_res_switch_btn") + with gr.Column(elem_id="img2img_dimensions_row", scale=1): + res_switch_btn = ToolButton(value=switch_values_symbol, elem_id="img2img_res_switch_btn") + 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") @@ -774,7 +777,7 @@ def create_ui(): seed, reuse_seed, subseed, reuse_subseed, subseed_strength, seed_resize_from_h, seed_resize_from_w, seed_checkbox = create_seed_inputs('img2img') elif category == "checkboxes": - with FormRow(elem_id="img2img_checkboxes", variant="compact"): + with FormRow(elem_classes="checkboxes-row", variant="compact"): restore_faces = gr.Checkbox(label='Restore faces', value=False, visible=len(shared.face_restorers) > 1, elem_id="img2img_restore_faces") tiling = gr.Checkbox(label='Tiling', value=False, elem_id="img2img_tiling") diff --git a/modules/ui_common.py b/modules/ui_common.py index a12433d2..d4e00829 100644 --- a/modules/ui_common.py +++ b/modules/ui_common.py @@ -130,7 +130,7 @@ Requested path was: {f} generation_info = None with gr.Column(): with gr.Row(elem_id=f"image_buttons_{tabname}"): - open_folder_button = gr.Button(folder_symbol, elem_id="hidden_element" if shared.cmd_opts.hide_ui_dir_config else f'open_folder_{tabname}') + open_folder_button = gr.Button(folder_symbol, visible=not shared.cmd_opts.hide_ui_dir_config) if tabname != "extras": save = gr.Button('Save', elem_id=f'save_{tabname}') @@ -160,6 +160,7 @@ Requested path was: {f} _js="function(x, y, z){ return [x, y, selected_gallery_index()] }", inputs=[generation_info, html_info, html_info], outputs=[html_info, html_info], + show_progress=False, ) save.click( diff --git a/modules/ui_components.py b/modules/ui_components.py index 284ca0cf..2b1da2cb 100644 --- a/modules/ui_components.py +++ b/modules/ui_components.py @@ -1,55 +1,61 @@ import gradio as gr -class ToolButton(gr.Button, gr.components.FormComponent): +class FormComponent: + def get_expected_parent(self): + return gr.components.Form + + +gr.Dropdown.get_expected_parent = FormComponent.get_expected_parent + + +class ToolButton(FormComponent, gr.Button): """Small button with single emoji as text, fits inside gradio forms""" - def __init__(self, **kwargs): - super().__init__(variant="tool", **kwargs) + def __init__(self, *args, **kwargs): + classes = kwargs.pop("elem_classes", []) + super().__init__(*args, elem_classes=["tool", *classes], **kwargs) def get_block_name(self): return "button" -class ToolButtonTop(gr.Button, gr.components.FormComponent): - """Small button with single emoji as text, with extra margin at top, fits inside gradio forms""" - - def __init__(self, **kwargs): - super().__init__(variant="tool-top", **kwargs) - - def get_block_name(self): - return "button" - - -class FormRow(gr.Row, gr.components.FormComponent): +class FormRow(FormComponent, gr.Row): """Same as gr.Row but fits inside gradio forms""" def get_block_name(self): return "row" -class FormGroup(gr.Group, gr.components.FormComponent): +class FormColumn(FormComponent, gr.Column): + """Same as gr.Column but fits inside gradio forms""" + + def get_block_name(self): + return "column" + + +class FormGroup(FormComponent, gr.Group): """Same as gr.Row but fits inside gradio forms""" def get_block_name(self): return "group" -class FormHTML(gr.HTML, gr.components.FormComponent): +class FormHTML(FormComponent, gr.HTML): """Same as gr.HTML but fits inside gradio forms""" def get_block_name(self): return "html" -class FormColorPicker(gr.ColorPicker, gr.components.FormComponent): +class FormColorPicker(FormComponent, gr.ColorPicker): """Same as gr.ColorPicker but fits inside gradio forms""" def get_block_name(self): return "colorpicker" -class DropdownMulti(gr.Dropdown): +class DropdownMulti(FormComponent, gr.Dropdown): """Same as gr.Dropdown but always multiselect""" def __init__(self, **kwargs): super().__init__(multiselect=True, **kwargs) diff --git a/requirements.txt b/requirements.txt index 6d53f089..e71251c5 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,7 +4,7 @@ basicsr fonts font-roboto gfpgan -gradio==3.16.2 +gradio==3.22.1 invisible-watermark numpy omegaconf diff --git a/requirements_versions.txt b/requirements_versions.txt index 0031c616..ab16e4cc 100644 --- a/requirements_versions.txt +++ b/requirements_versions.txt @@ -3,7 +3,7 @@ transformers==4.25.1 accelerate==0.12.0 basicsr==1.4.2 gfpgan==1.3.8 -gradio==3.16.2 +gradio==3.22.1 numpy==1.23.3 Pillow==9.4.0 realesrgan==0.3.0 diff --git a/script.js b/script.js index 97e0bfcf..978b948f 100644 --- a/script.js +++ b/script.js @@ -1,7 +1,9 @@ function gradioApp() { const elems = document.getElementsByTagName('gradio-app') - const gradioShadowRoot = elems.length == 0 ? null : elems[0].shadowRoot - return !!gradioShadowRoot ? gradioShadowRoot : document; + const elem = elems.length == 0 ? document : elems[0] + + elem.getElementById = function(id){ return document.getElementById(id) } + return elem.shadowRoot ? elem.shadowRoot : elem } function get_uiCurrentTab() { diff --git a/scripts/postprocessing_upscale.py b/scripts/postprocessing_upscale.py index 8842bd91..11eab31a 100644 --- a/scripts/postprocessing_upscale.py +++ b/scripts/postprocessing_upscale.py @@ -17,22 +17,24 @@ class ScriptPostprocessingUpscale(scripts_postprocessing.ScriptPostprocessing): def ui(self): selected_tab = gr.State(value=0) - with gr.Tabs(elem_id="extras_resize_mode"): - with gr.TabItem('Scale by', elem_id="extras_scale_by_tab") as tab_scale_by: - upscaling_resize = gr.Slider(minimum=1.0, maximum=8.0, step=0.05, label="Resize", value=4, elem_id="extras_upscaling_resize") + with gr.Column(): + with FormRow(): + with gr.Tabs(elem_id="extras_resize_mode"): + with gr.TabItem('Scale by', elem_id="extras_scale_by_tab") as tab_scale_by: + upscaling_resize = gr.Slider(minimum=1.0, maximum=8.0, step=0.05, label="Resize", value=4, elem_id="extras_upscaling_resize") - with gr.TabItem('Scale to', elem_id="extras_scale_to_tab") as tab_scale_to: - with FormRow(): - upscaling_resize_w = gr.Number(label="Width", value=512, precision=0, elem_id="extras_upscaling_resize_w") - upscaling_resize_h = gr.Number(label="Height", value=512, precision=0, elem_id="extras_upscaling_resize_h") - upscaling_crop = gr.Checkbox(label='Crop to fit', value=True, elem_id="extras_upscaling_crop") + with gr.TabItem('Scale to', elem_id="extras_scale_to_tab") as tab_scale_to: + with FormRow(): + upscaling_resize_w = gr.Number(label="Width", value=512, precision=0, elem_id="extras_upscaling_resize_w") + upscaling_resize_h = gr.Number(label="Height", value=512, precision=0, elem_id="extras_upscaling_resize_h") + upscaling_crop = gr.Checkbox(label='Crop to fit', value=True, elem_id="extras_upscaling_crop") - with FormRow(): - extras_upscaler_1 = gr.Dropdown(label='Upscaler 1', elem_id="extras_upscaler_1", choices=[x.name for x in shared.sd_upscalers], value=shared.sd_upscalers[0].name) + with FormRow(): + extras_upscaler_1 = gr.Dropdown(label='Upscaler 1', elem_id="extras_upscaler_1", choices=[x.name for x in shared.sd_upscalers], value=shared.sd_upscalers[0].name) - with FormRow(): - extras_upscaler_2 = gr.Dropdown(label='Upscaler 2', elem_id="extras_upscaler_2", choices=[x.name for x in shared.sd_upscalers], value=shared.sd_upscalers[0].name) - extras_upscaler_2_visibility = gr.Slider(minimum=0.0, maximum=1.0, step=0.001, label="Upscaler 2 visibility", value=0.0, elem_id="extras_upscaler_2_visibility") + with FormRow(): + extras_upscaler_2 = gr.Dropdown(label='Upscaler 2', elem_id="extras_upscaler_2", choices=[x.name for x in shared.sd_upscalers], value=shared.sd_upscalers[0].name) + extras_upscaler_2_visibility = gr.Slider(minimum=0.0, maximum=1.0, step=0.001, label="Upscaler 2 visibility", value=0.0, elem_id="extras_upscaler_2_visibility") tab_scale_by.select(fn=lambda: 0, inputs=[], outputs=[selected_tab]) tab_scale_to.select(fn=lambda: 1, inputs=[], outputs=[selected_tab]) diff --git a/style.css b/style.css index 3eac2b17..936930fd 100644 --- a/style.css +++ b/style.css @@ -1,48 +1,139 @@ -.container { - max-width: 100%; + +/* general gradio fixes */ + +:root{ + --checkbox-label-gap: 0.25em 0.1em; + --section-header-text-size: 12pt; } -.token-counter{ +.block.padded{ + padding: 0.2em 0.5em !important; +} + +div.gradio-container{ + max-width: unset !important; +} + +.hidden{ + display: none; +} + +.compact{ + background: transparent !important; + padding: 0 !important; +} + +div.form{ + border-width: 0; + box-shadow: none; + background: transparent; + overflow: visible; + gap: 0.5em; +} + +.block.gradio-dropdown, +.block.gradio-slider, +.block.gradio-checkbox, +.block.gradio-textbox, +.block.gradio-radio, +.block.gradio-checkboxgroup, +.block.gradio-number +{ + border-width: 0 !important; + box-shadow: none !important; +} + +.gap.compact{ + padding: 0; + gap: 0; +} + +div.compact{ + gap: 0.5em; +} + +.gradio-dropdown ul.options{ + max-height: 35em; +} + +.gradio-dropdown label span:not(.has-info){ + margin-bottom: 0; +} + +.gradio-dropdown div.wrap.wrap.wrap.wrap{ + box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05); +} + +.gradio-slider input[type="number"]{ + width: 6em; +} + +.block.gradio-checkbox { + margin: 0.75em 1.5em 0 0; +} + +/* general styled components */ + +.gradio-button.tool{ + max-width: 2.2em; + min-width: 2.2em !important; + height: 2.4em; + align-self: end; + line-height: 1em; + border-radius: 0.5em; +} + +.checkboxes-row{ + margin-bottom: 0.5em; + margin-left: 0em; +} +.checkboxes-row > div{ + flex: 0; + white-space: nowrap; + min-width: auto; +} + + +/* txt2img/img2img specific */ + +.block.token-counter{ position: absolute; display: inline-block; - right: 2em; + right: 1em; min-width: 0 !important; width: auto; z-index: 100; } -.token-counter.error span{ +.block.token-counter span{ + background: var(--input-background-fill) !important; + box-shadow: 0 0 0.0 0.3em rgba(192,192,192,0.15), inset 0 0 0.6em rgba(192,192,192,0.075); + border: 2px solid rgba(192,192,192,0.4) !important; + border-radius: 0.4em; +} + +.block.token-counter.error span{ box-shadow: 0 0 0.0 0.3em rgba(255,0,0,0.15), inset 0 0 0.6em rgba(255,0,0,0.075); border: 2px solid rgba(255,0,0,0.4) !important; } -.token-counter div{ +.block.token-counter div{ display: inline; } -.token-counter span{ +.block.token-counter span{ padding: 0.1em 0.75em; } -#sh{ - min-width: 2em; - min-height: 2em; - max-width: 2em; - max-height: 2em; - flex-grow: 0; - padding-left: 0.25em; - padding-right: 0.25em; - margin: 0.1em 0; - opacity: 0%; - cursor: default; +[id$=_subseed_show]{ + min-width: auto !important; + flex-grow: 0 !important; + display: flex; } -.output-html p {margin: 0 0.5em;} - -.row > *, -.row > .gr-form > * { - min-width: min(120px, 100%); - flex: 1 1 0%; +[id$=_subseed_show] label{ + margin-bottom: 0.5em; + align-self: end; } .performance { @@ -75,196 +166,94 @@ object-fit: scale-down; } #txt2img_actions_column, #img2img_actions_column { - margin: 0.35rem 0.75rem 0.35rem 0; + gap: 0.5em; } -#script_list { - padding: .625rem .75rem 0 .625rem; -} -.justify-center.overflow-x-scroll { - justify-content: left; -} - -.justify-center.overflow-x-scroll button:first-of-type { - margin-left: auto; -} - -.justify-center.overflow-x-scroll button:last-of-type { - margin-right: auto; -} - -[id$=_random_seed], [id$=_random_subseed], [id$=_reuse_seed], [id$=_reuse_subseed], #open_folder{ - min-width: 2.3em; - height: 2.5em; - flex-grow: 0; - padding-left: 0.25em; - padding-right: 0.25em; -} - -#hidden_element{ - display: none; -} - -[id$=_seed_row], [id$=_subseed_row]{ - gap: 0.5rem; - padding: 0.6em; -} - -[id$=_subseed_show_box]{ - min-width: auto; - flex-grow: 0; -} - -[id$=_subseed_show_box] > div{ - border: 0; - height: 100%; -} - -[id$=_subseed_show]{ - min-width: auto; - flex-grow: 0; - padding: 0; -} - -[id$=_subseed_show] label{ - height: 100%; -} - -#txt2img_actions_column, #img2img_actions_column{ - gap: 0; - margin-right: .75rem; -} - #txt2img_tools, #img2img_tools{ gap: 0.4em; } -#interrogate_col{ +.interrogate-col{ min-width: 0 !important; - max-width: 8em !important; - margin-right: 1em; - gap: 0; + max-width: fit-content; + gap: 0.5em; } -#interrogate, #deepbooru{ - margin: 0em 0.25em 0.5em 0.25em; +.interrogate-col > button{ min-width: 8em; max-width: 8em; + height: 5.45em; } -#style_pos_col, #style_neg_col{ - min-width: 8em !important; +.generate-box{ + position: relative; } - -#txt2img_styles_row, #img2img_styles_row{ - gap: 0.25em; - margin-top: 0.3em; -} - -#txt2img_styles_row > button, #img2img_styles_row > button{ - margin: 0; -} - -#txt2img_styles, #img2img_styles{ - padding: 0; -} - -#txt2img_styles > label > div, #img2img_styles > label > div{ - min-height: 3.2em; -} - -ul.list-none{ - max-height: 35em; - z-index: 2000; -} - -.gr-form{ - background: transparent; -} - -.my-4{ - margin-top: 0; - margin-bottom: 0; -} - -#resize_mode{ - flex: 1.5; -} - -button{ - align-self: stretch !important; -} - -.overflow-hidden, .gr-panel{ - overflow: visible !important; -} - -#x_type, #y_type{ - max-width: 10em; -} - -#txt2img_preview, #img2img_preview, #ti_preview{ +.gradio-button.generate-box-skip, .gradio-button.generate-box-interrupt{ position: absolute; - width: 320px; - left: 0; - right: 0; - margin-left: auto; - margin-right: auto; - margin-top: 34px; - z-index: 100; - border: none; - border-top-left-radius: 0; - border-top-right-radius: 0; -} - -@media screen and (min-width: 768px) { - #txt2img_preview, #img2img_preview, #ti_preview { - position: absolute; - } -} - -@media screen and (max-width: 767px) { - #txt2img_preview, #img2img_preview, #ti_preview { - position: relative; - } -} - -#txt2img_preview div.left-0.top-0, #img2img_preview div.left-0.top-0, #ti_preview div.left-0.top-0{ + width: 50%; + height: 100%; display: none; } - -fieldset span.text-gray-500, .gr-block.gr-box span.text-gray-500, label.block span{ - position: absolute; - top: -0.7em; - line-height: 1.2em; - padding: 0; - margin: 0 0.5em; - - background-color: white; - box-shadow: 6px 0 6px 0px white, -6px 0 6px 0px white; - - z-index: 300; +.gradio-button.generate-box-interrupt{ + left: 0; + border-radius: 0.5rem 0 0 0.5rem; +} +.gradio-button.generate-box-skip{ + right: 0; + border-radius: 0 0.5rem 0.5rem 0; } -.dark fieldset span.text-gray-500, .dark .gr-block.gr-box span.text-gray-500, .dark label.block span{ - background-color: rgb(31, 41, 55); - box-shadow: none; - border: 1px solid rgba(128, 128, 128, 0.1); - border-radius: 6px; - padding: 0.1em 0.5em; +#txtimg_hr_finalres{ + min-height: 0 !important; + padding: .625rem .75rem; + margin-left: -0.75em } -#txt2img_column_batch, #img2img_column_batch{ +#txtimg_hr_finalres .resolution{ + font-weight: bold; +} + +.inactive{ + opacity: 0.5; +} + +[id$=_column_batch]{ min-width: min(13.5em, 100%) !important; } -#settings fieldset span.text-gray-500, #settings .gr-block.gr-box span.text-gray-500, #settings label.block span{ - position: relative; - border: none; - margin-right: 8em; +[id$=_dimensions_row]{ + min-width: 0 !important; + max-width: fit-content; + padding: 0 1em; } -#settings .gr-panel div.flex-col div.justify-between div{ - position: relative; - z-index: 200; +#mode_img2img .gradio-image > div.fixed-height, #mode_img2img .gradio-image > div.fixed-height img{ + height: 480px !important; + max-height: 480px !important; + min-height: 480px !important; +} + + +/* settings */ +#quicksettings { + width: fit-content; +} + +#quicksettings > div, #quicksettings > fieldset{ + max-width: 24em; + min-width: 24em; + padding: 0; + border: none; + box-shadow: none; + background: none; + margin-right: 10px; +} + +#quicksettings .gradio-dropdown .wrap-inner{ + flex-wrap: unset; +} + +#quicksettings .gradio-dropdown .single-select{ + white-space: nowrap; + overflow: hidden; } #settings{ @@ -276,14 +265,14 @@ fieldset span.text-gray-500, .gr-block.gr-box span.text-gray-500, label.block s margin-left: 10em; } -#settings > div.flex-wrap{ +#settings > div.tab-nav{ float: left; display: block; margin-left: 0; width: 10em; } -#settings > div.flex-wrap button{ +#settings > div.tab-nav button{ display: block; border: none; text-align: left; @@ -294,29 +283,8 @@ fieldset span.text-gray-500, .gr-block.gr-box span.text-gray-500, label.block s margin: 0 1.2em; } -input[type="range"]{ - margin: 0.5em 0 -0.3em 0; -} - -#mask_bug_info { - text-align: center; - display: block; - margin-top: -0.75em; - margin-bottom: -0.75em; -} - -#txt2img_negative_prompt, #img2img_negative_prompt{ -} - -/* gradio 3.8 adds opacity to progressbar which makes it blink; disable it here */ -.transition.opacity-20 { - opacity: 1 !important; -} - -/* more gradio's garbage cleanup */ -.min-h-\[4rem\] { min-height: unset !important; } -.min-h-\[6rem\] { min-height: unset !important; } +/* live preview */ .progressDiv{ position: relative; height: 20px; @@ -362,6 +330,8 @@ input[type="range"]{ height: 100%; } +/* fullscreen popup (ie in Lora's (i) button) */ + .popup-metadata{ color: black; background: white; @@ -402,6 +372,8 @@ input[type="range"]{ padding: 2em; } +/* fullpage image viewer */ + #lightboxModal{ display: none; position: fixed; @@ -512,45 +484,7 @@ input[type="range"]{ background-color: rgba(0, 0, 0, 0.8); } -#imageARPreview{ - position:absolute; - top:0px; - left:0px; - border:2px solid red; - background:rgba(255, 0, 0, 0.3); - z-index: 900; - pointer-events:none; - display:none -} - -#txt2img_generate_box, #img2img_generate_box{ - position: relative; -} - -#txt2img_interrupt, #img2img_interrupt, #txt2img_skip, #img2img_skip{ - position: absolute; - width: 50%; - height: 100%; - background: #b4c0cc; - display: none; -} - -#txt2img_interrupt, #img2img_interrupt{ - left: 0; - border-radius: 0.5rem 0 0 0.5rem; -} -#txt2img_skip, #img2img_skip{ - right: 0; - border-radius: 0 0.5rem 0.5rem 0; -} - -.red { - color: red; -} - -.gallery-item { - --tw-bg-opacity: 0 !important; -} +/* context menu (ie for the generate button) */ #context-menu{ z-index:9999; @@ -579,61 +513,8 @@ input[type="range"]{ background: #a55000; } -#quicksettings { - width: fit-content; -} -#quicksettings > div, #quicksettings > fieldset{ - max-width: 24em; - min-width: 24em; - padding: 0; - border: none; - box-shadow: none; - background: none; - margin-right: 10px; -} - -#quicksettings > div > div > div > label > span { - position: relative; - margin-right: 9em; - margin-bottom: -1em; -} - -canvas[key="mask"] { - z-index: 12 !important; - filter: invert(); - mix-blend-mode: multiply; - pointer-events: none; -} - - -/* gradio 3.4.1 stuff for editable scrollbar values */ -.gr-box > div > div > input.gr-text-input{ - position: absolute; - right: 0.5em; - top: -0.6em; - z-index: 400; - width: 6em; -} -#quicksettings .gr-box > div > div > input.gr-text-input { - top: -1.12em; -} - -.row.gr-compact{ - overflow: visible; -} - -#img2img_image, #img2img_image > .h-60, #img2img_image > .h-60 > div, #img2img_image > .h-60 > div > img, -#img2img_sketch, #img2img_sketch > .h-60, #img2img_sketch > .h-60 > div, #img2img_sketch > .h-60 > div > img, -#img2maskimg, #img2maskimg > .h-60, #img2maskimg > .h-60 > div, #img2maskimg > .h-60 > div > img, -#inpaint_sketch, #inpaint_sketch > .h-60, #inpaint_sketch > .h-60 > div, #inpaint_sketch > .h-60 > div > img -{ - height: 480px !important; - max-height: 480px !important; - min-height: 480px !important; -} - -/* Extensions */ +/* extensions */ #tab_extensions table{ border-collapse: collapse; @@ -646,6 +527,7 @@ canvas[key="mask"] { #tab_extensions table input[type="checkbox"]{ margin-right: 0.5em; + appearance: checkbox; } #tab_extensions button{ @@ -670,74 +552,7 @@ canvas[key="mask"] { font-size: 90%; } -#image_buttons_txt2img button, #image_buttons_img2img button, #image_buttons_extras button{ - min-width: auto; - padding-left: 0.5em; - padding-right: 0.5em; -} - -.gr-form{ - background-color: white; -} - -.dark .gr-form{ - background-color: rgb(31 41 55 / var(--tw-bg-opacity)); -} - -.gr-button-tool, .gr-button-tool-top{ - max-width: 2.5em; - min-width: 2.5em !important; - height: 2.4em; -} - -.gr-button-tool{ - margin: 0.6em 0em 0.55em 0; -} - -.gr-button-tool-top, #settings .gr-button-tool{ - margin: 1.6em 0.7em 0.55em 0; -} - - -#modelmerger_results_container{ - margin-top: 1em; - overflow: visible; -} - -#modelmerger_models{ - gap: 0; -} - - -#quicksettings .gr-button-tool{ - margin: 0; - border-color: unset; - background-color: unset; -} - -#modelmerger_interp_description>p { - margin: 0!important; - text-align: center; -} -#modelmerger_interp_description { - margin: 0.35rem 0.75rem 1.23rem; -} -#img2img_settings > div.gr-form, #txt2img_settings > div.gr-form { - padding-top: 0.9em; - padding-bottom: 0.9em; -} -#txt2img_settings { - padding-top: 1.16em; - padding-bottom: 0.9em; -} -#img2img_settings { - padding-bottom: 0.9em; -} - -#img2img_settings div.gr-form .gr-form, #txt2img_settings div.gr-form .gr-form, #train_tabs div.gr-form .gr-form{ - border: none; - padding-bottom: 0.5em; -} +/* replace original footer with ours */ footer { display: none !important; @@ -756,90 +571,7 @@ footer { opacity: 0.85; } -#txtimg_hr_finalres{ - min-height: 0 !important; - padding: .625rem .75rem; - margin-left: -0.75em - -} - -#txtimg_hr_finalres .resolution{ - font-weight: bold; -} - -#txt2img_checkboxes, #img2img_checkboxes{ - margin-bottom: 0.5em; - margin-left: 0em; -} -#txt2img_checkboxes > div, #img2img_checkboxes > div{ - flex: 0; - white-space: nowrap; - min-width: auto; -} - -#img2img_copy_to_img2img, #img2img_copy_to_sketch, #img2img_copy_to_inpaint, #img2img_copy_to_inpaint_sketch{ - margin-left: 0em; -} - -#axis_options { - margin-left: 0em; -} - -.inactive{ - opacity: 0.5; -} - -[id*='_prompt_container']{ - gap: 0; -} - -[id*='_prompt_container'] > div{ - margin: -0.4em 0 0 0; -} - -.gr-compact { - border: none; -} - -.dark .gr-compact{ - background-color: rgb(31 41 55 / var(--tw-bg-opacity)); - margin-left: 0; -} - -.gr-compact{ - overflow: visible; -} - -.gr-compact > *{ -} - -.gr-compact .gr-block, .gr-compact .gr-form{ - border: none; - box-shadow: none; -} - -.gr-compact .gr-box{ - border-radius: .5rem !important; - border-width: 1px !important; -} - -#mode_img2img > div > div{ - gap: 0 !important; -} - -[id*='img2img_copy_to_'] { - border: none; -} - -[id*='img2img_copy_to_'] > button { -} - -[id*='img2img_label_copy_to_'] { - font-size: 1.0em; - font-weight: bold; - text-align: center; - line-height: 2.4em; -} +/* extra networks UI */ .extra-networks > div > [id *= '_extra_']{ margin: 0.3em; @@ -1025,7 +757,3 @@ footer { .extra-network-cards .card ul a:hover{ color: red; } - -[id*='_prompt_container'] > div { - margin: 0!important; -} From 46482decd5ec7c15811e1db5f992b0f616472cfe Mon Sep 17 00:00:00 2001 From: AUTOMATIC <16777216c@gmail.com> Date: Tue, 21 Mar 2023 06:49:19 +0300 Subject: [PATCH 2/9] fix ctrl+up/down attention edit fix dropdown obscured by live preview stylistic changes --- javascript/edit-attention.js | 2 +- modules/ui.py | 4 ++-- style.css | 12 +++++++++++- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/javascript/edit-attention.js b/javascript/edit-attention.js index 619bb1fa..20a5aadf 100644 --- a/javascript/edit-attention.js +++ b/javascript/edit-attention.js @@ -1,6 +1,6 @@ function keyupEditAttention(event){ let target = event.originalTarget || event.composedPath()[0]; - if (!target.matches("[id*='_toprow'] textarea.gr-text-input[placeholder]")) return; + if (! target.matches("[id*='_toprow'] [id*='_prompt'] textarea")) return; if (! (event.metaKey || event.ctrlKey)) return; let isPlus = event.key == "ArrowUp" diff --git a/modules/ui.py b/modules/ui.py index 80807ce3..6e0ac89f 100644 --- a/modules/ui.py +++ b/modules/ui.py @@ -587,7 +587,7 @@ def create_ui(): txt2img_prompt.submit(**txt2img_args) submit.click(**txt2img_args) - res_switch_btn.click(lambda w, h: (h, w), inputs=[width, height], outputs=[width, height]) + res_switch_btn.click(lambda w, h: (h, w), inputs=[width, height], outputs=[width, height], show_progress=False) txt_prompt_img.change( fn=modules.images.image_data, @@ -907,7 +907,7 @@ def create_ui(): img2img_prompt.submit(**img2img_args) submit.click(**img2img_args) - res_switch_btn.click(lambda w, h: (h, w), inputs=[width, height], outputs=[width, height]) + res_switch_btn.click(lambda w, h: (h, w), inputs=[width, height], outputs=[width, height], show_progress=False) img2img_interrogate.click( fn=lambda *args: process_interrogate(interrogate, *args), diff --git a/style.css b/style.css index 936930fd..692833bd 100644 --- a/style.css +++ b/style.css @@ -1,9 +1,10 @@ /* general gradio fixes */ -:root{ +:root, .dark{ --checkbox-label-gap: 0.25em 0.1em; --section-header-text-size: 12pt; + --block-background-fill: transparent; } .block.padded{ @@ -54,6 +55,7 @@ div.compact{ .gradio-dropdown ul.options{ max-height: 35em; + z-index: 3000; } .gradio-dropdown label span:not(.has-info){ @@ -72,6 +74,13 @@ div.compact{ margin: 0.75em 1.5em 0 0; } +.gradio-html div.wrap{ + height: 100%; +} +div.gradio-html.min{ + min-height: 0; +} + /* general styled components */ .gradio-button.tool{ @@ -103,6 +112,7 @@ div.compact{ min-width: 0 !important; width: auto; z-index: 100; + top: -0.75em; } .block.token-counter span{ From f93547be18641039aca24e8166f0ed7d495da15e Mon Sep 17 00:00:00 2001 From: AUTOMATIC <16777216c@gmail.com> Date: Tue, 21 Mar 2023 08:18:14 +0300 Subject: [PATCH 3/9] hide delete button for single-item dropdown more stylistic changes --- modules/scripts.py | 15 +++++++++++++-- modules/ui.py | 2 ++ modules/ui_common.py | 2 +- style.css | 43 ++++++++++++++++++++++++++++++++++--------- 4 files changed, 50 insertions(+), 12 deletions(-) diff --git a/modules/scripts.py b/modules/scripts.py index 40d8dcc6..8f55cf24 100644 --- a/modules/scripts.py +++ b/modules/scripts.py @@ -513,6 +513,18 @@ def reload_scripts(): scripts_postproc = scripts_postprocessing.ScriptPostprocessingRunner() +def add_classes_to_gradio_component(comp): + """ + this adds gradio-* to the component for css styling (ie gradio-button to gr.Button), as well as some others + """ + + comp.elem_classes = ["gradio-" + comp.get_block_name(), *(comp.elem_classes or [])] + + if getattr(comp, 'multiselect', False): + comp.elem_classes.append('multiselect') + + + def IOComponent_init(self, *args, **kwargs): if scripts_current is not None: scripts_current.before_component(self, **kwargs) @@ -521,8 +533,7 @@ def IOComponent_init(self, *args, **kwargs): res = original_IOComponent_init(self, *args, **kwargs) - # this adds gradio-* to every component for css styling (ie gradio-button to gr.Button) - self.elem_classes = ["gradio-" + self.get_block_name(), *(self.elem_classes or [])] + add_classes_to_gradio_component(self) script_callbacks.after_component_callback(self, **kwargs) diff --git a/modules/ui.py b/modules/ui.py index 6e0ac89f..c5b0e876 100644 --- a/modules/ui.py +++ b/modules/ui.py @@ -1601,11 +1601,13 @@ def create_ui(): for i, k, item in quicksettings_list: component = component_dict[k] + info = opts.data_labels[k] component.change( fn=lambda value, k=k: run_settings_single(value, key=k), inputs=[component], outputs=[component, text_settings], + show_progress=info.refresh is not None, ) text_settings.change( diff --git a/modules/ui_common.py b/modules/ui_common.py index d4e00829..7b752b45 100644 --- a/modules/ui_common.py +++ b/modules/ui_common.py @@ -129,7 +129,7 @@ Requested path was: {f} generation_info = None with gr.Column(): - with gr.Row(elem_id=f"image_buttons_{tabname}"): + with gr.Row(elem_id=f"image_buttons_{tabname}", elem_classes="image-buttons"): open_folder_button = gr.Button(folder_symbol, visible=not shared.cmd_opts.hide_ui_dir_config) if tabname != "extras": diff --git a/style.css b/style.css index 692833bd..677f03cd 100644 --- a/style.css +++ b/style.css @@ -8,7 +8,7 @@ } .block.padded{ - padding: 0.2em 0.5em !important; + padding: 0 !important; } div.gradio-container{ @@ -38,7 +38,8 @@ div.form{ .block.gradio-textbox, .block.gradio-radio, .block.gradio-checkboxgroup, -.block.gradio-number +.block.gradio-number, +.block.gradio-colorpicker { border-width: 0 !important; box-shadow: none !important; @@ -46,11 +47,11 @@ div.form{ .gap.compact{ padding: 0; - gap: 0; + gap: 0.2em 0; } div.compact{ - gap: 0.5em; + gap: 1em; } .gradio-dropdown ul.options{ @@ -58,7 +59,10 @@ div.compact{ z-index: 3000; } -.gradio-dropdown label span:not(.has-info){ +.gradio-dropdown label span:not(.has-info), +.gradio-textbox label span:not(.has-info), +.gradio-number label span:not(.has-info) +{ margin-bottom: 0; } @@ -66,6 +70,14 @@ div.compact{ box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05); } +.gradio-dropdown .token-remove.remove-all.remove-all{ + display: none; +} + +.gradio-dropdown.multiselect .token-remove.remove-all.remove-all{ + display: flex; +} + .gradio-slider input[type="number"]{ width: 6em; } @@ -81,6 +93,17 @@ div.gradio-html.min{ min-height: 0; } +.block.gradio-gallery{ + background: var(--input-background-fill); +} + +.gradio-container .prose a, .gradio-container .prose a:visited{ + color: unset; + text-decoration: none; +} + + + /* general styled components */ .gradio-button.tool{ @@ -188,9 +211,7 @@ div.gradio-html.min{ gap: 0.5em; } .interrogate-col > button{ - min-width: 8em; - max-width: 8em; - height: 5.45em; + flex: 1; } .generate-box{ @@ -241,6 +262,10 @@ div.gradio-html.min{ min-height: 480px !important; } +.image-buttons button{ + min-width: auto; +} + /* settings */ #quicksettings { @@ -254,7 +279,6 @@ div.gradio-html.min{ border: none; box-shadow: none; background: none; - margin-right: 10px; } #quicksettings .gradio-dropdown .wrap-inner{ @@ -286,6 +310,7 @@ div.gradio-html.min{ display: block; border: none; text-align: left; + white-space: initial; } #settings_result{ From 6eacaad4a92f5c85eb9addd096a673bf3d5db5fe Mon Sep 17 00:00:00 2001 From: AUTOMATIC <16777216c@gmail.com> Date: Tue, 21 Mar 2023 08:49:08 +0300 Subject: [PATCH 4/9] enable queue by default more stylistic changes --- modules/shared.py | 3 ++- modules/ui.py | 4 ++-- modules/ui_extensions.py | 2 +- style.css | 39 ++++++++++++++++++++++++++++----------- webui.py | 2 +- 5 files changed, 34 insertions(+), 16 deletions(-) diff --git a/modules/shared.py b/modules/shared.py index f28a12cc..0b70d104 100644 --- a/modules/shared.py +++ b/modules/shared.py @@ -107,7 +107,8 @@ parser.add_argument("--cors-allow-origins-regex", type=str, help="Allowed CORS o parser.add_argument("--tls-keyfile", type=str, help="Partially enables TLS, requires --tls-certfile to fully function", default=None) parser.add_argument("--tls-certfile", type=str, help="Partially enables TLS, requires --tls-keyfile to fully function", default=None) parser.add_argument("--server-name", type=str, help="Sets hostname of server", default=None) -parser.add_argument("--gradio-queue", action='store_true', help="Uses gradio queue; experimental option; breaks restart UI button") +parser.add_argument("--gradio-queue", action='store_true', help="does not do anything", default=True) +parser.add_argument("--no-gradio-queue", action='store_true', help="Disables gradio queue; causes the webpage to use http requests instead of websockets; was the defaul in earlier versions") parser.add_argument("--skip-version-check", action='store_true', help="Do not check versions of torch and xformers") parser.add_argument("--no-hashing", action='store_true', help="disable sha256 hashing of checkpoints to help loading performance", default=False) parser.add_argument("--no-download-sd-model", action='store_true', help="don't download SD1.5 model even if no model is found in --ckpt-dir", default=False) diff --git a/modules/ui.py b/modules/ui.py index c5b0e876..9b9bfa8b 100644 --- a/modules/ui.py +++ b/modules/ui.py @@ -478,7 +478,7 @@ def create_ui(): width = gr.Slider(minimum=64, maximum=2048, step=8, label="Width", value=512, elem_id="txt2img_width") height = gr.Slider(minimum=64, maximum=2048, step=8, label="Height", value=512, elem_id="txt2img_height") - with gr.Column(elem_id="txt2img_dimensions_row", scale=1): + with gr.Column(elem_id="txt2img_dimensions_row", scale=1, elem_classes="dimensions-tools"): res_switch_btn = ToolButton(value=switch_values_symbol, elem_id="txt2img_res_switch_btn") if opts.dimensions_and_batch_together: @@ -758,7 +758,7 @@ def create_ui(): width = gr.Slider(minimum=64, maximum=2048, step=8, label="Width", value=512, elem_id="img2img_width") height = gr.Slider(minimum=64, maximum=2048, step=8, label="Height", value=512, elem_id="img2img_height") - with gr.Column(elem_id="img2img_dimensions_row", scale=1): + with gr.Column(elem_id="img2img_dimensions_row", scale=1, elem_classes="dimensions-tools"): res_switch_btn = ToolButton(value=switch_values_symbol, elem_id="img2img_res_switch_btn") if opts.dimensions_and_batch_together: diff --git a/modules/ui_extensions.py b/modules/ui_extensions.py index df75a925..50173e68 100644 --- a/modules/ui_extensions.py +++ b/modules/ui_extensions.py @@ -244,7 +244,7 @@ def refresh_available_extensions_from_data(hide_tags, sort_column): hidden += 1 continue - install_code = f"""""" + install_code = f"""""" tags_text = ", ".join([f"{x}" for x in extension_tags]) diff --git a/style.css b/style.css index 677f03cd..cee13cf7 100644 --- a/style.css +++ b/style.css @@ -70,6 +70,15 @@ div.compact{ box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05); } +.gradio-dropdown .wrap-inner.wrap-inner.wrap-inner{ + flex-wrap: unset; +} + +.gradio-dropdown .single-select{ + white-space: nowrap; + overflow: hidden; +} + .gradio-dropdown .token-remove.remove-all.remove-all{ display: none; } @@ -125,6 +134,22 @@ div.gradio-html.min{ min-width: auto; } +button.custom-button{ + border-radius: var(--button-large-radius); + padding: var(--button-large-padding); + font-weight: var(--button-large-text-weight); + border: var(--button-border-width) solid var(--button-secondary-border-color); + background: var(--button-secondary-background-fill); + color: var(--button-secondary-text-color); + font-size: var(--button-large-text-size); + display: inline-flex; + justify-content: center; + align-items: center; + transition: var(--button-transition); + box-shadow: var(--button-shadow); + text-align: center; +} + /* txt2img/img2img specific */ @@ -250,10 +275,11 @@ div.gradio-html.min{ min-width: min(13.5em, 100%) !important; } -[id$=_dimensions_row]{ +div.dimensions-tools{ min-width: 0 !important; max-width: fit-content; - padding: 0 1em; + flex-direction: row; + align-content: center; } #mode_img2img .gradio-image > div.fixed-height, #mode_img2img .gradio-image > div.fixed-height img{ @@ -281,15 +307,6 @@ div.gradio-html.min{ background: none; } -#quicksettings .gradio-dropdown .wrap-inner{ - flex-wrap: unset; -} - -#quicksettings .gradio-dropdown .single-select{ - white-space: nowrap; - overflow: hidden; -} - #settings{ display: block; } diff --git a/webui.py b/webui.py index aaec79fd..ca725b7d 100644 --- a/webui.py +++ b/webui.py @@ -240,7 +240,7 @@ def webui(): shared.demo = modules.ui.create_ui() startup_timer.record("create ui") - if cmd_opts.gradio_queue: + if not cmd_opts.no_gradio_queue: shared.demo.queue(64) gradio_auth_creds = [] From d3dcb05904de0a21cee27466da399263d21dbf43 Mon Sep 17 00:00:00 2001 From: AUTOMATIC <16777216c@gmail.com> Date: Tue, 21 Mar 2023 09:24:19 +0300 Subject: [PATCH 5/9] fix extra networks ui --- modules/ui_extra_networks.py | 2 +- style.css | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/modules/ui_extra_networks.py b/modules/ui_extra_networks.py index cdfd6f2a..8cd6d8cf 100644 --- a/modules/ui_extra_networks.py +++ b/modules/ui_extra_networks.py @@ -86,7 +86,7 @@ class ExtraNetworksPage: subdirs = {"": 1, **subdirs} subdirs_html = "".join([f""" - """ for subdir in subdirs]) diff --git a/style.css b/style.css index cee13cf7..b258552d 100644 --- a/style.css +++ b/style.css @@ -636,12 +636,12 @@ footer { .extra-network-subdirs button{ margin: 0 0.15em; } - -#txt2img_extra_networks .search, #img2img_extra_networks .search{ +.extra-networks .tab-nav .search{ display: inline-block; max-width: 16em; margin: 0.3em; align-self: center; + width: 16em; } #txt2img_extra_view, #img2img_extra_view { @@ -766,12 +766,15 @@ footer { left: 0; right: 0; padding: 0.5em; - color: white; background: rgba(0,0,0,0.5); box-shadow: 0 0 0.25em 0.25em rgba(0,0,0,0.5); text-shadow: 0 0 0.2em black; } +.extra-network-cards .card .actions *{ + color: white; +} + .extra-network-cards .card .actions:hover{ box-shadow: 0 0 0.75em 0.75em rgba(0,0,0,0.5) !important; } From 9e1afa9eb421ec3c7fa4d972b8f4728f3fb9b210 Mon Sep 17 00:00:00 2001 From: AUTOMATIC <16777216c@gmail.com> Date: Sat, 25 Mar 2023 07:29:51 +0300 Subject: [PATCH 6/9] bump gradio to 3.23 fix broken image dragging --- modules/generation_parameters_copypaste.py | 7 ++++++- modules/images.py | 4 +++- requirements.txt | 2 +- requirements_versions.txt | 2 +- style.css | 1 - 5 files changed, 11 insertions(+), 5 deletions(-) diff --git a/modules/generation_parameters_copypaste.py b/modules/generation_parameters_copypaste.py index 7c0b5b4e..6df76858 100644 --- a/modules/generation_parameters_copypaste.py +++ b/modules/generation_parameters_copypaste.py @@ -401,9 +401,14 @@ def connect_paste(button, paste_fields, input_comp, override_settings_component, button.click( fn=paste_func, - _js=f"recalculate_prompts_{tabname}", inputs=[input_comp], outputs=[x[0] for x in paste_fields], ) + button.click( + fn=None, + _js=f"recalculate_prompts_{tabname}", + inputs=[], + outputs=[], + ) diff --git a/modules/images.py b/modules/images.py index 7df2b08c..26be5bae 100644 --- a/modules/images.py +++ b/modules/images.py @@ -640,6 +640,8 @@ Steps: {json_info["steps"]}, Sampler: {sampler}, CFG scale: {json_info["scale"]} def image_data(data): + import gradio as gr + try: image = Image.open(io.BytesIO(data)) textinfo, _ = read_info_from_image(image) @@ -655,7 +657,7 @@ def image_data(data): except Exception: pass - return '', None + return gr.update(), None def flatten(img, bgcolor): diff --git a/requirements.txt b/requirements.txt index e71251c5..3c40fd07 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,7 +4,7 @@ basicsr fonts font-roboto gfpgan -gradio==3.22.1 +gradio==3.23 invisible-watermark numpy omegaconf diff --git a/requirements_versions.txt b/requirements_versions.txt index ab16e4cc..77e3da4e 100644 --- a/requirements_versions.txt +++ b/requirements_versions.txt @@ -3,7 +3,7 @@ transformers==4.25.1 accelerate==0.12.0 basicsr==1.4.2 gfpgan==1.3.8 -gradio==3.22.1 +gradio==3.23 numpy==1.23.3 Pillow==9.4.0 realesrgan==0.3.0 diff --git a/style.css b/style.css index b258552d..a55d8b39 100644 --- a/style.css +++ b/style.css @@ -55,7 +55,6 @@ div.compact{ } .gradio-dropdown ul.options{ - max-height: 35em; z-index: 3000; } From 1bfa1be6dd86120132a550dfbf61f2f308979016 Mon Sep 17 00:00:00 2001 From: AUTOMATIC <16777216c@gmail.com> Date: Sat, 25 Mar 2023 08:28:21 +0300 Subject: [PATCH 7/9] fix clipping in lightbox image viewer --- style.css | 85 ++++++++++++++++--------------------------------------- 1 file changed, 25 insertions(+), 60 deletions(-) diff --git a/style.css b/style.css index a55d8b39..029b5413 100644 --- a/style.css +++ b/style.css @@ -426,86 +426,51 @@ div.dimensions-tools{ /* fullpage image viewer */ #lightboxModal{ - display: none; - position: fixed; - z-index: 1001; - padding-top: 100px; - left: 0; - top: 0; - width: 100%; - height: 100%; - overflow: auto; - background-color: rgba(20, 20, 20, 0.95); - user-select: none; - -webkit-user-select: none; + display: none; + position: fixed; + z-index: 1001; + left: 0; + top: 0; + width: 100%; + height: 100%; + overflow: auto; + background-color: rgba(20, 20, 20, 0.95); + user-select: none; + -webkit-user-select: none; + flex-direction: column; } .modalControls { - display: grid; - grid-template-columns: 32px 32px 32px 1fr 32px; - grid-template-areas: "zoom tile save space close"; - position: absolute; - top: 0; - left: 0; - right: 0; - padding: 16px; - gap: 16px; + display: flex; + gap: 1em; + padding: 1em; background-color: rgba(0,0,0,0.2); } - .modalClose { - grid-area: close; + margin-left: auto; } - -.modalZoom { - grid-area: zoom; -} - -.modalSave { - grid-area: save; -} - -.modalTileImage { - grid-area: tile; -} - -.modalClose, -.modalZoom, -.modalTileImage { - color: white; - font-size: 35px; - font-weight: bold; - cursor: pointer; -} - -.modalSave { +.modalControls span{ color: white; - font-size: 28px; - margin-top: 8px; + font-size: 35px; font-weight: bold; cursor: pointer; + width: 1em; } -.modalClose:hover, -.modalClose:focus, -.modalSave:hover, -.modalSave:focus, -.modalZoom:hover, -.modalZoom:focus { - color: #999; - text-decoration: none; - cursor: pointer; +.modalControls span:hover, .modalControls span:focus{ + color: #999; + text-decoration: none; } -#modalImage { +#lightboxModal > img { display: block; margin: auto; width: auto; } -.modalImageFullscreen { +#lightboxModal > img.modalImageFullscreen{ object-fit: contain; - height: 90%; + height: 100%; } .modalPrev, From 82905f520c6e92b2b955fec02cd9d04d7de01560 Mon Sep 17 00:00:00 2001 From: AUTOMATIC <16777216c@gmail.com> Date: Sat, 25 Mar 2023 08:48:34 +0300 Subject: [PATCH 8/9] restore interrupt/stop button styling --- style.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/style.css b/style.css index 029b5413..aa5ecb34 100644 --- a/style.css +++ b/style.css @@ -246,6 +246,10 @@ button.custom-button{ width: 50%; height: 100%; display: none; + background: #b4c0cc; +} +.gradio-button.generate-box-skip:hover, .gradio-button.generate-box-interrupt:hover{ + background: #c2cfdb; } .gradio-button.generate-box-interrupt{ left: 0; From 23d68bfc9a4d13cd7b9ffc98e404eb0a818b1bd4 Mon Sep 17 00:00:00 2001 From: AUTOMATIC <16777216c@gmail.com> Date: Sat, 25 Mar 2023 08:54:01 +0300 Subject: [PATCH 9/9] fix generate forever and other context menus --- javascript/contextMenus.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/contextMenus.js b/javascript/contextMenus.js index 11bcce1b..06f505b0 100644 --- a/javascript/contextMenus.js +++ b/javascript/contextMenus.js @@ -43,7 +43,7 @@ contextMenuInit = function(){ }) - gradioApp().getRootNode().appendChild(contextMenu) + gradioApp().appendChild(contextMenu) let menuWidth = contextMenu.offsetWidth + 4; let menuHeight = contextMenu.offsetHeight + 4;