From 51f7db16cf9a3a57e36dccda724710f3a0f7e19a Mon Sep 17 00:00:00 2001 From: Tom <9644716+BlafKing@users.noreply.github.com> Date: Fri, 24 Nov 2023 06:59:14 +0100 Subject: [PATCH] Update to v2.0 --- .gitignore | 3 +- README.md | 25 ++++- javascript/civitai-html.js | 161 +++++++++++++++++++++++++++++---- scripts/civitai_api.py | 36 ++++++-- scripts/civitai_file_manage.py | 48 +++++++++- scripts/civitai_gui.py | 68 +++++++++----- style.css | 12 +++ 7 files changed, 302 insertions(+), 51 deletions(-) diff --git a/.gitignore b/.gitignore index 7b62f12..d0683b4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ __pycache__ -.vscode \ No newline at end of file +.vscode +running \ No newline at end of file diff --git a/README.md b/README.md index b77d99a..1cf7dc2 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,10 @@ * Assign tags by scanning all installed models for automatic use in image generation. +

Quick Model Info Access 📊

+ +* A button for each model card in txt2img and img2img to load it into the extension. +

High-speed downloads with Aria2 🚄

* Maximize your bandwidth for lightning-fast downloads. @@ -86,14 +90,29 @@ These settings can be found under the "Settings" tab in Web-UI and then under th # Preview 👀 -https://github.com/BlafKing/sd-civitai-browser/assets/9644716/ea873c3e-a7e4-44a8-907a-e9bddf13bc55 +https://github.com/BlafKing/sd-civitai-browser-plus/assets/9644716/44c5c7a0-4854-4043-bfbb-f32fa9df5a74 -(Theme used: [Lobe](https://github.com/canisminor1990/sd-webui-lobe-theme)) - # Changelog 📋 +

v2.0

+* Feature: New button on each model card in txt2img and img2img to view it in the extension. +
+ Preview + +![ezgif-3-b1f0de4dd2](https://github.com/BlafKing/sd-civitai-browser-plus/assets/9644716/536a693a-c30c-438e-a34f-1aec54e4e7ee) + +
+ +* Feature: Ability to set [\Model Name] & [\Model Name\Version Name] as default sub folders. +* New setting: Hide sub folders that start with a '.' +* Bug fix: Preview HTML is now emptied when loading a new page. +* Bug fix: Buttons now correctly display when loading new page. +* Bug fix: Fixed compatibility with SD.Next. (again) +* Bug fix: Emptied tags, base model, and filename upon loading new page. + +---

v1.16

* Feature: Ability to download/update model preview images in Update Models tab. diff --git a/javascript/civitai-html.js b/javascript/civitai-html.js index be76974..82ba748 100644 --- a/javascript/civitai-html.js +++ b/javascript/civitai-html.js @@ -1,17 +1,23 @@ "use strict"; // Selects a model by pressing on card -function select_model(model_name) { - var civitaiDiv = document.getElementById('civitai_preview_html'); - let model_dropdown = gradioApp().querySelector('#eventtext1 textarea'); - if (model_dropdown && model_name) { - let randomNumber = Math.floor(Math.random() * 1000); - let paddedNumber = String(randomNumber).padStart(3, '0'); - model_dropdown.value = model_name + "." + paddedNumber; - updateInput(model_dropdown); - observer.unobserve(civitaiDiv); - observer.observe(civitaiDiv); - } +function select_model(model_name, bool = false, content_type = null) { + const output = bool ? gradioApp().querySelector('#model_sent textarea') : gradioApp().querySelector('#model_select textarea'); + + if (output && model_name) { + const randomNumber = Math.floor(Math.random() * 1000); + const paddedNumber = String(randomNumber).padStart(3, '0'); + output.value = model_name + "." + paddedNumber; + updateInput(output); + } + + if (content_type) { + const outputType = gradioApp().querySelector('#type_sent textarea'); + const randomNumber = Math.floor(Math.random() * 1000); + const paddedNumber = String(randomNumber).padStart(3, '0'); + outputType.value = content_type + "." + paddedNumber; + updateInput(outputType); + } } // Changes the card size @@ -341,9 +347,7 @@ function handleCivitaiDivChanges() { document.addEventListener("scroll", handleCivitaiDivChanges) // Create the accordion dropdown inside the settings tab -function createAccordion() { - var containerDiv = document.querySelector("#settings_civitai_browser_plus > div > div"); - var subfolders = containerDiv.querySelectorAll("[id$='subfolder']"); +function createAccordion(containerDiv, subfolders, name) { if (containerDiv == null || subfolders.length == 0) { return; } @@ -351,7 +355,7 @@ function createAccordion() { accordionContainer.id = 'settings-accordion'; var toggleButton = document.createElement('button'); toggleButton.id = 'accordionToggle'; - toggleButton.innerHTML = 'Default sub folders
â–¼
'; + toggleButton.innerHTML = name + '
â–¼
'; toggleButton.onclick = function () { accordionDiv.style.display = (accordionDiv.style.display === 'none') ? 'block' : 'none'; toggleButton.lastChild.style.transform = accordionDiv.style.display === 'none' ? 'rotate(90deg)' : 'rotate(0)'; @@ -366,6 +370,122 @@ function createAccordion() { containerDiv.appendChild(accordionContainer); } +// Adds a button to the cards in txt2img and img2img +function createCardButtons(event) { + const clickedElement = event.target; + const validButtonNames = ['Textual Inversion', 'Hypernetworks', 'Checkpoints', 'Lora']; + const validParentIds = ['txt2img_textual_inversion_cards_html', 'txt2img_hypernetworks_cards_html', 'txt2img_checkpoints_cards_html', 'txt2img_lora_cards_html']; + + const hasMatchingButtonName = validButtonNames.some(buttonName => + clickedElement.innerText.trim() === buttonName + ); + + const flexboxDivs = document.querySelectorAll('.layoutkit-flexbox'); + let isLobeTheme = false; + flexboxDivs.forEach(div => { + const anchorElements = div.querySelectorAll('a'); + const hasGitHubLink = Array.from(anchorElements).some(anchor => anchor.href === 'https://github.com/lobehub/sd-webui-lobe-theme/releases'); + if (hasGitHubLink) { + isLobeTheme = true; + } + }); + + if (hasMatchingButtonName || isLobeTheme) { + const checkForCardDivs = setInterval(() => { + const cardDivs = document.querySelectorAll('.card'); + + if (cardDivs.length > 0) { + clearInterval(checkForCardDivs); + + cardDivs.forEach(cardDiv => { + const buttonRow = cardDiv.querySelector('.button-row'); + const actions = cardDiv.querySelector('.actions'); + const nameSpan = actions.querySelector('.name'); + let modelName = nameSpan.textContent.trim(); + let currentElement = cardDiv.parentElement; + let content_type = null; + + while (currentElement) { + const parentId = currentElement.id; + if (validParentIds.includes(parentId)) { + content_type = parentId; + break; + } + currentElement = currentElement.parentElement; + } + + const existingDiv = buttonRow.querySelector('.goto-civitbrowser.card-button'); + if (existingDiv) { + return; + } + + const metaDataButton = buttonRow.querySelector('.metadata-button.card-button') + + const newDiv = document.createElement('div'); + newDiv.classList.add('goto-civitbrowser', 'card-button'); + newDiv.addEventListener('click', function (event) { + event.stopPropagation(); + sendModelToBrowser(modelName, content_type); + }); + + const svgIcon = document.createElementNS("http://www.w3.org/2000/svg", "svg"); + if (isLobeTheme) { + svgIcon.setAttribute('width', '25'); + svgIcon.setAttribute('height', '25'); + } else { + if (metaDataButton) { + metaDataButton.style.paddingTop = '5px'; + metaDataButton.style.width = '42px'; + metaDataButton.style.fontSize = '230%'; + } + svgIcon.setAttribute('width', '40'); + svgIcon.setAttribute('height', '40'); + } + svgIcon.setAttribute('viewBox', '75 0 500 500'); + svgIcon.setAttribute('fill', 'white'); + + svgIcon.innerHTML = ` + + + `; + + newDiv.appendChild(svgIcon); + buttonRow.insertBefore(newDiv, buttonRow.firstChild); + }); + } + }, 100); + } +} + +document.addEventListener('click', createCardButtons); + +function sendModelToBrowser(modelName, content_type) { + const tabNav = document.querySelector('.tab-nav'); + const buttons = tabNav.querySelectorAll('button'); + for (const button of buttons) { + if (button.textContent.includes('Civitai')) { + button.click(); + + const firstButton = document.querySelector('#tab_civitai_interface > div > div > div > button'); + if (firstButton) { + firstButton.click(); + } + } + } + select_model(modelName, true, content_type); +} + +// Clicks the first item in the browser cards list +function clickFirstFigureInColumn() { + const columnDiv = document.querySelector('.column.civmodellist'); + if (columnDiv) { + const firstFigure = columnDiv.querySelector('figure'); + if (firstFigure) { + firstFigure.click(); + } + } +} + // Runs all functions when the page is fully loaded function onPageLoad() { const divElement = document.getElementById('setting_custom_api_key'); @@ -375,6 +495,16 @@ function onPageLoad() { return; } + var subfolderDiv = document.querySelector("#settings_civitai_browser_plus > div > div"); + var subfolders = subfolderDiv.querySelectorAll("[id$='subfolder']"); + + createAccordion(subfolderDiv, subfolders, "Default sub folders"); + + var upscalerDiv = document.querySelector("#settings_civitai_browser_plus > div > div > #settings-accordion > div"); + var upscalers = upscalerDiv.querySelectorAll("[id$='upscale_subfolder']"); + + createAccordion(upscalerDiv, upscalers, "Upscalers"); + observer.observe(civitaiDiv); clearInterval(intervalID); updateSVGIcons(); @@ -384,7 +514,6 @@ function onPageLoad() { setupClickOutsideListener(); createLink(infoElement); updateBackToTopVisibility([{isIntersecting: false}]); - createAccordion(); } // Checks every second if the page is fully loaded diff --git a/scripts/civitai_api.py b/scripts/civitai_api.py index 817cba0..d5db683 100644 --- a/scripts/civitai_api.py +++ b/scripts/civitai_api.py @@ -462,10 +462,15 @@ def update_next_page(content_type, sort_type, period_type, use_search_term, sear gr.Slider.update(value=current_page, maximum=total_pages, label=page_string), # Page Count gr.Button.update(interactive=False), # Save Tags gr.Button.update(interactive=False), # Save Images - gr.Button.update(interactive=False), # Download Button + gr.Button.update(interactive=False, visible=False if gl.isDownloading else True), # Download Button + gr.Button.update(interactive=False, visible=False), # Delete Button gr.Textbox.update(interactive=False, value=None), # Install Path gr.Dropdown.update(choices=[], value="", interactive=False), # Sub Folder List - gr.Dropdown.update(choices=[], value="", interactive=False) # File List + gr.Dropdown.update(choices=[], value="", interactive=False), # File List + gr.HTML.update(value='
'), # Preview HTML + gr.Textbox.update(value=None), # Trained Tags + gr.Textbox.update(value=None), # Base Model + gr.Textbox.update(value=None) # Model Filename ) def pagecontrol(json_data): @@ -549,10 +554,16 @@ def update_model_list(content_type, sort_type, period_type, use_search_term, sea gr.Slider.update(value=current_page, maximum=total_pages, label=page_string), # Page Count gr.Button.update(interactive=False), # Save Tags gr.Button.update(interactive=False), # Save Images - gr.Button.update(interactive=False), # Download Button - gr.Textbox.update(interactive=False, value=None), # Install Path + gr.Button.update(interactive=False, visible=False if gl.isDownloading else True), # Download Button + gr.Button.update(interactive=False, visible=False), # Delete Button + gr.Textbox.update(interactive=False, value=None, visible=True), # Install Path gr.Dropdown.update(choices=[], value="", interactive=False), # Sub Folder List - gr.Dropdown.update(choices=[], value="", interactive=False) # File List + gr.Dropdown.update(choices=[], value="", interactive=False), # File List + gr.HTML.update(value='
'), # Preview HTML + gr.Textbox.update(value=None), # Trained Tags + gr.Textbox.update(value=None), # Base Model + gr.Textbox.update(value=None) # Model Filename + ) def update_model_versions(model_name): @@ -817,9 +828,13 @@ def update_model_info(model_name=None, model_version=None): break insert_sub = getattr(opts, "insert_sub", True) + dot_subfolders = getattr(opts, "dot_subfolders", True) + try: sub_folders = ["None"] for root, dirs, _ in os.walk(model_folder): + if dot_subfolders: + dirs = [d for d in dirs if not d.startswith('.')] for d in dirs: sub_folder = os.path.relpath(os.path.join(root, d), model_folder) if sub_folder: @@ -828,11 +843,13 @@ def update_model_info(model_name=None, model_version=None): sub_folders.remove("None") sub_folders = sorted(sub_folders) sub_folders.insert(0, "None") + sub_opt1 = os.path.join(os.sep, model_name) + sub_opt2 = os.path.join(os.sep, model_name, model_version) if insert_sub: model_name = model_name.replace('/', '').replace('\\', '') model_version = model_version.replace('/', '').replace('\\', '') - sub_folders.insert(1, os.path.join(os.sep, model_name)) - sub_folders.insert(2, os.path.join(os.sep, model_name, model_version)) + sub_folders.insert(1, sub_opt1) + sub_folders.insert(2, sub_opt2) list = set() sub_folders = [x for x in sub_folders if not (x in list or list.add(x))] @@ -840,6 +857,11 @@ def update_model_info(model_name=None, model_version=None): sub_folders = ["None"] default_sub = sub_folder_value(content_type, desc) + if default_sub == f"{os.sep}Model Name": + default_sub = sub_opt1 + elif default_sub == f"{os.sep}Model Name{os.sep}Version Name": + default_sub = sub_opt2 + if folder_location == "None": folder_location = model_folder if default_sub != "None": diff --git a/scripts/civitai_file_manage.py b/scripts/civitai_file_manage.py index 7d2fc87..953bac0 100644 --- a/scripts/civitai_file_manage.py +++ b/scripts/civitai_file_manage.py @@ -332,6 +332,48 @@ def gen_sha256(file_path): return hash_value +def model_from_sent(model_name, content_type, click_first_item): + model_name = re.sub(r'\.\d{3}$', '', model_name) + content_type = re.sub(r'\.\d{3}$', '', content_type) + content_mapping = { + "txt2img_textual_inversion_cards_html": ['TextualInversion'], + "txt2img_hypernetworks_cards_html": ['Hypernetwork'], + "txt2img_checkpoints_cards_html": ['Checkpoint'], + "txt2img_lora_cards_html": ['LORA', 'LoCon'] + } + content_type = content_mapping.get(content_type, content_type) + + for content_type_item in content_type: + folder = _api.contenttype_folder(content_type_item) + for folder_path, _, files in os.walk(folder): + for file in files: + if file.startswith(model_name) and not file.endswith(".json"): + model_file = os.path.join(folder_path, file) + + + modelID = get_models(model_file) + gl.json_data = _api.api_to_data(content_type, "Newest", "AllTime", "Model name", None, None, None, f"civitai.com/models/{modelID}") + if gl.json_data == "timeout": + HTML = '
The Civit-API has timed out, please try again.
The servers might be too busy or the selected model could not be found.
' + number = click_first_item + if gl.json_data != None and gl.json_data != "timeout": + model_dict = {} + for item in gl.json_data['items']: + model_dict[item['name']] = item['name'] + HTML = _api.model_list_html(gl.json_data, model_dict) + (hasPrev, hasNext, current_page, total_pages) = _api.pagecontrol(gl.json_data) + page_string = f"Page: {current_page}/{total_pages}" + number = _download.random_number(click_first_item) + + + return ( + gr.HTML.update(HTML), # Card HTML + gr.Button.update(interactive=hasPrev), # Prev Button + gr.Button.update(interactive=hasNext), # Next Button + gr.Slider.update(value=current_page, maximum=total_pages, label=page_string), # Page Slider + gr.Textbox.update(number) # Click first card trigger + ) + def is_image_url(url): image_extensions = ['.jpg', '.jpeg', '.png', '.gif', '.bmp'] parsed = urlparse(url) @@ -845,9 +887,9 @@ def load_to_browser(): global from_ver, from_installed _ = None if from_ver: - (lm,lv,lh,pp,np,p,st,si,dm,ip,sf,fl) = _api.update_model_list(_,_,_,_,_,_,_,_,_,_,True) + (lm,lv,lh,pp,np,p,st,si,dm,_dm,ip,sf,fl,ph,tt,bm,mf) = _api.update_model_list(_,_,_,_,_,_,_,_,_,_,True) if from_installed: - (lm,lv,lh,pp,np,p,st,si,dm,ip,sf,fl) = _api.update_model_list(_,_,_,_,_,_,_,_,_,_,False,True) + (lm,lv,lh,pp,np,p,st,si,dm,_dm,ip,sf,fl,ph,tt,bm,mf) = _api.update_model_list(_,_,_,_,_,_,_,_,_,_,False,True) gl.file_scan = True from_ver, from_installed = False, False @@ -858,7 +900,7 @@ def load_to_browser(): gr.Button.update(interactive=True, visible=True), gr.Button.update(interactive=False, visible=False), gr.Button.update(interactive=False, visible=False), - lm,lv,lh,pp,np,p,st,si,dm,ip,sf,fl, + lm,lv,lh,pp,np,p,st,si,dm,_dm,ip,sf,fl,ph,tt,bm,mf, gr.HTML.update(value='
') ) diff --git a/scripts/civitai_gui.py b/scripts/civitai_gui.py index ff11cce..151bdfe 100644 --- a/scripts/civitai_gui.py +++ b/scripts/civitai_gui.py @@ -1,5 +1,5 @@ import gradio as gr -from modules import script_callbacks, shared, ui_settings +from modules import script_callbacks, shared import os import json import fnmatch @@ -70,6 +70,7 @@ def on_ui_tabs(): toggle3 = "toggle3L" if lobe_directory else "toggle3" refreshbtn = "refreshBtnL" if lobe_directory else "refreshBtn" filterBox = "filterBoxL" if lobe_directory else "filterBox" + if page_header: header = "headerL" if lobe_directory else "header" else: @@ -178,7 +179,10 @@ def on_ui_tabs(): #Invisible triggers/variables model_id = gr.Textbox(value=None, visible=False) dl_url = gr.Textbox(value=None, visible=False) - event_text = gr.Textbox(elem_id="eventtext1", visible=False) + model_select = gr.Textbox(elem_id="model_select", visible=False) + model_sent = gr.Textbox(elem_id="model_sent", visible=False) + type_sent = gr.Textbox(elem_id="type_sent", visible=False) + click_first_item = gr.Textbox(elem_id="type_sent", visible=False) download_start = gr.Textbox(value=None, visible=False) download_finish = gr.Textbox(value=None, visible=False) tag_start = gr.Textbox(value=None, visible=False) @@ -211,6 +215,11 @@ def on_ui_tabs(): # Javascript Functions # + click_first_item.change( + fn=None, + _js="() => clickFirstFigureInColumn()" + ) + list_models.select( fn=None, inputs=[list_models], @@ -311,11 +320,9 @@ def on_ui_tabs(): (html, tags, base_mdl, DwnButton, DelButton, filelist, filename, id, current_sha256, install_path, sub_folder) = _api.update_model_info(model_name,ret_versions['value']) return gr.Dropdown.update(value=model_name),ret_versions,html,tags,base_mdl,filename,install_path,sub_folder,DwnButton,DelButton,filelist,id,current_sha256,gr.Button.update(interactive=True) - event_text.change( + model_select.change( fn=update_models_dropdown, - inputs=[ - event_text - ], + inputs=[model_select], outputs=[ list_models, list_versions, @@ -333,6 +340,12 @@ def on_ui_tabs(): save_info ] ) + + model_sent.change( + fn=_file.model_from_sent, + inputs=[model_sent, type_sent, click_first_item], + outputs=[list_html, get_prev_page , get_next_page, page_slider, click_first_item] + ) sub_folder.select( fn=select_subfolder, @@ -526,9 +539,14 @@ def on_ui_tabs(): save_info, save_images, download_model, + delete_model, install_path, sub_folder, - file_list + file_list, + preview_html, + trained_tags, + base_model, + model_filename ] page_btn_list = { @@ -732,9 +750,14 @@ def on_ui_tabs(): save_info, save_images, download_model, + delete_model, install_path, sub_folder, file_list, + preview_html, + trained_tags, + base_model, + model_filename, installed_progress ] ) @@ -757,9 +780,14 @@ def on_ui_tabs(): save_info, save_images, download_model, + delete_model, install_path, sub_folder, file_list, + preview_html, + trained_tags, + base_model, + model_filename, version_progress ] ) @@ -767,12 +795,16 @@ def on_ui_tabs(): return (civitai_interface, "Civitai Browser+", "civitai_interface"), def subfolder_list(folder, desc=None): + insert_sub = getattr(opts, "insert_sub", True) + dot_subfolders = getattr(opts, "dot_subfolders", True) if folder == None: return try: model_folder = _api.contenttype_folder(folder, desc) sub_folders = ["None"] for root, dirs, _ in os.walk(model_folder): + if dot_subfolders: + dirs = [d for d in dirs if not d.startswith('.')] for d in dirs: sub_folder = os.path.relpath(os.path.join(root, d), model_folder) if sub_folder: @@ -781,6 +813,9 @@ def subfolder_list(folder, desc=None): sub_folders.remove("None") sub_folders = sorted(sub_folders) sub_folders.insert(0, "None") + if insert_sub: + sub_folders.insert(1, f"{os.sep}Model Name") + sub_folders.insert(2, f"{os.sep}Model Name{os.sep}Version Name") list = set() sub_folders = [x for x in sub_folders if not (x in list or list.add(x))] @@ -805,9 +840,10 @@ def on_ui_settings(): shared.opts.add_option("show_log", shared.OptionInfo(False, "Show Aria2 logs in console", section=section).info("Requires UI reload")) shared.opts.add_option("split_aria2", shared.OptionInfo(64, "Number of connections to use for downloading a model", gr.Slider, lambda: {"maximum": "64", "minimum": "1", "step": "1"}, section=section).info("Only applies to Aria2")) shared.opts.add_option("aria2_flags", shared.OptionInfo(r"", "Custom Aria2 command line flags", section=section).info("Requires UI reload")) - shared.opts.add_option("insert_sub", shared.OptionInfo(True, "Insert [/Model Name] & [/Model Name/Version Name] as default sub folder options", section=section)) + shared.opts.add_option("insert_sub", shared.OptionInfo(True, f"Insert [{os.sep}Model Name] & [{os.sep}Model Name{os.sep}Version Name] as sub folder options", section=section)) + shared.opts.add_option("dot_subfolders", shared.OptionInfo(True, "Hide sub-folders that start with a .", section=section)) shared.opts.add_option("use_LORA", shared.OptionInfo(False, "Treat LoCon's as LORA's", section=section).info("SD-WebUI v1.5 and higher treats LoCON's the same as LORA's, Requires UI reload")) - shared.opts.add_option("unpack_zip", shared.OptionInfo(False, "Automatically unpack .zip after downloading", section=section)) + shared.opts.add_option("unpack_zip", shared.OptionInfo(False, "Automatically unpack .zip files after downloading", section=section)) shared.opts.add_option("hide_early_access", shared.OptionInfo(True, "Hide early access models", section=section).info("Early access models are only downloadable for supporter tier members, Requires API key")) shared.opts.add_option("custom_api_key", shared.OptionInfo(r"", "Personal CivitAI API key", section=section).info("You can create your own API key in your CivitAI account settings, Requires UI reload")) shared.opts.add_option("page_header", shared.OptionInfo(False, "Page navigation as header", section=section).info("Keeps the page navigation always visible at the top, Requires UI reload")) @@ -816,15 +852,6 @@ def on_ui_settings(): use_LORA = getattr(opts, "use_LORA", False) - def has_folders(input, desc=None): - if input == None: - return False - try: - path = any(entry.is_dir() for entry in os.scandir(_api.contenttype_folder(input, desc))) - except: - return False - return path - # Default sub folders folders = [ "Checkpoint", @@ -853,7 +880,7 @@ def on_ui_settings(): desc = None if isinstance(folder, tuple): folder_name = " - ".join(folder) - setting_name = folder[1] + setting_name = f"{folder[1]}_upscale" folder = folder[0] desc = folder[1] else: @@ -863,8 +890,7 @@ def on_ui_settings(): folder = "LORA" setting_name = "LORA_LoCon" - if has_folders(folder, desc): - shared.opts.add_option(f"{setting_name}_subfolder", shared.OptionInfo("None", folder_name, gr.Dropdown, make_lambda(folder, desc), section=section)) + shared.opts.add_option(f"{setting_name}_subfolder", shared.OptionInfo("None", folder_name, gr.Dropdown, make_lambda(folder, desc), section=section)) script_callbacks.on_ui_tabs(on_ui_tabs) script_callbacks.on_ui_settings(on_ui_settings) \ No newline at end of file diff --git a/style.css b/style.css index c96d9e6..7992774 100644 --- a/style.css +++ b/style.css @@ -96,6 +96,10 @@ z-index: 60; } +.acss-14flpmm .gap:has(#quicksettings):first-child { + gap: var(--layout-gap); +} + #browserTab > div > #header, #browserTab > div > #header_off { display: flex; flex-direction: column; @@ -343,6 +347,14 @@ /* End of Custom Accordion */ +.goto-civitbrowser.card-button { + filter: drop-shadow(2px 2px 3px black); +} + +.goto-civitbrowser.card-button:hover svg { + fill: red !important; +} + /* Custom settings Accordion */ #settings-accordion { border: 1px solid var(--block-border-color);