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
+
+
+
+
+
+* 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);