Update to v3.6.0
parent
c3b8e0cfa8
commit
053da94ecb
12
README.md
12
README.md
|
|
@ -100,6 +100,18 @@ https://github.com/BlafKing/sd-civitai-browser-plus/assets/9644716/44c5c7a0-4854
|
|||
|
||||
# Changelog 📋
|
||||
|
||||
<h3>v3.6.0</h3>
|
||||
|
||||
* Feature: Ability to set custom default sub folders.
|
||||
* Feature: Automatically fetches latest available Basemodels.
|
||||
* Bug fix: Lag fixed on SD-WebUI Forge/Gradio 4+, thanks to @BenjaminSymons and @channelcat!
|
||||
* Bug fix: Version ID has been suffixed to filename to avoid detecting different models as installed.
|
||||
* Bug fix: Filename comparing to detect installed models is no longer case sensitive.
|
||||
* Bug fix: CivitAI button on model cards correctly works again.
|
||||
* Bug fix: Correct image path now gets used when local images in HTML are used.
|
||||
* Bug fix: Any trailing or leading spaces get removed from model/version names now.
|
||||
|
||||
---
|
||||
<h3>v3.5.4</h3>
|
||||
|
||||
* Feature: Added support for DoRA (Requires SD-WebUI v1.9)
|
||||
|
|
|
|||
|
|
@ -367,7 +367,7 @@ function updateBackToTopVisibility(entries) {
|
|||
|
||||
// Create the accordion dropdown inside the settings tab
|
||||
function createAccordion(containerDiv, subfolders, name, id_name) {
|
||||
if (containerDiv == null || subfolders.length == 0) {
|
||||
if (containerDiv == null) {
|
||||
return;
|
||||
}
|
||||
var accordionContainer = document.createElement('div');
|
||||
|
|
@ -384,8 +384,11 @@ function createAccordion(containerDiv, subfolders, name, id_name) {
|
|||
accordionContainer.appendChild(toggleButton);
|
||||
var accordionDiv = document.createElement('div');
|
||||
accordionDiv.classList.add('accordion');
|
||||
if (subfolders && subfolders.length > 0) {
|
||||
accordionDiv.append(...subfolders);
|
||||
accordionDiv.style.display = 'none';
|
||||
}
|
||||
|
||||
accordionDiv.style.display = 'none'; // Initially hidden
|
||||
accordionContainer.appendChild(accordionDiv);
|
||||
containerDiv.appendChild(accordionContainer);
|
||||
}
|
||||
|
|
@ -486,14 +489,15 @@ function addOnClickToButtons() {
|
|||
});
|
||||
}
|
||||
|
||||
function modelInfoPopUp(modelName, content_type) {
|
||||
function modelInfoPopUp(modelName=null, content_type=null, no_message=false) {
|
||||
const sendToBrowserElement = gradioApp().querySelector('#setting_civitai_send_to_browser input');
|
||||
let sendToBrowser = false;
|
||||
if (sendToBrowserElement) {
|
||||
sendToBrowser = sendToBrowserElement.checked;
|
||||
}
|
||||
|
||||
if (modelName) {
|
||||
select_model(modelName, null, true, content_type, sendToBrowser);
|
||||
}
|
||||
if (sendToBrowser) {
|
||||
const tabNav = document.querySelector('.tab-nav');
|
||||
const buttons = tabNav.querySelectorAll('button');
|
||||
|
|
@ -559,18 +563,23 @@ function modelInfoPopUp(modelName, content_type) {
|
|||
});
|
||||
inner.classList.add('civitai-overlay-inner');
|
||||
|
||||
const modelInfo = createElementWithStyle('div', {
|
||||
var modelInfo;
|
||||
if (!no_message) {
|
||||
modelInfo = createElementWithStyle('div', {
|
||||
fontSize: '24px',
|
||||
color: 'white',
|
||||
fontFamily: 'var(--font)'
|
||||
});
|
||||
modelInfo.classList.add('civitai-overlay-text');
|
||||
modelInfo.textContent = 'Loading model info, please wait!';
|
||||
}
|
||||
|
||||
document.body.style.overflow = 'hidden';
|
||||
document.body.appendChild(overlay);
|
||||
overlay.append(closeButton, inner);
|
||||
if (!no_message) {
|
||||
inner.appendChild(modelInfo);
|
||||
}
|
||||
|
||||
setDynamicWidth(inner);
|
||||
window.addEventListener('resize', () => setDynamicWidth(inner));
|
||||
|
|
@ -601,11 +610,15 @@ function handleKeyPress(event) {
|
|||
}
|
||||
|
||||
function inputHTMLPreviewContent(html_input) {
|
||||
//console.log("Last 500 characters of HTML input:", html_input.slice(-500));
|
||||
var inner = document.querySelector('.civitai-overlay-inner')
|
||||
let startIndex = html_input.indexOf("'value': '");
|
||||
if (startIndex !== -1) {
|
||||
startIndex += "'value': '".length;
|
||||
const endIndex = html_input.indexOf("', 'type': None,", startIndex);
|
||||
let endIndex = html_input.indexOf(", 'placeholder'", startIndex);
|
||||
if (endIndex === -1) {
|
||||
endIndex = html_input.indexOf("', 'type': None,", startIndex);
|
||||
}
|
||||
if (endIndex !== -1) {
|
||||
let extractedText = html_input.substring(startIndex, endIndex);
|
||||
var modelIdNotFound = extractedText.includes(">Model ID not found.<br>The");
|
||||
|
|
@ -626,6 +639,9 @@ function inputHTMLPreviewContent(html_input) {
|
|||
modelInfo.innerHTML = extractedText;
|
||||
inner.appendChild(modelInfo);
|
||||
|
||||
inner.style.top = 'unset';
|
||||
inner.style.transform = 'translate(-50%, 0%)'
|
||||
|
||||
setDescriptionToggle();
|
||||
}
|
||||
}
|
||||
|
|
@ -963,6 +979,188 @@ function setDescriptionToggle() {
|
|||
}
|
||||
}
|
||||
|
||||
function submitNewSubfolder(subfolderId, subfolderValue) {
|
||||
const output = gradioApp().querySelector('#create_subfolder textarea');
|
||||
output.value = subfolderId + ".add." + subfolderValue;
|
||||
updateInput(output)
|
||||
}
|
||||
|
||||
function deleteSubfolder(subfolderId) {
|
||||
const output = gradioApp().querySelector('#create_subfolder textarea');
|
||||
output.value = subfolderId + ".delete.";
|
||||
updateInput(output)
|
||||
}
|
||||
|
||||
function createCustomSubfolder(subfolderDiv, subfolderId, subfolderValue) {
|
||||
if (typeof subfolderId === 'undefined') {
|
||||
console.error('subfolderId is required.');
|
||||
return;
|
||||
}
|
||||
|
||||
const newContainerDiv = document.createElement("div");
|
||||
newContainerDiv.classList.add("svelte-1f354aw", "container", "CivitDefaultSubfolder");
|
||||
newContainerDiv.style.display = "flex";
|
||||
newContainerDiv.style.alignItems = "center";
|
||||
|
||||
newContainerDiv.setAttribute("subfolder_id", subfolderId);
|
||||
|
||||
const newTextArea = document.createElement("textarea");
|
||||
newTextArea.setAttribute("data-testid", "textbox");
|
||||
newTextArea.classList.add("scroll-hide", "svelte-1f354aw");
|
||||
newTextArea.setAttribute("dir", "ltr");
|
||||
newTextArea.setAttribute("placeholder", "{BASEMODEL}/{NSFW}/{AUTHOR}/{MODELNAME}/{MODELID}/{VERSIONNAME}/{VERSIONID}");
|
||||
newTextArea.setAttribute("rows", "1");
|
||||
newTextArea.style.overflowY = "scroll";
|
||||
newTextArea.style.height = "42px";
|
||||
newTextArea.style.flex = "1";
|
||||
|
||||
if (typeof subfolderValue !== 'undefined') {
|
||||
newTextArea.value = subfolderValue;
|
||||
}
|
||||
|
||||
newTextArea.addEventListener("keydown", function(event) {
|
||||
if (event.key === "Enter") {
|
||||
event.preventDefault();
|
||||
submitNewSubfolder(subfolderId, newTextArea.value);
|
||||
}
|
||||
});
|
||||
|
||||
const saveButton = document.createElement("button");
|
||||
saveButton.textContent = "Save";
|
||||
saveButton.classList.add("save-button", "lg", "primary", "gradio-button", "svelte-cmf5ev");
|
||||
saveButton.setAttribute("title", "")
|
||||
saveButton.style.marginRight = "10px";
|
||||
saveButton.addEventListener("click", function() {
|
||||
submitNewSubfolder(subfolderId, newTextArea.value);
|
||||
});
|
||||
|
||||
const deleteButton = document.createElement("button");
|
||||
deleteButton.textContent = "Delete";
|
||||
deleteButton.classList.add("delete-button", "lg", "primary", "gradio-button", "svelte-cmf5ev");
|
||||
deleteButton.style.marginRight = "10px";
|
||||
deleteButton.addEventListener("click", function() {
|
||||
deleteSubfolder(subfolderId);
|
||||
newContainerDiv.remove();
|
||||
});
|
||||
|
||||
newContainerDiv.appendChild(deleteButton);
|
||||
newContainerDiv.appendChild(saveButton);
|
||||
newContainerDiv.appendChild(newTextArea);
|
||||
|
||||
subfolderDiv.appendChild(newContainerDiv);
|
||||
}
|
||||
|
||||
function insertExistingSubfolders(input) {
|
||||
const subfolder = document.querySelectorAll("civitai-custom-subfolder-div");
|
||||
createCustomSubfolder(subfolder, Id, Value);
|
||||
}
|
||||
|
||||
function createSubfolderButton() {
|
||||
const subfolderParent = document.getElementById("create-sub-accordion");
|
||||
const subfolderDiv = subfolderParent.querySelector(".accordion");
|
||||
|
||||
const subfolder = document.createElement("div");
|
||||
subfolder.classList.add("flex-column-layout", "civitai-custom-subfolder-div");
|
||||
|
||||
const customSubfoldersList = document.querySelector('#custom_subfolders_list');
|
||||
const textarea = customSubfoldersList.querySelector('textarea');
|
||||
const subfoldersString = textarea ? textarea.value : '';
|
||||
|
||||
const subfoldersArray = subfoldersString.split('␞␞');
|
||||
|
||||
for (let i = 0; i < subfoldersArray.length; i += 2) {
|
||||
const subfolderId = subfoldersArray[i];
|
||||
const subfolderValue = subfoldersArray[i + 1];
|
||||
|
||||
createCustomSubfolder(subfolder, subfolderId, subfolderValue);
|
||||
}
|
||||
|
||||
const buttonContainer = document.createElement("div");
|
||||
buttonContainer.classList.add("sub-folder-button-container");
|
||||
buttonContainer.style.display = "flex";
|
||||
buttonContainer.style.gap = "10px";
|
||||
|
||||
const optionsDiv = document.createElement("div");
|
||||
optionsDiv.classList.add("placeholder-options-container");
|
||||
optionsDiv.style.display = "flex";
|
||||
optionsDiv.style.justifyContent = "center";
|
||||
|
||||
const plusButton = document.createElement("button");
|
||||
plusButton.textContent = "Create new default sub folder entry";
|
||||
plusButton.classList.add("plus-button", "lg", "primary", "gradio-button", "svelte-cmf5ev");
|
||||
plusButton.style.marginTop = "10px";
|
||||
plusButton.addEventListener("click", function() {
|
||||
const existingSubfolderDivs = document.querySelectorAll("div.CivitDefaultSubfolder");
|
||||
let highestSubfolderId = 0;
|
||||
|
||||
existingSubfolderDivs.forEach((div) => {
|
||||
const subfolderId = parseInt(div.getAttribute('subfolder_id'), 10);
|
||||
if (subfolderId > highestSubfolderId) {
|
||||
highestSubfolderId = subfolderId;
|
||||
}
|
||||
});
|
||||
|
||||
const newSubfolderId = highestSubfolderId + 1;
|
||||
createCustomSubfolder(subfolder, newSubfolderId);
|
||||
});
|
||||
|
||||
// Create the guide button
|
||||
const guide_html = `
|
||||
<div style="text-align: center;">
|
||||
<div>These options can be used to add sub-folder options.</div>
|
||||
<div>There are a few placeholders you can use which will be automatically replaced with the selected model's information:</div>
|
||||
<div></div>
|
||||
<div>{BASEMODEL}: Replaced with the base model name.</div>
|
||||
<div>{NSFW}: Creates a folder named "nsfw", folder will not be created if model is sfw.</div>
|
||||
<div>{AUTHOR}: Replaced with the author of the model.</div>
|
||||
<div>{MODELNAME}: Replaced with the name of the model.</div>
|
||||
<div>{MODELID}: Replaced with the unique ID of the model.</div>
|
||||
<div>{VERSIONNAME}: Replaced with the version name of the model.</div>
|
||||
<div>{VERSIONID}: Replaced with the unique ID of the model version.</div>
|
||||
<div></div>
|
||||
<div>For example, if I select a model called 'ReV Animated'</div>
|
||||
<div>and it's version is called 'V2 Rebirth' then the following:</div>
|
||||
<div>{MODELNAME}/{VERSIONNAME}</div>
|
||||
<div>Will be replaced with:</div>
|
||||
<div>ReV Animated/V2 Rebirth</div>
|
||||
<div></div>
|
||||
<div>Always use '/' as a seperator, regardless of your OS</div>
|
||||
</div>
|
||||
`;
|
||||
const guideButton = document.createElement("button");
|
||||
guideButton.textContent = "Guide";
|
||||
guideButton.classList.add("guide-button", "lg", "primary", "gradio-button", "svelte-cmf5ev");
|
||||
guideButton.style.marginTop = "10px";
|
||||
guideButton.addEventListener("click", function() {
|
||||
modelInfoPopUp(null, null, true);
|
||||
insertGuideMessage(guide_html);
|
||||
});
|
||||
|
||||
const optionsText = document.createElement("span");
|
||||
optionsText.textContent = "Available options: {BASEMODEL} {NSFW} {AUTHOR} {MODELNAME} {MODELID} {VERSIONNAME} {VERSIONID}";
|
||||
|
||||
// Append buttons to the container
|
||||
buttonContainer.appendChild(guideButton);
|
||||
buttonContainer.appendChild(plusButton);
|
||||
|
||||
optionsDiv.appendChild(optionsText);
|
||||
|
||||
subfolder.insertBefore(optionsDiv, subfolder.firstChild);
|
||||
subfolder.insertBefore(buttonContainer, subfolder.firstChild);
|
||||
subfolderDiv.appendChild(subfolder);
|
||||
}
|
||||
|
||||
function insertGuideMessage(html_input) {
|
||||
const overlayContainer = document.querySelector(".civitai-overlay-inner");
|
||||
if (overlayContainer) {
|
||||
const guideHtml = document.createElement('div');
|
||||
guideHtml.innerHTML = html_input;
|
||||
while (guideHtml.firstChild) {
|
||||
overlayContainer.appendChild(guideHtml.firstChild);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Runs all functions when the page is fully loaded
|
||||
function onPageLoad() {
|
||||
updateSVGIcons();
|
||||
|
|
@ -975,9 +1173,8 @@ function onPageLoad() {
|
|||
let div = subfolderDiv || downloadDiv;
|
||||
let subfolders = div.querySelectorAll("[id$='subfolder']");
|
||||
createAccordion(div, subfolders, "Default sub folders", 'default-sub-accordion');
|
||||
|
||||
subfolders = div.querySelectorAll("[id^='setting_insert_sub']");
|
||||
createAccordion(div, subfolders, "Insert sub folder options", 'insert-sub-accordion');
|
||||
createAccordion(div, null, "Create sub folder entries", 'create-sub-accordion');
|
||||
createSubfolderButton();
|
||||
}
|
||||
|
||||
if (subfolderDiv || settingsDiv) {
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ from html import escape
|
|||
from scripts.civitai_global import print, debug_print
|
||||
import scripts.civitai_global as gl
|
||||
import scripts.civitai_download as _download
|
||||
import scripts.civitai_file_manage as _file
|
||||
|
||||
gl.init()
|
||||
|
||||
|
|
@ -188,7 +189,7 @@ def model_list_html(json_data):
|
|||
for folder in model_folders:
|
||||
for root, dirs, files in os.walk(folder, followlinks=True):
|
||||
for file in files:
|
||||
existing_files.add(file)
|
||||
existing_files.add(file.lower())
|
||||
if file.endswith('.json'):
|
||||
json_path = os.path.join(root, file)
|
||||
with open(json_path, 'r', encoding="utf-8") as f:
|
||||
|
|
@ -244,10 +245,13 @@ def model_list_html(json_data):
|
|||
|
||||
for version in reversed(item['modelVersions']):
|
||||
for file in version.get('files', []):
|
||||
file_name = file['name']
|
||||
file_name = os.path.splitext(file['name'])[0]
|
||||
file_extension = os.path.splitext(file['name'])[1]
|
||||
file_name = f"{file_name}_{file['id']}{file_extension}"
|
||||
file_sha256 = file.get('hashes', {}).get('SHA256', "").upper()
|
||||
|
||||
name_match = file_name in existing_files
|
||||
#filename_check
|
||||
name_match = file_name.lower() in existing_files
|
||||
sha256_match = file_sha256 in existing_files_sha256
|
||||
if name_match or sha256_match:
|
||||
if version == item['modelVersions'][0]:
|
||||
|
|
@ -500,7 +504,9 @@ def update_model_versions(model_id, json_input=None):
|
|||
versions_dict[version['name']].append(item["name"])
|
||||
for version_file in version['files']:
|
||||
file_sha256 = version_file.get('hashes', {}).get('SHA256', "").upper()
|
||||
version_filename = version_file['name']
|
||||
version_filename = os.path.splitext(version_file['name'])[0]
|
||||
version_extension = os.path.splitext(version_file['name'])[1]
|
||||
version_filename = f"{version_filename}_{version_file['id']}{version_extension}"
|
||||
version_files.add((version['name'], version_filename, file_sha256))
|
||||
|
||||
for root, _, files in os.walk(model_folder, followlinks=True):
|
||||
|
|
@ -520,8 +526,9 @@ def update_model_versions(model_id, json_input=None):
|
|||
except Exception as e:
|
||||
print(f"failed to read: \"{file}\": {e}")
|
||||
|
||||
#filename_check
|
||||
for version_name, version_filename, _ in version_files:
|
||||
if file == version_filename:
|
||||
if file.lower() == version_filename.lower():
|
||||
installed_versions.add(version_name)
|
||||
break
|
||||
|
||||
|
|
@ -542,6 +549,7 @@ def cleaned_name(file_name):
|
|||
|
||||
name, extension = os.path.splitext(file_name)
|
||||
clean_name = re.sub(illegal_chars_pattern, '', name)
|
||||
clean_name = re.sub(r'\s+', ' ', clean_name.strip())
|
||||
|
||||
return f"{clean_name}{extension}"
|
||||
|
||||
|
|
@ -616,6 +624,7 @@ def update_model_info(model_string=None, model_version=None, only_html=False, in
|
|||
model_folder = os.path.join(contenttype_folder(content_type, desc))
|
||||
model_uploader = None
|
||||
uploader_avatar = None
|
||||
nsfw = item['nsfw']
|
||||
creator = item.get('creator', None)
|
||||
if creator:
|
||||
model_uploader = creator.get('username', None)
|
||||
|
|
@ -639,6 +648,8 @@ def update_model_info(model_string=None, model_version=None, only_html=False, in
|
|||
|
||||
model_availability = selected_version.get('availability', 'Unknown')
|
||||
model_date_published = selected_version.get('publishedAt', '').split('T')[0]
|
||||
version_name = selected_version['name']
|
||||
version_id = selected_version['id']
|
||||
|
||||
if selected_version['trainedWords']:
|
||||
output_training = ",".join(selected_version['trainedWords'])
|
||||
|
|
@ -651,7 +662,9 @@ def update_model_info(model_string=None, model_version=None, only_html=False, in
|
|||
dl_dict[file['name']] = file['downloadUrl']
|
||||
|
||||
if not model_filename:
|
||||
model_filename = file['name']
|
||||
model_filename = os.path.splitext(file['name'])[0]
|
||||
model_extension = os.path.splitext(file['name'])[1]
|
||||
model_filename = f"{model_filename}_{file['id']}{model_extension}"
|
||||
dl_url = file['downloadUrl']
|
||||
gl.json_info = item
|
||||
sha256_value = file['hashes'].get('SHA256', 'Unknown')
|
||||
|
|
@ -671,7 +684,9 @@ def update_model_info(model_string=None, model_version=None, only_html=False, in
|
|||
})
|
||||
if is_primary:
|
||||
default_file = unique_file_name
|
||||
model_filename = file['name']
|
||||
model_filename = os.path.splitext(file['name'])[0]
|
||||
model_extension = os.path.splitext(file['name'])[1]
|
||||
model_filename = f"{model_filename}_{file['id']}{model_extension}"
|
||||
dl_url = file['downloadUrl']
|
||||
gl.json_info = item
|
||||
sha256_value = file['hashes'].get('SHA256', 'Unknown')
|
||||
|
|
@ -855,7 +870,7 @@ def update_model_info(model_string=None, model_version=None, only_html=False, in
|
|||
|
||||
folder_location = "None"
|
||||
default_subfolder = "None"
|
||||
sub_folders = ["None"]
|
||||
sub_folders = _file.getSubfolders(model_folder, output_basemodel, nsfw, model_uploader, model_name, model_id, version_name, version_id)
|
||||
|
||||
for root, dirs, files in os.walk(model_folder, followlinks=True):
|
||||
for filename in files:
|
||||
|
|
@ -876,8 +891,9 @@ def update_model_info(model_string=None, model_version=None, only_html=False, in
|
|||
except Exception as e:
|
||||
print(f"Error decoding JSON: {str(e)}")
|
||||
else:
|
||||
#filename_check
|
||||
for filename in files:
|
||||
if filename == model_filename or filename == cleaned_name(model_filename):
|
||||
if filename.lower() == model_filename.lower() or filename.lower() == cleaned_name(model_filename).lower():
|
||||
folder_location = root
|
||||
BtnDownInt = False
|
||||
BtnDel = True
|
||||
|
|
@ -886,99 +902,20 @@ def update_model_info(model_string=None, model_version=None, only_html=False, in
|
|||
if folder_location != "None":
|
||||
break
|
||||
|
||||
insert_sub_1 = getattr(opts, "insert_sub_1", False)
|
||||
insert_sub_2 = getattr(opts, "insert_sub_2", False)
|
||||
insert_sub_3 = getattr(opts, "insert_sub_3", False)
|
||||
insert_sub_4 = getattr(opts, "insert_sub_4", False)
|
||||
insert_sub_5 = getattr(opts, "insert_sub_5", False)
|
||||
insert_sub_6 = getattr(opts, "insert_sub_6", False)
|
||||
insert_sub_7 = getattr(opts, "insert_sub_7", False)
|
||||
insert_sub_8 = getattr(opts, "insert_sub_8", False)
|
||||
insert_sub_9 = getattr(opts, "insert_sub_9", False)
|
||||
insert_sub_10 = getattr(opts, "insert_sub_10", False)
|
||||
insert_sub_11 = getattr(opts, "insert_sub_11", False)
|
||||
insert_sub_12 = getattr(opts, "insert_sub_12", False)
|
||||
insert_sub_13 = getattr(opts, "insert_sub_13", False)
|
||||
insert_sub_14 = getattr(opts, "insert_sub_14", False)
|
||||
dot_subfolders = getattr(opts, "dot_subfolders", True)
|
||||
|
||||
try:
|
||||
sub_folders = ["None"]
|
||||
for root, dirs, _ in os.walk(model_folder, followlinks=True):
|
||||
if dot_subfolders:
|
||||
dirs = [d for d in dirs if not d.startswith('.')]
|
||||
dirs = [d for d in dirs if not any(part.startswith('.') for part in os.path.join(root, d).split(os.sep))]
|
||||
for d in dirs:
|
||||
sub_folder = os.path.relpath(os.path.join(root, d), model_folder)
|
||||
if sub_folder:
|
||||
sub_folders.append(f'{os.sep}{sub_folder}')
|
||||
|
||||
sub_folders.remove("None")
|
||||
sub_folders = sorted(sub_folders, key=lambda x: (x.lower(), x))
|
||||
sub_folders.insert(0, "None")
|
||||
base = cleaned_name(output_basemodel)
|
||||
author = cleaned_name(model_uploader)
|
||||
name = cleaned_name(model_name)
|
||||
ver = cleaned_name(model_version)
|
||||
|
||||
if insert_sub_1:
|
||||
sub_folders.insert(1, os.path.join(os.sep, base))
|
||||
if insert_sub_2:
|
||||
sub_folders.insert(2, os.path.join(os.sep, base, author))
|
||||
if insert_sub_3:
|
||||
sub_folders.insert(3, os.path.join(os.sep, base, author, name))
|
||||
if insert_sub_4:
|
||||
sub_folders.insert(4, os.path.join(os.sep, base, author, name, ver))
|
||||
if insert_sub_5:
|
||||
sub_folders.insert(5, os.path.join(os.sep, base, name))
|
||||
if insert_sub_6:
|
||||
sub_folders.insert(6, os.path.join(os.sep, base, name, ver))
|
||||
if insert_sub_7:
|
||||
sub_folders.insert(7, os.path.join(os.sep, author))
|
||||
if insert_sub_8:
|
||||
sub_folders.insert(8, os.path.join(os.sep, author, base))
|
||||
if insert_sub_9:
|
||||
sub_folders.insert(9, os.path.join(os.sep, author, base, name))
|
||||
if insert_sub_10:
|
||||
sub_folders.insert(10, os.path.join(os.sep, author, base, name, ver))
|
||||
if insert_sub_11:
|
||||
sub_folders.insert(11, os.path.join(os.sep, author, name))
|
||||
if insert_sub_12:
|
||||
sub_folders.insert(12, os.path.join(os.sep, author, name, ver))
|
||||
if insert_sub_13:
|
||||
sub_folders.insert(13, os.path.join(os.sep, name))
|
||||
if insert_sub_14:
|
||||
sub_folders.insert(14, os.path.join(os.sep, name, ver))
|
||||
|
||||
list = set()
|
||||
sub_folders = [x for x in sub_folders if not (x in list or list.add(x))]
|
||||
except Exception as e:
|
||||
print(e)
|
||||
sub_folders = ["None"]
|
||||
|
||||
default_sub = sub_folder_value(content_type, desc)
|
||||
|
||||
variable_mapping = {
|
||||
"Base model": base,
|
||||
"Author name": author,
|
||||
"Model name": name,
|
||||
"Model version": ver
|
||||
}
|
||||
|
||||
if any(key in default_sub for key in variable_mapping.keys()):
|
||||
path_components = [variable_mapping.get(component.strip(os.sep), component.strip(os.sep)) for component in default_sub.split(os.sep)]
|
||||
default_sub = os.path.join(os.sep, *path_components)
|
||||
|
||||
default_subfolder = sub_folder_value(content_type, desc)
|
||||
if default_subfolder != "None":
|
||||
default_subfolder = _file.convertCustomFolder(default_subfolder, output_basemodel, nsfw, model_uploader, model_name, model_id, version_name, version_id)
|
||||
if folder_location == "None":
|
||||
folder_location = model_folder
|
||||
if default_sub != "None":
|
||||
folder_path = folder_location + default_sub
|
||||
if default_subfolder != "None":
|
||||
folder_path = folder_location + default_subfolder
|
||||
else:
|
||||
folder_path = folder_location
|
||||
else:
|
||||
folder_path = folder_location
|
||||
|
||||
relative_path = os.path.relpath(folder_location, model_folder)
|
||||
default_subfolder = f'{os.sep}{relative_path}' if relative_path != "." else default_sub if BtnDel == False else "None"
|
||||
default_subfolder = f'{os.sep}{relative_path}' if relative_path != "." else default_subfolder if BtnDel == False else "None"
|
||||
if gl.isDownloading:
|
||||
item = gl.download_queue[0]
|
||||
if int(model_id) == int(item['model_id']):
|
||||
|
|
@ -1026,14 +963,14 @@ def update_model_info(model_string=None, model_version=None, only_html=False, in
|
|||
def sub_folder_value(content_type, desc=None):
|
||||
use_LORA = getattr(opts, "use_LORA", False)
|
||||
if content_type in ["LORA", "LoCon"] and use_LORA:
|
||||
folder = getattr(opts, "LORA_LoCon_subfolder", "None")
|
||||
folder = getattr(opts, "LORA_LoCon_default_subfolder", "None")
|
||||
elif content_type == "Upscaler":
|
||||
for upscale_type in ["SWINIR", "REALESRGAN", "GFPGAN", "BSRGAN"]:
|
||||
if upscale_type in desc:
|
||||
folder = getattr(opts, f"{upscale_type}_subfolder", "None")
|
||||
folder = getattr(opts, "ESRGAN_subfolder", "None")
|
||||
folder = getattr(opts, f"{upscale_type}_default_subfolder", "None")
|
||||
folder = getattr(opts, "ESRGAN_default_subfolder", "None")
|
||||
else:
|
||||
folder = getattr(opts, f"{content_type}_subfolder", "None")
|
||||
folder = getattr(opts, f"{content_type}_default_subfolder", "None")
|
||||
if folder == None:
|
||||
return "None"
|
||||
return folder
|
||||
|
|
@ -1186,11 +1123,15 @@ def get_headers(referer=None, no_api=None):
|
|||
|
||||
return headers
|
||||
|
||||
def request_civit_api(api_url=None):
|
||||
def request_civit_api(api_url=None, skip_error_check=False):
|
||||
headers = get_headers()
|
||||
proxies, ssl = get_proxies()
|
||||
try:
|
||||
response = requests.get(api_url, headers=headers, timeout=(60,30), proxies=proxies, verify=ssl)
|
||||
if skip_error_check:
|
||||
response.encoding = "utf-8"
|
||||
data = json.loads(response.text)
|
||||
return data
|
||||
response.raise_for_status()
|
||||
except requests.exceptions.Timeout as e:
|
||||
print("The request timed out. Please try again later.")
|
||||
|
|
|
|||
|
|
@ -181,14 +181,9 @@ def selected_to_queue(model_list, subfolder, download_start, create_json, curren
|
|||
|
||||
model_folder = _api.contenttype_folder(content_type, desc)
|
||||
|
||||
sub_opt1 = os.path.join(os.sep, _api.cleaned_name(model_name))
|
||||
sub_opt2 = os.path.join(os.sep, _api.cleaned_name(model_name), _api.cleaned_name(version_name))
|
||||
|
||||
default_sub = _api.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
|
||||
default_subfolder = _api.sub_folder_value(content_type, desc)
|
||||
if default_subfolder != "None":
|
||||
default_subfolder = _file.convertCustomFolder(default_subfolder, output_basemodel, nsfw, model_uploader, model_name, model_id, version_name, version_id)
|
||||
|
||||
if subfolder and subfolder != "None" and subfolder != "Only available if the selected files are of the same model type":
|
||||
from_batch = False
|
||||
|
|
@ -200,8 +195,8 @@ def selected_to_queue(model_list, subfolder, download_start, create_json, curren
|
|||
install_path = model_folder + subfolder
|
||||
else:
|
||||
from_batch = True
|
||||
if default_sub != "None":
|
||||
install_path = model_folder + default_sub
|
||||
if default_subfolder != "None":
|
||||
install_path = model_folder + default_subfolder
|
||||
else:
|
||||
install_path = model_folder
|
||||
|
||||
|
|
|
|||
|
|
@ -363,7 +363,6 @@ def convert_local_images(html):
|
|||
return str(soup)
|
||||
|
||||
def model_from_sent(model_name, content_type):
|
||||
|
||||
modelID_failed = False
|
||||
output_html = None
|
||||
model_file = None
|
||||
|
|
@ -459,6 +458,8 @@ def model_from_sent(model_name, content_type):
|
|||
output_html = output_html.replace('zoom-overlay', 'zoom-preview-overlay')
|
||||
output_html = output_html.replace('resetZoom', 'resetPreviewZoom')
|
||||
|
||||
debug_print(output_html)
|
||||
|
||||
number = _download.random_number()
|
||||
|
||||
return (
|
||||
|
|
@ -511,13 +512,99 @@ def send_to_browser(model_name, content_type, click_first_item):
|
|||
number = _download.random_number(click_first_item)
|
||||
|
||||
return (
|
||||
gr.Textbox.update(output_html), # Card HTML
|
||||
gr.Textbox.update(value=output_html), # Card HTML
|
||||
gr.Button.update(interactive=False), # Prev Button
|
||||
gr.Button.update(interactive=False), # Next Button
|
||||
gr.Slider.update(value=1, maximum=1), # Page Slider
|
||||
gr.Textbox.update(number) # Click first card trigger
|
||||
gr.Textbox.update(value=number) # Click first card trigger
|
||||
)
|
||||
|
||||
def convertCustomFolder(folderValue, basemodel, nsfw, author, modelName, modelId, versionName, versionId):
|
||||
replacements = {
|
||||
"BASEMODEL": _api.cleaned_name(str(basemodel)),
|
||||
"AUTHOR": _api.cleaned_name(str(author)),
|
||||
"MODELNAME": _api.cleaned_name(str(modelName)),
|
||||
"MODELID": _api.cleaned_name(str(modelId)),
|
||||
"VERSIONNAME": _api.cleaned_name(str(versionName)),
|
||||
"VERSIONID": _api.cleaned_name(str(versionId))
|
||||
}
|
||||
|
||||
if not nsfw:
|
||||
segments = folderValue.split(os.sep)
|
||||
segments = [seg for seg in segments if "{NSFW}" not in seg]
|
||||
folderValue = os.sep.join(segments)
|
||||
else:
|
||||
replacements["NSFW"] = "nsfw"
|
||||
|
||||
formatted_value = folderValue.format(**replacements)
|
||||
|
||||
converted_folder = formatted_value.replace('/', os.sep).replace('\\', os.sep)
|
||||
converted_folder = os.sep.join(part for part in converted_folder.split(os.sep) if part)
|
||||
|
||||
if not converted_folder.startswith(os.sep):
|
||||
converted_folder = os.sep + converted_folder
|
||||
|
||||
return converted_folder
|
||||
|
||||
def getSubfolders(model_folder, basemodel=None, nsfw=None, author=None, modelName=None, modelId=None, versionName=None, versionId=None):
|
||||
try:
|
||||
dot_subfolders = getattr(opts, "dot_subfolders", True)
|
||||
sub_folders = ["None"]
|
||||
for root, dirs, _ in os.walk(model_folder, followlinks=True):
|
||||
if dot_subfolders:
|
||||
dirs = [d for d in dirs if not d.startswith('.')]
|
||||
dirs = [d for d in dirs if not any(part.startswith('.') for part in os.path.join(root, d).split(os.sep))]
|
||||
for d in dirs:
|
||||
sub_folder = os.path.relpath(os.path.join(root, d), model_folder)
|
||||
if sub_folder:
|
||||
if not sub_folder.startswith(os.sep):
|
||||
sub_folder = os.sep + sub_folder
|
||||
sub_folders.append(sub_folder)
|
||||
|
||||
with open(gl.subfolder_json, 'r') as json_file:
|
||||
config_data = json.load(json_file)
|
||||
|
||||
for key, value in config_data.items():
|
||||
if basemodel:
|
||||
try:
|
||||
converted_value = convertCustomFolder(value, basemodel, nsfw, author, modelName, modelId, versionName, versionId)
|
||||
sub_folders.append(converted_value)
|
||||
except Exception as e:
|
||||
print(f"Error: Failed to process custom subfolder: {e}")
|
||||
else:
|
||||
upper_value = value.upper()
|
||||
if not upper_value.startswith(os.sep):
|
||||
upper_value = os.sep + upper_value
|
||||
sub_folders.append(upper_value)
|
||||
|
||||
sub_folders.remove("None")
|
||||
sub_folders = sorted(sub_folders, key=lambda x: (x.lower(), x))
|
||||
sub_folders.insert(0, "None")
|
||||
|
||||
except Exception as e:
|
||||
print(e)
|
||||
sub_folders = ["None"]
|
||||
|
||||
list = set()
|
||||
sub_folders = [x for x in sub_folders if not (x in list or list.add(x))]
|
||||
|
||||
return sub_folders
|
||||
|
||||
def updateSubfolder(subfolderInput):
|
||||
with open(gl.subfolder_json, 'r') as f:
|
||||
data = json.load(f)
|
||||
|
||||
index, action, value = subfolderInput.split('.', 2)
|
||||
index = str(index)
|
||||
|
||||
if action == "delete":
|
||||
data.pop(index, None)
|
||||
elif action == "add":
|
||||
data[index] = value
|
||||
|
||||
with open(gl.subfolder_json, 'w') as f:
|
||||
json.dump(data, f, indent=4)
|
||||
|
||||
def is_image_url(url):
|
||||
image_extensions = ['.jpg', '.jpeg', '.png', '.gif', '.bmp']
|
||||
parsed = urlparse(url)
|
||||
|
|
@ -558,6 +645,7 @@ def make_dir(path):
|
|||
|
||||
def save_model_info(install_path, file_name, sub_folder, sha256=None, preview_html=None, overwrite_toggle=False, api_response=None):
|
||||
save_path, filename = get_save_path_and_name(install_path, file_name, api_response, sub_folder)
|
||||
image_path = get_image_path(install_path, api_response, sub_folder)
|
||||
json_file = os.path.join(install_path, f'{filename}.json')
|
||||
make_dir(install_path)
|
||||
|
||||
|
|
@ -576,7 +664,7 @@ def save_model_info(install_path, file_name, sub_folder, sha256=None, preview_ht
|
|||
img_urls = re.findall(r'data-sampleimg="true" src=[\'"]?([^\'" >]+)', preview_html)
|
||||
for i, img_url in enumerate(img_urls):
|
||||
img_name = f'{filename}_{i}.jpg'
|
||||
preview_html = preview_html.replace(img_url,f'{os.path.join(save_path, img_name)}')
|
||||
preview_html = preview_html.replace(img_url,f'{os.path.join(image_path, img_name)}')
|
||||
|
||||
match = re.search(r'(\s*)<div class="model-block">', preview_html)
|
||||
if match:
|
||||
|
|
|
|||
|
|
@ -1,11 +1,15 @@
|
|||
from modules.shared import opts
|
||||
do_debug_print = getattr(opts, "civitai_debug_prints", False)
|
||||
def init():
|
||||
import warnings
|
||||
import warnings, os, json
|
||||
from urllib3.exceptions import InsecureRequestWarning
|
||||
warnings.simplefilter('ignore', InsecureRequestWarning)
|
||||
|
||||
global download_queue, last_version, cancel_status, recent_model, last_url, json_data, json_info, main_folder, previous_inputs, download_fail, sortNewest, isDownloading, old_download, scan_files, from_update_tab, url_list, print
|
||||
config_folder = os.path.join(os.getcwd(), "config_states")
|
||||
if not os.path.exists(config_folder):
|
||||
os.mkdir(config_folder)
|
||||
|
||||
global download_queue, last_version, cancel_status, recent_model, last_url, json_data, json_info, main_folder, previous_inputs, download_fail, sortNewest, isDownloading, old_download, scan_files, from_update_tab, url_list, print, subfolder_json
|
||||
|
||||
cancel_status = None
|
||||
recent_model = None
|
||||
|
|
@ -17,6 +21,11 @@ def init():
|
|||
url_list = {}
|
||||
download_queue = []
|
||||
|
||||
subfolder_json = os.path.join(config_folder, "civitai_subfolders.json")
|
||||
if not os.path.exists(subfolder_json):
|
||||
with open(subfolder_json, 'w') as json_file:
|
||||
json.dump({}, json_file)
|
||||
|
||||
from_update_tab = False
|
||||
scan_files = False
|
||||
download_fail = False
|
||||
|
|
|
|||
|
|
@ -146,6 +146,24 @@ def txt2img_output(image_url):
|
|||
geninfo = nr + geninfo
|
||||
return gr.Textbox.update(value=geninfo)
|
||||
|
||||
def get_base_models():
|
||||
api_url = 'https://civitai.com/api/v1/models?baseModels=GetModels'
|
||||
json_return = _api.request_civit_api(api_url, True)
|
||||
default_options = ["SD 1.4","SD 1.5","SD 1.5 LCM","SD 2.0","SD 2.0 768","SD 2.1","SD 2.1 768",
|
||||
"SD 2.1 Unclip","SDXL 0.9","SDXL 1.0","SDXL 1.0 LCM","SDXL Distilled","SDXL Turbo","SDXL Lightning",
|
||||
"Stable Cascade","Pony","SVD","SVD XT","Playground v2","PixArt a", "Flux.1 S", "Flux.1 D","Other"]
|
||||
|
||||
if not isinstance(json_return, dict):
|
||||
print("Couldn't fetch latest baseModel options, using default.")
|
||||
return default_options
|
||||
|
||||
try:
|
||||
options = json_return['error']['issues'][0]['unionErrors'][0]['issues'][0]['options']
|
||||
return options
|
||||
except (KeyError, IndexError) as e:
|
||||
print(f"Basemodel fetch error extracting options: {e}")
|
||||
return default_options
|
||||
|
||||
def on_ui_tabs():
|
||||
page_header = getattr(opts, "page_header", False)
|
||||
lobe_directory = None
|
||||
|
|
@ -188,7 +206,7 @@ def on_ui_tabs():
|
|||
with gr.Row():
|
||||
content_type = gr.Dropdown(label='Content type:', choices=content_choices, value=None, type="value", multiselect=True, elem_id="centerText")
|
||||
with gr.Row():
|
||||
base_filter = gr.Dropdown(label='Base model:', multiselect=True, choices=["SD 1.4","SD 1.5","SD 1.5 LCM","SD 2.0","SD 2.0 768","SD 2.1","SD 2.1 768","SD 2.1 Unclip","SDXL 0.9","SDXL 1.0","SDXL 1.0 LCM","SDXL Distilled","SDXL Turbo","SDXL Lightning","Stable Cascade","Pony","SVD","SVD XT","Playground v2","PixArt a", "Flux.1 S", "Flux.1 D","Other"], value=None, type="value", elem_id="centerText")
|
||||
base_filter = gr.Dropdown(label='Base model:', multiselect=True, choices=get_base_models(), value=None, type="value", elem_id="centerText")
|
||||
with gr.Row():
|
||||
period_type = gr.Dropdown(label='Time period:', choices=["All Time", "Year", "Month", "Week", "Day"], value="All Time", type="value", elem_id="centerText")
|
||||
sort_type = gr.Dropdown(label='Sort by:', choices=["Newest","Oldest","Most Downloaded","Highest Rated","Most Liked","Most Buzz","Most Discussed","Most Collected","Most Images"], value="Most Downloaded", type="value", elem_id="centerText")
|
||||
|
|
@ -301,9 +319,17 @@ def on_ui_tabs():
|
|||
</div>
|
||||
''')
|
||||
|
||||
#Invisible triggers/variables
|
||||
#Yes, there is probably a much better way of passing variables/triggering functions
|
||||
def format_custom_subfolders():
|
||||
separator = '␞␞'
|
||||
with open(gl.subfolder_json, 'r') as f:
|
||||
data = json.load(f)
|
||||
result = separator.join([f"{key}{separator}{value}" for key, value in data.items()])
|
||||
return result
|
||||
|
||||
#Invisible triggers/variables
|
||||
#Yes, there is probably a much better way of passing variables/triggering functions between javascript and python
|
||||
|
||||
gr.Textbox(elem_id="custom_subfolders_list", visible=False, value=format_custom_subfolders())
|
||||
model_id = gr.Textbox(visible=False)
|
||||
queue_trigger = gr.Textbox(visible=False)
|
||||
dl_url = gr.Textbox(visible=False)
|
||||
|
|
@ -316,6 +342,7 @@ def on_ui_tabs():
|
|||
queue_html_input = gr.Textbox(elem_id="queue_html_input", visible=False)
|
||||
list_html_input = gr.Textbox(elem_id="list_html_input", visible=False)
|
||||
preview_html_input = gr.Textbox(elem_id="preview_html_input", visible=False)
|
||||
create_subfolder = gr.Textbox(elem_id="create_subfolder", visible=False)
|
||||
send_to_browser = gr.Textbox(elem_id="send_to_browser", visible=False)
|
||||
arrange_dl_id = gr.Textbox(elem_id="arrange_dl_id", visible=False)
|
||||
remove_dl_id = gr.Textbox(elem_id="remove_dl_id", visible=False)
|
||||
|
|
@ -977,6 +1004,13 @@ def on_ui_tabs():
|
|||
outputs=browser_list
|
||||
)
|
||||
|
||||
# Settings function
|
||||
create_subfolder.change(
|
||||
fn=_file.updateSubfolder,
|
||||
inputs=create_subfolder,
|
||||
outputs=[]
|
||||
)
|
||||
|
||||
if ver_bool:
|
||||
tab_name = "CivitAI Browser+"
|
||||
else:
|
||||
|
|
@ -985,72 +1019,10 @@ def on_ui_tabs():
|
|||
return (civitai_interface, tab_name, "civitai_interface"),
|
||||
|
||||
def subfolder_list(folder, desc=None):
|
||||
insert_sub_1 = getattr(opts, "insert_sub_1", False)
|
||||
insert_sub_2 = getattr(opts, "insert_sub_2", False)
|
||||
insert_sub_3 = getattr(opts, "insert_sub_3", False)
|
||||
insert_sub_4 = getattr(opts, "insert_sub_4", False)
|
||||
insert_sub_5 = getattr(opts, "insert_sub_5", False)
|
||||
insert_sub_6 = getattr(opts, "insert_sub_6", False)
|
||||
insert_sub_7 = getattr(opts, "insert_sub_7", False)
|
||||
insert_sub_8 = getattr(opts, "insert_sub_8", False)
|
||||
insert_sub_9 = getattr(opts, "insert_sub_9", False)
|
||||
insert_sub_10 = getattr(opts, "insert_sub_10", False)
|
||||
insert_sub_11 = getattr(opts, "insert_sub_11", False)
|
||||
insert_sub_12 = getattr(opts, "insert_sub_12", False)
|
||||
insert_sub_13 = getattr(opts, "insert_sub_13", False)
|
||||
insert_sub_14 = getattr(opts, "insert_sub_14", False)
|
||||
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, followlinks=True):
|
||||
if dot_subfolders:
|
||||
dirs = [d for d in dirs if not d.startswith('.')]
|
||||
dirs = [d for d in dirs if not any(part.startswith('.') for part in os.path.join(root, d).split(os.sep))]
|
||||
for d in dirs:
|
||||
sub_folder = os.path.relpath(os.path.join(root, d), model_folder)
|
||||
if sub_folder:
|
||||
sub_folders.append(f'{os.sep}{sub_folder}')
|
||||
|
||||
sub_folders.remove("None")
|
||||
sub_folders = sorted(sub_folders, key=lambda x: (x.lower(), x))
|
||||
sub_folders.insert(0, "None")
|
||||
if insert_sub_1:
|
||||
sub_folders.insert(1, f"{os.sep}Base model")
|
||||
if insert_sub_2:
|
||||
sub_folders.insert(2, f"{os.sep}Base model{os.sep}Author name")
|
||||
if insert_sub_3:
|
||||
sub_folders.insert(3, f"{os.sep}Base model{os.sep}Author name{os.sep}Model name")
|
||||
if insert_sub_4:
|
||||
sub_folders.insert(4, f"{os.sep}Base model{os.sep}Author name{os.sep}Model name{os.sep}Model version")
|
||||
if insert_sub_5:
|
||||
sub_folders.insert(5, f"{os.sep}Base model{os.sep}Model name")
|
||||
if insert_sub_6:
|
||||
sub_folders.insert(6, f"{os.sep}Base model{os.sep}Model name{os.sep}Model version")
|
||||
if insert_sub_7:
|
||||
sub_folders.insert(7, f"{os.sep}Author name")
|
||||
if insert_sub_8:
|
||||
sub_folders.insert(8, f"{os.sep}Author name{os.sep}Base model")
|
||||
if insert_sub_9:
|
||||
sub_folders.insert(9, f"{os.sep}Author name{os.sep}Base model{os.sep}Model name")
|
||||
if insert_sub_10:
|
||||
sub_folders.insert(10, f"{os.sep}Author name{os.sep}Base model{os.sep}Model name{os.sep}Model version")
|
||||
if insert_sub_11:
|
||||
sub_folders.insert(11, f"{os.sep}Author name{os.sep}Model name")
|
||||
if insert_sub_12:
|
||||
sub_folders.insert(12, f"{os.sep}Author name{os.sep}Model name{os.sep}Model version")
|
||||
if insert_sub_13:
|
||||
sub_folders.insert(13, f"{os.sep}Model name")
|
||||
if insert_sub_14:
|
||||
sub_folders.insert(14, f"{os.sep}Model name{os.sep}Model version")
|
||||
|
||||
list = set()
|
||||
sub_folders = [x for x in sub_folders if not (x in list or list.add(x))]
|
||||
except:
|
||||
return None
|
||||
sub_folders = _file.getSubfolders(model_folder)
|
||||
return sub_folders
|
||||
|
||||
def make_lambda(folder, desc):
|
||||
|
|
@ -1340,37 +1312,8 @@ def on_ui_settings():
|
|||
).info("Not recommended for security, may be required if you do not have the correct CA Bundle available")
|
||||
)
|
||||
|
||||
id_and_sub_options = {
|
||||
"1" : f"{os.sep}Base model",
|
||||
"2" : f"{os.sep}Base model{os.sep}Author name",
|
||||
"3" : f"{os.sep}Base model{os.sep}Author name{os.sep}Model name",
|
||||
"4" : f"{os.sep}Base model{os.sep}Author name{os.sep}Model name{os.sep}Model version",
|
||||
"5" : f"{os.sep}Base model{os.sep}Model name",
|
||||
"6" : f"{os.sep}Base model{os.sep}Model name{os.sep}Model version",
|
||||
"7" : f"{os.sep}Author name",
|
||||
"8" : f"{os.sep}Author name{os.sep}Base model",
|
||||
"9" : f"{os.sep}Author name{os.sep}Base model{os.sep}Model name",
|
||||
"10" : f"{os.sep}Author name{os.sep}Base model{os.sep}Model name{os.sep}Model version",
|
||||
"11" : f"{os.sep}Author name{os.sep}Model name",
|
||||
"12" : f"{os.sep}Author name{os.sep}Model name{os.sep}Model version",
|
||||
"13" : f"{os.sep}Model name",
|
||||
"14" : f"{os.sep}Model name{os.sep}Model version",
|
||||
}
|
||||
|
||||
for number, string in id_and_sub_options.items():
|
||||
shared.opts.add_option(
|
||||
f"insert_sub_{number}",
|
||||
shared.OptionInfo(
|
||||
False,
|
||||
f"Insert: [{string}]",
|
||||
section=download,
|
||||
**({'category_id': cat_id} if ver_bool else {})
|
||||
)
|
||||
)
|
||||
|
||||
use_LORA = getattr(opts, "use_LORA", False)
|
||||
|
||||
# Default sub folders
|
||||
use_LORA = getattr(opts, "use_LORA", False)
|
||||
folders = [
|
||||
"Checkpoint",
|
||||
"LORA, LoCon, DoRA" if use_LORA else "LORA",
|
||||
|
|
@ -1409,7 +1352,7 @@ def on_ui_settings():
|
|||
folder = "LORA"
|
||||
setting_name = "LORA_LoCon"
|
||||
|
||||
shared.opts.add_option(f"{setting_name}_subfolder", shared.OptionInfo("None", folder_name, gr.Dropdown, make_lambda(folder, desc), section=download, **({'category_id': cat_id} if ver_bool else {})))
|
||||
shared.opts.add_option(f"{setting_name}_default_subfolder", shared.OptionInfo("None", folder_name, gr.Dropdown, make_lambda(folder, desc), section=download, **({'category_id': cat_id} if ver_bool else {})))
|
||||
|
||||
script_callbacks.on_ui_tabs(on_ui_tabs)
|
||||
script_callbacks.on_ui_settings(on_ui_settings)
|
||||
|
|
|
|||
23
style.css
23
style.css
|
|
@ -537,6 +537,29 @@
|
|||
padding: 8px 8px;
|
||||
}
|
||||
|
||||
.flex-column-layout {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.sub-folder-button-container {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.guide-button {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.plus-button {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
|
||||
#accordionToggle {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
|
|
|
|||
Loading…
Reference in New Issue