Upload 3 files
Browse files- javascript/colab_sd_models.js +244 -0
- scripts/colab_sd_models.py +242 -0
- style.css +302 -0
javascript/colab_sd_models.js
ADDED
|
@@ -0,0 +1,244 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
document.addEventListener('DOMContentLoaded', () => {
|
| 2 |
+
const observer = new MutationObserver((mutations) => {
|
| 3 |
+
mutations.forEach((mutation) => {
|
| 4 |
+
if (mutation.addedNodes) {
|
| 5 |
+
mutation.addedNodes.forEach((node) => {
|
| 6 |
+
if (node.id === 'tab_models_list') {
|
| 7 |
+
// запуск кода после загрузки элементов
|
| 8 |
+
Array.from(document.querySelectorAll('#tabs > div.tab-nav > button')).find(button => button.textContent.includes('модели')).click();
|
| 9 |
+
// переопределение параметров колонок на основе числа моделей в категории
|
| 10 |
+
const models_checkbox_grids = document.querySelectorAll("#tab_models_list fieldset > div[data-testid='checkbox-group']");
|
| 11 |
+
models_checkbox_grids.forEach(models_checkbox_grid => {
|
| 12 |
+
const model_label = models_checkbox_grid.querySelectorAll('label');
|
| 13 |
+
const numColumns = model_label.length > 9 ? 'repeat(auto-fit, minmax(250px, 1fr))' : '1fr';
|
| 14 |
+
models_checkbox_grid.style.gridTemplateColumns = numColumns;
|
| 15 |
+
});
|
| 16 |
+
// подвсетка категории мужицких моделей (костаыль, потому что градио своим скриптом долбит каждые Nms переопределение классов)
|
| 17 |
+
const intervalId = setInterval(() => {
|
| 18 |
+
const modelsNavButtons = document.querySelectorAll("div#tab_models_list > div.gap > div.tabs > div.tab-nav > button");
|
| 19 |
+
const MaleCat = Array.from(modelsNavButtons).find(button => button.textContent.includes('мужские'));
|
| 20 |
+
if (MaleCat) {
|
| 21 |
+
MaleCat.setAttribute("id", "male_only");
|
| 22 |
+
}
|
| 23 |
+
}, 100);
|
| 24 |
+
// получение инфы по кд о свободном пространтсве из скрытого уродского текстбокса в красивый элементик в шапочке
|
| 25 |
+
const freespacetextarea = document.querySelector("#free_space_area > label > textarea");
|
| 26 |
+
const frespace_out = document.querySelector("#frespace_out");
|
| 27 |
+
let prevValue = freespacetextarea.value;
|
| 28 |
+
setInterval(function () {
|
| 29 |
+
const currentValue = freespacetextarea.value;
|
| 30 |
+
if (currentValue !== prevValue) {
|
| 31 |
+
frespace_out.innerHTML = `${currentValue}`;
|
| 32 |
+
prevValue = currentValue;
|
| 33 |
+
}
|
| 34 |
+
}, 100);
|
| 35 |
+
// скликивание реальной но скрытой уродской кнопки с обработчиком проверки свободного места при нажатии на фейковую но красивую кнопочку
|
| 36 |
+
const freespace_getButton = document.querySelector("#freespace_get");
|
| 37 |
+
const free_spaceOrigButton = document.querySelector("#free_space_button");
|
| 38 |
+
freespace_getButton.addEventListener("click", function () {
|
| 39 |
+
free_spaceOrigButton.click();
|
| 40 |
+
});
|
| 41 |
+
// копирование реальных элементов из вкладок с моделями в результатах поиска
|
| 42 |
+
const SearchBlock = document.querySelector('#clear_search_models_results').closest('label').closest('div').closest('div').closest('div');
|
| 43 |
+
const ModelDLHeaderBlock = document.querySelector('.models_dl_header').closest('div').parentNode.closest('div').closest('div');
|
| 44 |
+
const ModelDLHeaderContainer = document.querySelector('.models_dl_header').closest('div').parentNode;
|
| 45 |
+
ModelDLHeaderBlock.appendChild(SearchBlock);
|
| 46 |
+
// небольшой css-фикс
|
| 47 |
+
ModelDLHeaderContainer.style.cssText = `display: flex; flex-direction: row; align-items: center; justify-content: flex-start; flex-wrap: wrap;`;
|
| 48 |
+
document.querySelector('.models_dl_header').parentNode.style.marginRight = "50px";
|
| 49 |
+
// фильтрация моделей при вводе
|
| 50 |
+
const searchInput = document.querySelector('input[type="text"]');
|
| 51 |
+
const findedModels = document.querySelector('#finded_models');
|
| 52 |
+
const tabModelsList = document.querySelector('#tab_models_list');
|
| 53 |
+
const labels = tabModelsList.querySelectorAll('label');
|
| 54 |
+
const clearSearchResultsButton = document.querySelector("#clear_search_models_results");
|
| 55 |
+
searchInput.addEventListener('input', (event) => {
|
| 56 |
+
const searchTerm = event.target.value.toLowerCase();
|
| 57 |
+
findedModels.innerHTML = '';
|
| 58 |
+
if (searchTerm !== '') {
|
| 59 |
+
labels.forEach((label) => {
|
| 60 |
+
const labelText = label.textContent.toLowerCase();
|
| 61 |
+
if (labelText.includes(searchTerm)) {
|
| 62 |
+
const clone = label.cloneNode(true);
|
| 63 |
+
findedModels.appendChild(clone);
|
| 64 |
+
const originalCheckbox = label.querySelector('input[type="checkbox"]');
|
| 65 |
+
const clonedCheckbox = clone.querySelector('input[type="checkbox"]');
|
| 66 |
+
clonedCheckbox.addEventListener('change', () => {
|
| 67 |
+
originalCheckbox.click();
|
| 68 |
+
});
|
| 69 |
+
}
|
| 70 |
+
});
|
| 71 |
+
}
|
| 72 |
+
});
|
| 73 |
+
// обработчик на кнопочку очистки результатов
|
| 74 |
+
clearSearchResultsButton.addEventListener('click', () => {
|
| 75 |
+
findedModels.innerHTML = '';
|
| 76 |
+
searchInput.value = '';
|
| 77 |
+
});
|
| 78 |
+
// автоматическое скликивание скрытых кнопок для подгрузки установленных моделей и свободного места после загрузки дополнения через 1 сек
|
| 79 |
+
setTimeout(() => document.querySelector("#files_button").click(), 1000);
|
| 80 |
+
setTimeout(() => document.querySelector("#free_space_button").click(), 1000);
|
| 81 |
+
// файловый менеджер на тексбоксах
|
| 82 |
+
setTimeout(() => {
|
| 83 |
+
const filesArea = document.querySelector("#files_area > label > textarea");
|
| 84 |
+
const filesCheckbox = document.querySelector("#files_checkbox");
|
| 85 |
+
const deleteArea = document.querySelector("#delete_area > label > textarea");
|
| 86 |
+
// обновление списка чекбоксов с файлами при изменении списка путей в текстбоксе
|
| 87 |
+
function addCheckboxEventListeners() {
|
| 88 |
+
const delete_checkboxes = document.querySelectorAll("#files_checkbox > label > input[type=checkbox]");
|
| 89 |
+
delete_checkboxes.forEach(checkbox => {
|
| 90 |
+
checkbox.addEventListener("change", event => {
|
| 91 |
+
// отмеченные на удаление делаем красными и зачеркнутыми
|
| 92 |
+
const delete_span = event.target.parentElement.querySelector("span");
|
| 93 |
+
if (event.target.checked) {
|
| 94 |
+
delete_span.style.textDecoration = "line-through";
|
| 95 |
+
delete_span.style.color = "#ed5252";
|
| 96 |
+
} else {
|
| 97 |
+
delete_span.style.textDecoration = "none";
|
| 98 |
+
delete_span.style.color = "";
|
| 99 |
+
}
|
| 100 |
+
});
|
| 101 |
+
});
|
| 102 |
+
}
|
| 103 |
+
// функция для обновления чекбоксов с файлами почти в реальном времени
|
| 104 |
+
function updateCheckboxes() {
|
| 105 |
+
while (filesCheckbox.firstChild) {
|
| 106 |
+
filesCheckbox.removeChild(filesCheckbox.firstChild);
|
| 107 |
+
}
|
| 108 |
+
const fileNames = filesArea.value.split("\n").map(path => path.split("/").pop());
|
| 109 |
+
if (fileNames.length === 0 || (fileNames.length === 1 && fileNames[0] === "")) {
|
| 110 |
+
const message = document.createElement("p");
|
| 111 |
+
message.textContent = "ничего не найдено";
|
| 112 |
+
filesCheckbox.appendChild(message);
|
| 113 |
+
} else {
|
| 114 |
+
fileNames.forEach(fileName => {
|
| 115 |
+
const checkbox = document.createElement("input");
|
| 116 |
+
checkbox.type = "checkbox";
|
| 117 |
+
checkbox.id = fileName;
|
| 118 |
+
checkbox.addEventListener("change", event => {
|
| 119 |
+
if (event.target.checked) {
|
| 120 |
+
deleteArea.value += (deleteArea.value ? "\n" : "") + fileName;
|
| 121 |
+
} else {
|
| 122 |
+
const lines = deleteArea.value.split("\n");
|
| 123 |
+
const index = lines.indexOf(fileName);
|
| 124 |
+
if (index !== -1) {
|
| 125 |
+
lines.splice(index, 1);
|
| 126 |
+
deleteArea.value = lines.join("\n");
|
| 127 |
+
}
|
| 128 |
+
}
|
| 129 |
+
deleteArea.dispatchEvent(new Event('input')); // имитация ввода, это самая важная часть кода
|
| 130 |
+
});
|
| 131 |
+
const label = document.createElement("label");
|
| 132 |
+
label.htmlFor = fileName;
|
| 133 |
+
label.className = "filecheckbox";
|
| 134 |
+
const span = document.createElement("span");
|
| 135 |
+
span.textContent = fileName;
|
| 136 |
+
label.appendChild(checkbox);
|
| 137 |
+
label.appendChild(span);
|
| 138 |
+
filesCheckbox.appendChild(label);
|
| 139 |
+
});
|
| 140 |
+
}
|
| 141 |
+
deleteArea.value = deleteArea.value.trim();
|
| 142 |
+
deleteArea.dispatchEvent(new Event('input')); // имитация ввода, без этого не работает
|
| 143 |
+
addCheckboxEventListeners()
|
| 144 |
+
}
|
| 145 |
+
// наблюдаем за скрытым тексбоксом с путями до моделей и обнов��ям чекбоксы
|
| 146 |
+
const observer = new MutationObserver(updateCheckboxes);
|
| 147 |
+
observer.observe(filesArea, { characterData: true, subtree: true });
|
| 148 |
+
updateCheckboxes();
|
| 149 |
+
// скликивание реальной но скрытой уродской кнопки с обработчиком обновления списка файлов при нажатии на фейковую но красивую кнопочку
|
| 150 |
+
const RefreshFilesButton = document.querySelector("#refresh_files_button");
|
| 151 |
+
RefreshFilesButton.addEventListener("click", () => {
|
| 152 |
+
document.querySelector("#files_button").click();
|
| 153 |
+
// задержки по 3 секунды необходимы, чтобы колаб одуплился
|
| 154 |
+
setTimeout(function () { updateCheckboxes(); }, 3000);
|
| 155 |
+
});
|
| 156 |
+
// при клике на фейковую кнопочку удаления - произойдет и обновление списка файлов с задержкой 3 сек
|
| 157 |
+
document.querySelector("#delete_button").addEventListener("click", function () {
|
| 158 |
+
setTimeout(function () {
|
| 159 |
+
document.querySelector("#files_button").click();
|
| 160 |
+
// задержки по 3 секунды необходимы, чтобы колаб одуплился
|
| 161 |
+
setTimeout(function () { updateCheckboxes(); }, 3000);
|
| 162 |
+
}, 3000);
|
| 163 |
+
});
|
| 164 |
+
// скликивание реальной но скрытой уродской кнопки с обработчиком удаления моделей при нажатии на фейковую но красивую кнопочку
|
| 165 |
+
const OrigDelButton = document.querySelector("#delete_button");
|
| 166 |
+
const CustomDelButton = document.querySelector("#delete_files_button");
|
| 167 |
+
CustomDelButton.addEventListener("click", () => {
|
| 168 |
+
OrigDelButton.click();
|
| 169 |
+
});
|
| 170 |
+
// проверка выхлопа из функции загрузки в скрытом текстбоксе
|
| 171 |
+
setInterval(function () {
|
| 172 |
+
var DLresultText = document.querySelector("#downloads_result_text > span.finish_dl_func");
|
| 173 |
+
DLresultText.textContent = document.querySelector("#dlresultbox > label > textarea").value;
|
| 174 |
+
// функция скрытия прогрессбара
|
| 175 |
+
function checkDLresult(element, text) {
|
| 176 |
+
if (element.textContent.includes(text)) {
|
| 177 |
+
document.querySelector("div.downloads_result_container > div.models_porgress_loader").style.removeProperty("display");
|
| 178 |
+
document.querySelector("#downloads_start_text").style.removeProperty("display");
|
| 179 |
+
document.querySelector("#downloads_result_text > span.dl_progress_info").textContent = "чтобы новые файлы появились в выпадающем списке моделей, нужно обновить их список по соответсвующей кнопке";
|
| 180 |
+
}
|
| 181 |
+
}
|
| 182 |
+
// просто скрываем прогрессбар если в выхлопе есть фраза о завершении или предупреждение
|
| 183 |
+
checkDLresult(DLresultText, "заверш");
|
| 184 |
+
checkDLresult(DLresultText, "слишком");
|
| 185 |
+
checkDLresult(DLresultText, "ОШИБКА");
|
| 186 |
+
// раскрашиваем текст сообщения о результате выполнения, если что-то пошло не так
|
| 187 |
+
if (DLresultText) {
|
| 188 |
+
if (DLresultText.textContent.includes("слишком")) {
|
| 189 |
+
DLresultText.style.setProperty("color", "#ff4f8b", "important");
|
| 190 |
+
} else if (DLresultText.textContent.includes("ОШИБКА")) {
|
| 191 |
+
DLresultText.style.setProperty("color", "#de2f2f", "important");
|
| 192 |
+
} else if (DLresultText.textContent.includes("заверш")) {
|
| 193 |
+
DLresultText.style.setProperty("color", "#99fb99", "important");
|
| 194 |
+
}
|
| 195 |
+
}
|
| 196 |
+
}, 200);
|
| 197 |
+
// действия по клику на фейковую но видимую кнопку для скачивания
|
| 198 |
+
document.querySelector("#general_download_button").addEventListener("click", function () {
|
| 199 |
+
// очистка текстбокса от выхлопа предыдущего выполнения
|
| 200 |
+
var resultTextareaDL = document.querySelector("#dlresultbox > label > textarea");
|
| 201 |
+
resultTextareaDL.value = "";
|
| 202 |
+
var resultClearOut = new Event("input", { bubbles: true }); // без этого не будет работать обноволение .value
|
| 203 |
+
resultTextareaDL.dispatchEvent(resultClearOut);
|
| 204 |
+
// делаем прогрессбар и место для результирующего текста видимыми
|
| 205 |
+
const DLprogressBar = document.querySelector("div.downloads_result_container > div.models_porgress_loader");
|
| 206 |
+
DLprogressBar.style.setProperty("display", "block", "important");
|
| 207 |
+
const DLresultText = document.querySelector("#downloads_result_text");
|
| 208 |
+
DLresultText.style.setProperty("display", "block", "important");
|
| 209 |
+
document.querySelector("#downloads_start_text").style.setProperty("display", "block", "important");
|
| 210 |
+
// скликивание реальных но скрытых кнопок с обработчиками загрузки файлов по чекбоксам и кастомных ссылок при нажатии на фейковую но кнопочку
|
| 211 |
+
// формирование списка из кастомных ссылок
|
| 212 |
+
document.querySelector("#ownlinks_download_button").click();
|
| 213 |
+
setTimeout(function () {
|
| 214 |
+
// через 3 сек. добавим его к списку ссылок из чекбоксов и отправим на загрузку вместе
|
| 215 |
+
document.querySelector("#checkboxes_download_button").click();
|
| 216 |
+
}, 3000); // задержка, чтобы колаб успел одуплиться
|
| 217 |
+
});
|
| 218 |
+
// если кнопка загрузки уже нажата, запрещаем кликать еще раз пока функция загрузки не выплюнет ответ
|
| 219 |
+
var GendownloadButton = document.querySelector("#general_download_button");
|
| 220 |
+
var DLprogressBar = document.querySelector("div.downloads_result_container > div.models_porgress_loader");
|
| 221 |
+
if (GendownloadButton && DLprogressBar) {
|
| 222 |
+
var DLobserver = new MutationObserver(function (mutations) {
|
| 223 |
+
mutations.forEach(function (mutation) {
|
| 224 |
+
if (mutation.type === "attributes" && mutation.attributeName === "style") { // отслеживание видимости прогрессбара
|
| 225 |
+
if (DLprogressBar.style.display === "block") {
|
| 226 |
+
GendownloadButton.setAttribute("disabled", "disabled");
|
| 227 |
+
} else {
|
| 228 |
+
setTimeout(function () {
|
| 229 |
+
GendownloadButton.removeAttribute("disabled");
|
| 230 |
+
}, 3000); // не сразу даем кликнуть снова, а после ожидания 3 секунды, чтобы не закликали
|
| 231 |
+
}
|
| 232 |
+
}
|
| 233 |
+
});
|
| 234 |
+
});
|
| 235 |
+
DLobserver.observe(DLprogressBar, { attributes: true });
|
| 236 |
+
}
|
| 237 |
+
}, 9000); // запуск скриптов через 9 секунд после загрузки вебуи, чтобы успели отработать скрипты других дополнений и градио
|
| 238 |
+
}
|
| 239 |
+
});
|
| 240 |
+
}
|
| 241 |
+
});
|
| 242 |
+
});
|
| 243 |
+
observer.observe(document.body, { childList: true, subtree: true });
|
| 244 |
+
});
|
scripts/colab_sd_models.py
ADDED
|
@@ -0,0 +1,242 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import re
|
| 3 |
+
import requests
|
| 4 |
+
import shutil
|
| 5 |
+
import subprocess
|
| 6 |
+
from concurrent.futures import ThreadPoolExecutor, as_completed
|
| 7 |
+
|
| 8 |
+
import gradio as gr
|
| 9 |
+
from bs4 import BeautifulSoup
|
| 10 |
+
from modules import script_callbacks, scripts, shared, sd_models
|
| 11 |
+
from modules.paths_internal import data_path
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
urlprefix = "https://huggingface.co/2ch/models/resolve/main/"
|
| 15 |
+
models_json_data = requests.get(urlprefix + "colab_models.json").json()
|
| 16 |
+
wget = "wget -nv -t 10 --show-progress --progress=bar:force -q --content-disposition "
|
| 17 |
+
sdroot = data_path
|
| 18 |
+
models_folder_path = sd_models.model_path
|
| 19 |
+
loras_folder_path = shared.cmd_opts.lora_dir
|
| 20 |
+
embeddings_folder_path = shared.cmd_opts.embeddings_dir
|
| 21 |
+
ct = "token=542c1d6077168822e1b49e30e3437a5d"
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
def on_ui_tabs():
|
| 25 |
+
with gr.Blocks() as models_list:
|
| 26 |
+
# шапка вкладки с поиском и свободным местом на диске
|
| 27 |
+
gr.HTML(
|
| 28 |
+
"""<div class="models_top_container"><div class="models_top_header_text"><h1 class="models_dl_header">выбор и скачивание моделей</h1><p>учитывай весьма ограниченное пространство на диске в колабе!</p></div><div class="freespaceinfo"><div id="frespace_output"><span>свободно в колабе: <span id="frespace_out">нажми на кнопочку</span></div><div id="freespace_get"></div></div></div>""")
|
| 29 |
+
search_and_results = gr.HTML(
|
| 30 |
+
"""<label id="models_search_field"><input type="text" id="models_search_input" class="svelte-1pie7s6" placeholder="начни вводить для поиска"/><span id="clear_search_models_results"></span></label><div id="finded_models"></div>""")
|
| 31 |
+
# вкладки с категориями
|
| 32 |
+
buttons = []
|
| 33 |
+
checkbox_groups = []
|
| 34 |
+
checkboxes = []
|
| 35 |
+
for category in models_json_data['categories']:
|
| 36 |
+
categories = ["models_A", "models_B", "models_C", "models_D", "models_E", "models_F", "models_G", "models_H", "models_I", "models_J", "models_K", "models_L", "models_M", "models_N", "models_O", "models_P", "models_Q"]
|
| 37 |
+
tab_names = ["аниме", "лайнарт", "женские", "игры и кино", "техника и космос", "крипота", "макро", "мемные", "мужские", "мультфильмы", "пиксельарт", "трехмерная графика", "универсальные", "фотореализм", "фурри", "футанари",
|
| 38 |
+
"художественные"]
|
| 39 |
+
category_map = dict(zip(categories, tab_names))
|
| 40 |
+
tab_name = category_map.get(category)
|
| 41 |
+
with gr.Tab(tab_name):
|
| 42 |
+
checkbox_group = gr.CheckboxGroup(sorted(models_json_data['categories'][category], key=lambda x: x.lower()), label="")
|
| 43 |
+
checkboxes.append(checkbox_group)
|
| 44 |
+
checkbox_groups.append(checkbox_group)
|
| 45 |
+
# ссылки для реквеста добавления моделей
|
| 46 |
+
gr.HTML(
|
| 47 |
+
"""<div class="request_new_models">не нашел нужную модель? запрос на добавление можно отправить в <a href="https://t.me/colabSDbot" target="_blank">бота</a> или <a href="https://t.me/stabdiff" target="_blank">группу</a>.</div>""")
|
| 48 |
+
|
| 49 |
+
# функция для формирования списка своих ссылок
|
| 50 |
+
def get_own_links(ownmodels, ownloras, ownembeddings):
|
| 51 |
+
urls = []
|
| 52 |
+
for text, dlpath in zip([ownmodels, ownloras, ownembeddings], [models_folder_path, loras_folder_path, embeddings_folder_path]):
|
| 53 |
+
lines = text.split("\n")
|
| 54 |
+
for line in lines:
|
| 55 |
+
if line.strip():
|
| 56 |
+
# url = wget+line+" -P "+dlpath
|
| 57 |
+
link = line.strip() + (f'?{ct}' if '?' not in line else f'&{ct}') if 'civitai' in line else line.strip()
|
| 58 |
+
url = f'{wget}"{link}" -P {dlpath}'
|
| 59 |
+
urls.append(url)
|
| 60 |
+
own_urls = os.path.join(sdroot, "urls.txt")
|
| 61 |
+
with open(own_urls, "w") as f:
|
| 62 |
+
for url in urls:
|
| 63 |
+
f.write(url + "\n")
|
| 64 |
+
print("список загрузки сформирован...")
|
| 65 |
+
|
| 66 |
+
# текстбоксы для указания своих ссылок
|
| 67 |
+
gr.HTML("""<div class="ownfiles_header"><h2>здесь можно указать прямые ссылки на загрузку моделей, лор и внедрений</h2></div>""")
|
| 68 |
+
with gr.Row():
|
| 69 |
+
plhd = """вставляй каждую ссылку с новой строки!\nпримеры ссылок:\nhttps://models.tensorplay.ai/104249\nhttps://civitai.com/api/download/models/110660\nhttps://huggingface.co/2ch/gay/resolve/main/lora/BettercocksFlaccid.safetensors"""
|
| 70 |
+
ownmodels = gr.Textbox(label="модели", placeholder=plhd, info="прямые ссылки на Checkpoints", lines=5, elem_id="ownmodels")
|
| 71 |
+
ownloras = gr.Textbox(label="лоры", placeholder=plhd, info="прямые ссылки на LoRas", lines=5, elem_id="ownloras")
|
| 72 |
+
ownembeddings = gr.Textbox(label="внедрения", placeholder=plhd, info="прямые ссылки на Textual Inversions", lines=5, elem_id="ownembeddings")
|
| 73 |
+
# кнопка при нажатии на которую происходит сначала клик на кнопку формирования списка своих ссылок, а потом на кнопку основной функции загрузки
|
| 74 |
+
download_button = gr.Button("скачать выбранные модели", elem_id="general_download_button")
|
| 75 |
+
# кнопка для формирования списка своих ссылок
|
| 76 |
+
button = gr.Button("скачать по ссылкам", elem_id="ownlinks_download_button")
|
| 77 |
+
button.click(get_own_links, inputs=[ownmodels, ownloras, ownembeddings])
|
| 78 |
+
# кнопка для отправки на загрузку
|
| 79 |
+
download_button = gr.Button("скачать отмеченные модели", elem_id="checkboxes_download_button")
|
| 80 |
+
|
| 81 |
+
# функция определения точки монтирования и свободного места на диске
|
| 82 |
+
def find_mount_point():
|
| 83 |
+
# __file__ = "."
|
| 84 |
+
path = os.path.realpath(__file__)
|
| 85 |
+
path = os.path.abspath(path)
|
| 86 |
+
while not os.path.ismount(path):
|
| 87 |
+
path = os.path.dirname(path)
|
| 88 |
+
return path
|
| 89 |
+
|
| 90 |
+
def free_space():
|
| 91 |
+
total, used, free = shutil.disk_usage(find_mount_point())
|
| 92 |
+
power = 2 ** 10
|
| 93 |
+
n = 0
|
| 94 |
+
power_labels = {0: '', 1: 'Кило', 2: 'Мега', 3: 'Гига', 4: 'Тера'}
|
| 95 |
+
while free > power:
|
| 96 |
+
free /= power
|
| 97 |
+
n += 1
|
| 98 |
+
return f"{free:.2f} {power_labels[n]}байт"
|
| 99 |
+
|
| 100 |
+
# функция вычисления общего размера загружаемых файлов в байтах
|
| 101 |
+
def get_file_size(url):
|
| 102 |
+
url = re.search(r'https?://\S+', url).group()
|
| 103 |
+
|
| 104 |
+
def contleght(url):
|
| 105 |
+
return int(requests.get(url, stream=True).headers.get('Content-Length', 0))
|
| 106 |
+
|
| 107 |
+
if "huggingface" in url:
|
| 108 |
+
try:
|
| 109 |
+
try:
|
| 110 |
+
file_size = int(next((pre.text.split('size ')[1].split('\n')[0] for pre in BeautifulSoup(requests.get(url.replace('resolve', 'blame')).text, 'html.parser').find_all('pre') if 'size' in pre.text)))
|
| 111 |
+
except:
|
| 112 |
+
file_size_text = BeautifulSoup(requests.get(url.replace('resolve', 'blob')).text, 'html.parser').find('strong', string='Size of remote file:').next_sibling.strip()
|
| 113 |
+
file_size = int(float(file_size_text.split()[0]) * {'KB': 1024, 'MB': 1024 ** 2, 'GB': 1024 ** 3, 'TB': 1024 ** 4}[file_size_text.split()[1]])
|
| 114 |
+
except:
|
| 115 |
+
file_size = contleght(url)
|
| 116 |
+
if file_size < 1048576: file_size = contleght(url)
|
| 117 |
+
elif "civitai" in url:
|
| 118 |
+
try:
|
| 119 |
+
file_size = int(requests.get("https://civitai.com/api/v1/model-versions/" + url.split('/')[-1] + civitai_token).json()["files"][0]["sizeKB"] * 1024)
|
| 120 |
+
except:
|
| 121 |
+
file_size = contleght(url)
|
| 122 |
+
if file_size < 1048576: file_size = contleght(url)
|
| 123 |
+
else:
|
| 124 |
+
file_size = contleght(url)
|
| 125 |
+
return file_size
|
| 126 |
+
|
| 127 |
+
# основная функция для загрузки отмеченных чекбоксов
|
| 128 |
+
def start_download(*checkbox_groups):
|
| 129 |
+
try:
|
| 130 |
+
urls = []
|
| 131 |
+
for checkbox_group in checkbox_groups:
|
| 132 |
+
selected_choices = checkbox_group
|
| 133 |
+
for choice in selected_choices:
|
| 134 |
+
if choice in models_json_data["models"]:
|
| 135 |
+
file_names = models_json_data["models"][choice].split(',')
|
| 136 |
+
for file_name in file_names:
|
| 137 |
+
url = wget + urlprefix + file_name.strip() + " -P " + models_folder_path
|
| 138 |
+
urls.append(url)
|
| 139 |
+
own_urls = os.path.join(sdroot, "urls.txt")
|
| 140 |
+
with open(own_urls, "r") as f:
|
| 141 |
+
own_links = f.read().splitlines()
|
| 142 |
+
urls.extend(own_links)
|
| 143 |
+
os.remove(own_urls)
|
| 144 |
+
except Exception as e:
|
| 145 |
+
print(f"ОШИБКА: {e}")
|
| 146 |
+
return f"ОШИБКА: {e}"
|
| 147 |
+
try:
|
| 148 |
+
def bytes_convert(size_bytes):
|
| 149 |
+
if size_bytes >= 1073741824:
|
| 150 |
+
return f"{round(size_bytes / 1073741824, 2)} Гб"
|
| 151 |
+
else:
|
| 152 |
+
return f"{round(size_bytes / 1048576, 2)} Мб"
|
| 153 |
+
|
| 154 |
+
def downloader(url):
|
| 155 |
+
process = subprocess.Popen(url, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
| 156 |
+
while True:
|
| 157 |
+
output = process.stdout.readline().decode('utf-8')
|
| 158 |
+
if output == '' and process.poll() is not None:
|
| 159 |
+
break
|
| 160 |
+
if output:
|
| 161 |
+
yield output.strip()
|
| 162 |
+
return process.poll()
|
| 163 |
+
|
| 164 |
+
total_file_size = 0
|
| 165 |
+
with ThreadPoolExecutor(max_workers=len(urls)) as executor:
|
| 166 |
+
futures = [executor.submit(get_file_size, url) for url in urls]
|
| 167 |
+
for future in as_completed(futures):
|
| 168 |
+
total_file_size += future.result()
|
| 169 |
+
total, used, free = shutil.disk_usage(find_mount_point())
|
| 170 |
+
if total_file_size <= (free - 1073741824):
|
| 171 |
+
print(f"загрузка {bytes_convert(total_file_size)} уже началась, жди!")
|
| 172 |
+
with ThreadPoolExecutor(max_workers=len(urls)) as executor:
|
| 173 |
+
futures = [executor.submit(downloader, url) for url in urls]
|
| 174 |
+
for future in as_completed(futures):
|
| 175 |
+
for line in future.result():
|
| 176 |
+
print(line)
|
| 177 |
+
if os.path.exists(os.path.join(models_folder_path, "nullModel.ckpt")):
|
| 178 |
+
try:
|
| 179 |
+
os.remove(os.path.join(models_folder_path, "nullModel.ckpt"))
|
| 180 |
+
except:
|
| 181 |
+
pass
|
| 182 |
+
return "функция загрузки завершила работу!"
|
| 183 |
+
else:
|
| 184 |
+
print(f"слишком много файлов! ты пытаешься скачать {bytes_convert(total_file_size)}, имея свободных только {bytes_convert(free)} (и как минимум 1 Гб должен оставаться не занятым на диске!).")
|
| 185 |
+
return f"слишком много файлов! ты пытаешься скачать {bytes_convert(total_file_size)}, имея свободных только {bytes_convert(free)} (и как минимум 1 Гб должен оставаться не занятым на диске!)."
|
| 186 |
+
except Exception as e:
|
| 187 |
+
print(f"ОШИБКА: {e}")
|
| 188 |
+
return f"ОШИБКА: {e}"
|
| 189 |
+
|
| 190 |
+
# скрытый текстбокс для вывода информации о результате
|
| 191 |
+
dlresultbox = gr.Textbox(label="", elem_id="dlresultbox")
|
| 192 |
+
download_button.click(start_download, inputs=checkbox_groups, outputs=dlresultbox)
|
| 193 |
+
# анимация процесса выполнения функции загрузки
|
| 194 |
+
gr.HTML(
|
| 195 |
+
"""<div class="downloads_result_container"><div class="models_porgress_loader"></div><div id="downloads_start_text">задача по загрузке запущена, подробности в выводе ячейки в колабе...</div><div id="downloads_result_text"><span class="finish_dl_func"></span><span class="dl_progress_info"></span></div></div>""")
|
| 196 |
+
# скрытые элементы для взаимодействия с функцией определения места на диске
|
| 197 |
+
spacetextbox = gr.Textbox(label="", elem_id="free_space_area")
|
| 198 |
+
space_button = gr.Button("проверить свободное место", elem_id="free_space_button")
|
| 199 |
+
space_button.click(fn=free_space, outputs=spacetextbox)
|
| 200 |
+
# HTML-разметка для формирования чекбоксов для удаления файлов моделей
|
| 201 |
+
gr.HTML(
|
| 202 |
+
"""<hr class="divider"/><div id="filemanager"><h2 class="current_models_files">файлы моделей которые можно удалить для освобождения места:</h2><div id="files_checkbox"></div><div class="filebuttons"><div id="delete_files_button"></div><div id="refresh_files_button"></div></div></div>""")
|
| 203 |
+
|
| 204 |
+
# функция получения путей до установленных файлов моделей
|
| 205 |
+
def get_models_paths():
|
| 206 |
+
file_paths = []
|
| 207 |
+
for root, dirs, files in os.walk(models_folder_path):
|
| 208 |
+
for file in files:
|
| 209 |
+
file_path = os.path.join(root, file)
|
| 210 |
+
file_paths.append(file_path)
|
| 211 |
+
return '\n'.join(file_paths)
|
| 212 |
+
|
| 213 |
+
# скрытые текстбокс и кнопка для получения списка файлов из папки моделей
|
| 214 |
+
filestextbox = gr.Textbox(label="", elem_id="files_area")
|
| 215 |
+
files_button = gr.Button("установленные модели", elem_id="files_button")
|
| 216 |
+
files_button.click(fn=get_models_paths, outputs=filestextbox)
|
| 217 |
+
|
| 218 |
+
# функция удаления списка отмеченных файлов
|
| 219 |
+
def del_models(inputs):
|
| 220 |
+
files_to_delete = inputs.split("\n")
|
| 221 |
+
for file in files_to_delete:
|
| 222 |
+
if file and file != "None":
|
| 223 |
+
try:
|
| 224 |
+
os.remove(os.path.join(models_folder_path, file))
|
| 225 |
+
print(f"успешно удалена модель: {file}")
|
| 226 |
+
except OSError as e:
|
| 227 |
+
print(f"ОШИБКА: {e.filename} - {e.strerror}.")
|
| 228 |
+
else:
|
| 229 |
+
print("удалять нечего, или ничего не выбрано для удаления")
|
| 230 |
+
|
| 231 |
+
# скрытые текстбокс и кнопка для формирования списка файлов на удаление
|
| 232 |
+
deletetextbox = gr.Textbox(label="", elem_id="delete_area")
|
| 233 |
+
delete_button = gr.Button("удалить", elem_id="delete_button")
|
| 234 |
+
delete_button.click(fn=del_models, inputs=deletetextbox, outputs=deletetextbox)
|
| 235 |
+
with gr.Accordion("описания моделей (не обновляется)", open=False):
|
| 236 |
+
gr.HTML(requests.get("https://raw.githubusercontent.com/PR0LAPSE/PR0LAPSE.github.io/main/models.html").text)
|
| 237 |
+
# возврат всех элементов
|
| 238 |
+
return (models_list, "модели", "models_list"),
|
| 239 |
+
|
| 240 |
+
|
| 241 |
+
# вывод в вебуи
|
| 242 |
+
script_callbacks.on_ui_tabs(on_ui_tabs)
|
style.css
ADDED
|
@@ -0,0 +1,302 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#free_space_area,
|
| 2 |
+
#free_space_button,
|
| 3 |
+
#files_area,
|
| 4 |
+
#delete_area,
|
| 5 |
+
#files_button,
|
| 6 |
+
#delete_button,
|
| 7 |
+
#ownlinks_download_button,
|
| 8 |
+
#checkboxes_download_button,
|
| 9 |
+
#dlresultbox,
|
| 10 |
+
#downloads_result_text,
|
| 11 |
+
#downloads_start_text,
|
| 12 |
+
.models_porgress_loader {
|
| 13 |
+
display: none !important;
|
| 14 |
+
}
|
| 15 |
+
#models_search_input {
|
| 16 |
+
width: 500px !important;
|
| 17 |
+
float: none !important;
|
| 18 |
+
display: inline !important;
|
| 19 |
+
position: relative;
|
| 20 |
+
top: -25px;
|
| 21 |
+
}
|
| 22 |
+
#clear_search_models_results {
|
| 23 |
+
display: inline-block;
|
| 24 |
+
cursor: pointer !important;
|
| 25 |
+
--wh: 40px;
|
| 26 |
+
width: var(--wh);
|
| 27 |
+
height: var(--wh);
|
| 28 |
+
padding-top: 0px !important;
|
| 29 |
+
margin: 10px 0 0 10px!important;
|
| 30 |
+
position: relative;
|
| 31 |
+
top: -10px;
|
| 32 |
+
border-radius: 5px;
|
| 33 |
+
border: var(--button-border-width) solid var(--button-secondary-border-color);
|
| 34 |
+
text-align: center;
|
| 35 |
+
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='40' height='40' viewBox='0 0 40 40'%3E%3Cpath d='m9.02,30.98L30.98,9.02m0,21.96L9.02,9.02' fill='none' opacity='.5' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.17'/%3E%3C/svg%3E");
|
| 36 |
+
background-color: var(--button-secondary-background-fill);
|
| 37 |
+
}
|
| 38 |
+
#finded_models {
|
| 39 |
+
position: absolute;
|
| 40 |
+
z-index: 2;
|
| 41 |
+
width: 500px;
|
| 42 |
+
top: 50px;
|
| 43 |
+
background: var(--input-background-fill);
|
| 44 |
+
color: var(--body-text-color);
|
| 45 |
+
}
|
| 46 |
+
#finded_models label {
|
| 47 |
+
background: none !important;
|
| 48 |
+
border: none;
|
| 49 |
+
}
|
| 50 |
+
#tab_models_list .tabs label {
|
| 51 |
+
background: none !important;
|
| 52 |
+
border: none;
|
| 53 |
+
}
|
| 54 |
+
#tab_models_list .tabs .tabitem div fieldset div {
|
| 55 |
+
display: grid;
|
| 56 |
+
grid-gap: 10px;
|
| 57 |
+
}
|
| 58 |
+
#tab_models_list div[data-testid='checkbox-group'] label span {
|
| 59 |
+
width: 275px;
|
| 60 |
+
font-size: 0.92em !important;
|
| 61 |
+
white-space: nowrap;
|
| 62 |
+
overflow: hidden;
|
| 63 |
+
text-overflow: ellipsis;
|
| 64 |
+
}
|
| 65 |
+
#tab_models_list div.tab-nav > button {
|
| 66 |
+
font-size: 1em !important;
|
| 67 |
+
}
|
| 68 |
+
#tab_models_list fieldset label:hover:not(.selected) {
|
| 69 |
+
color: var(--checkbox-background-color-selected)!important;
|
| 70 |
+
}
|
| 71 |
+
#tab_models_list fieldset .selected {
|
| 72 |
+
color: #60d43d !important;
|
| 73 |
+
}
|
| 74 |
+
#general_download_button {
|
| 75 |
+
border: var(--button-border-width) solid var(--button-primary-border-color);
|
| 76 |
+
background: var(--button-primary-background-fill);
|
| 77 |
+
color: var(--button-primary-text-color);
|
| 78 |
+
margin-top: 28px !important;
|
| 79 |
+
}
|
| 80 |
+
#tab_models_list button.secondary {
|
| 81 |
+
width: 70%;
|
| 82 |
+
margin: 0 auto;
|
| 83 |
+
}
|
| 84 |
+
#male_only {
|
| 85 |
+
color: #b8dabb !important;
|
| 86 |
+
}
|
| 87 |
+
.freespaceinfo {
|
| 88 |
+
width: fit-content;
|
| 89 |
+
display: flex;
|
| 90 |
+
flex-direction: row;
|
| 91 |
+
flex-wrap: nowrap;
|
| 92 |
+
justify-content: flex-start;
|
| 93 |
+
align-items: center;
|
| 94 |
+
}
|
| 95 |
+
#frespace_output {
|
| 96 |
+
width: fit-content;
|
| 97 |
+
height: 40px;
|
| 98 |
+
border: 1px solid var(--button-secondary-border-color);
|
| 99 |
+
margin: -30px 0px 0px 0px;
|
| 100 |
+
display: flex;
|
| 101 |
+
flex-direction: row;
|
| 102 |
+
flex-wrap: nowrap;
|
| 103 |
+
align-items: center;
|
| 104 |
+
padding: 0px 15px;
|
| 105 |
+
font-size: 1.2em;
|
| 106 |
+
}
|
| 107 |
+
#freespace_get {
|
| 108 |
+
width: 40px;
|
| 109 |
+
height: 40px;
|
| 110 |
+
border: 1px solid var(--button-secondary-border-color);
|
| 111 |
+
margin: -30px 50px 0px 10px;
|
| 112 |
+
cursor: pointer;
|
| 113 |
+
background-image: url("data:image/svg+xml,%3Csvg id='refresh' xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 36 36'%3E%3Cpath fill='%23fff' opacity='.5' d='m3.33,33v-2.81h6.09l-.7-.56c-2-1.59-3.45-3.33-4.36-5.2-.91-1.88-1.36-3.97-1.36-6.28,0-3.31.98-6.29,2.93-8.93,1.95-2.64,4.52-4.46,7.71-5.46v2.91c-2.34.91-4.23,2.41-5.67,4.52-1.44,2.11-2.16,4.43-2.16,6.96,0,1.97.37,3.68,1.1,5.13.73,1.45,1.73,2.71,2.98,3.77l1.41.98v-5.81h2.81v10.78H3.33Zm19.08-.7v-2.95c2.37-.91,4.27-2.41,5.67-4.52,1.41-2.11,2.11-4.43,2.11-6.96,0-1.5-.37-3.02-1.1-4.57-.73-1.55-1.7-2.91-2.88-4.1l-1.36-1.22v5.81h-2.81V3h10.78v2.81h-6.14l.7.66c1.88,1.75,3.28,3.63,4.22,5.63.94,2,1.41,3.92,1.41,5.77,0,3.31-.97,6.3-2.91,8.95-1.94,2.66-4.5,4.48-7.69,5.48Z'%3E%3C/path%3E%3C/svg%3E");
|
| 114 |
+
background-position: 50%;
|
| 115 |
+
background-repeat: no-repeat
|
| 116 |
+
}
|
| 117 |
+
#freespace_get:hover {
|
| 118 |
+
background-color: #00000078;
|
| 119 |
+
background-image: url("data:image/svg+xml,%3Csvg id='refresh' xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 36 36'%3E%3Cpath fill='%23fff' opacity='.7' d='m3.33,33v-2.81h6.09l-.7-.56c-2-1.59-3.45-3.33-4.36-5.2-.91-1.88-1.36-3.97-1.36-6.28,0-3.31.98-6.29,2.93-8.93,1.95-2.64,4.52-4.46,7.71-5.46v2.91c-2.34.91-4.23,2.41-5.67,4.52-1.44,2.11-2.16,4.43-2.16,6.96,0,1.97.37,3.68,1.1,5.13.73,1.45,1.73,2.71,2.98,3.77l1.41.98v-5.81h2.81v10.78H3.33Zm19.08-.7v-2.95c2.37-.91,4.27-2.41,5.67-4.52,1.41-2.11,2.11-4.43,2.11-6.96,0-1.5-.37-3.02-1.1-4.57-.73-1.55-1.7-2.91-2.88-4.1l-1.36-1.22v5.81h-2.81V3h10.78v2.81h-6.14l.7.66c1.88,1.75,3.28,3.63,4.22,5.63.94,2,1.41,3.92,1.41,5.77,0,3.31-.97,6.3-2.91,8.95-1.94,2.66-4.5,4.48-7.69,5.48Z'%3E%3C/path%3E%3C/svg%3E");
|
| 120 |
+
}
|
| 121 |
+
#freespace_get:active {
|
| 122 |
+
background-color: #00000078;
|
| 123 |
+
background-image: url("data:image/svg+xml,%3Csvg id='refresh' xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 36 36'%3E%3Cpath fill='%23fff' opacity='.85' d='m3.33,33v-2.81h6.09l-.7-.56c-2-1.59-3.45-3.33-4.36-5.2-.91-1.88-1.36-3.97-1.36-6.28,0-3.31.98-6.29,2.93-8.93,1.95-2.64,4.52-4.46,7.71-5.46v2.91c-2.34.91-4.23,2.41-5.67,4.52-1.44,2.11-2.16,4.43-2.16,6.96,0,1.97.37,3.68,1.1,5.13.73,1.45,1.73,2.71,2.98,3.77l1.41.98v-5.81h2.81v10.78H3.33Zm19.08-.7v-2.95c2.37-.91,4.27-2.41,5.67-4.52,1.41-2.11,2.11-4.43,2.11-6.96,0-1.5-.37-3.02-1.1-4.57-.73-1.55-1.7-2.91-2.88-4.1l-1.36-1.22v5.81h-2.81V3h10.78v2.81h-6.14l.7.66c1.88,1.75,3.28,3.63,4.22,5.63.94,2,1.41,3.92,1.41,5.77,0,3.31-.97,6.3-2.91,8.95-1.94,2.66-4.5,4.48-7.69,5.48Z'%3E%3C/path%3E%3C/svg%3E");
|
| 124 |
+
transform: rotate(90deg)
|
| 125 |
+
}
|
| 126 |
+
span#frespace_out {
|
| 127 |
+
color: #7ced7c
|
| 128 |
+
}
|
| 129 |
+
.ownfiles_header {
|
| 130 |
+
display: flex;
|
| 131 |
+
}
|
| 132 |
+
.ownfiles_header > span {
|
| 133 |
+
margin-right: 50px;
|
| 134 |
+
}
|
| 135 |
+
.ownfiles_header h2 {
|
| 136 |
+
font-size: 1.2em !important;
|
| 137 |
+
color: #deeedb !important;
|
| 138 |
+
font-weight: normal !important
|
| 139 |
+
}
|
| 140 |
+
#ownmodels > label > span {
|
| 141 |
+
color: #37e46f;
|
| 142 |
+
}
|
| 143 |
+
#ownloras > label > span {
|
| 144 |
+
color: #45b9ec;
|
| 145 |
+
}
|
| 146 |
+
#ownembeddings > label > span {
|
| 147 |
+
color: #f46ea2;
|
| 148 |
+
}
|
| 149 |
+
#ownmodels > label > textarea,
|
| 150 |
+
#ownloras > label > textarea,
|
| 151 |
+
#ownembeddings > label > textarea {
|
| 152 |
+
font-family: monospace;
|
| 153 |
+
font-size: 0.95em
|
| 154 |
+
}
|
| 155 |
+
#ownmodels > label > textarea {
|
| 156 |
+
color: #a7d0b4;
|
| 157 |
+
}
|
| 158 |
+
#ownloras > label > textarea {
|
| 159 |
+
color: #9bc5d9;
|
| 160 |
+
}
|
| 161 |
+
#ownembeddings > label > textarea {
|
| 162 |
+
color: #dcbfcb;
|
| 163 |
+
}
|
| 164 |
+
#filemanager {
|
| 165 |
+
height: max-content;
|
| 166 |
+
}
|
| 167 |
+
.current_models_files {
|
| 168 |
+
margin-bottom: 30px!important;
|
| 169 |
+
color: #eedbdb !important;
|
| 170 |
+
}
|
| 171 |
+
#files_checkbox {
|
| 172 |
+
width: max-content;
|
| 173 |
+
display: grid;
|
| 174 |
+
grid-template-columns: repeat(3, 1fr);
|
| 175 |
+
grid-gap: 35px;
|
| 176 |
+
grid-row-gap: 18px;
|
| 177 |
+
}
|
| 178 |
+
.filecheckbox input {
|
| 179 |
+
margin-right: 6px;
|
| 180 |
+
border: var(--checkbox-border-width) solid var(--checkbox-border-color) !important;
|
| 181 |
+
background-color: var(--checkbox-background-color) !important;
|
| 182 |
+
line-height: var(--line-sm) !important;
|
| 183 |
+
}
|
| 184 |
+
.filecheckbox input:checked {
|
| 185 |
+
border-color: #f47373 !important;
|
| 186 |
+
background-image: #de2f2f !important;
|
| 187 |
+
background-color: #de2f2f !important;
|
| 188 |
+
}
|
| 189 |
+
.filecheckbox span:hover {
|
| 190 |
+
color: #ff9494
|
| 191 |
+
}
|
| 192 |
+
.filebuttons {
|
| 193 |
+
display: flex;
|
| 194 |
+
flex-direction: row;
|
| 195 |
+
flex-wrap: wrap;
|
| 196 |
+
align-content: center;
|
| 197 |
+
align-items: center;
|
| 198 |
+
justify-content: center;
|
| 199 |
+
margin-top: 15px;
|
| 200 |
+
padding-top: 15px;
|
| 201 |
+
border-top: 2px solid #afafaf17;
|
| 202 |
+
}
|
| 203 |
+
#delete_files_button,
|
| 204 |
+
#refresh_files_button {
|
| 205 |
+
width: 40px;
|
| 206 |
+
height: 40px;
|
| 207 |
+
border: 1px solid var(--button-secondary-border-color);
|
| 208 |
+
margin: 0 50px;
|
| 209 |
+
cursor: pointer;
|
| 210 |
+
background-color: transparent;
|
| 211 |
+
background-position: 50%;
|
| 212 |
+
background-repeat: no-repeat
|
| 213 |
+
}
|
| 214 |
+
#refresh_files_button {
|
| 215 |
+
background-image: url("data:image/svg+xml,%3Csvg id='refresh' xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 36 36'%3E%3Cpath fill='%23fff' opacity='.5' d='m3.33,33v-2.81h6.09l-.7-.56c-2-1.59-3.45-3.33-4.36-5.2-.91-1.88-1.36-3.97-1.36-6.28,0-3.31.98-6.29,2.93-8.93,1.95-2.64,4.52-4.46,7.71-5.46v2.91c-2.34.91-4.23,2.41-5.67,4.52-1.44,2.11-2.16,4.43-2.16,6.96,0,1.97.37,3.68,1.1,5.13.73,1.45,1.73,2.71,2.98,3.77l1.41.98v-5.81h2.81v10.78H3.33Zm19.08-.7v-2.95c2.37-.91,4.27-2.41,5.67-4.52,1.41-2.11,2.11-4.43,2.11-6.96,0-1.5-.37-3.02-1.1-4.57-.73-1.55-1.7-2.91-2.88-4.1l-1.36-1.22v5.81h-2.81V3h10.78v2.81h-6.14l.7.66c1.88,1.75,3.28,3.63,4.22,5.63.94,2,1.41,3.92,1.41,5.77,0,3.31-.97,6.3-2.91,8.95-1.94,2.66-4.5,4.48-7.69,5.48Z'%3E%3C/path%3E%3C/svg%3E");
|
| 216 |
+
}
|
| 217 |
+
#refresh_files_button:hover {
|
| 218 |
+
background-color: #00000078;
|
| 219 |
+
background-image: url("data:image/svg+xml,%3Csvg id='refresh' xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 36 36'%3E%3Cpath fill='%23fff' opacity='.7' d='m3.33,33v-2.81h6.09l-.7-.56c-2-1.59-3.45-3.33-4.36-5.2-.91-1.88-1.36-3.97-1.36-6.28,0-3.31.98-6.29,2.93-8.93,1.95-2.64,4.52-4.46,7.71-5.46v2.91c-2.34.91-4.23,2.41-5.67,4.52-1.44,2.11-2.16,4.43-2.16,6.96,0,1.97.37,3.68,1.1,5.13.73,1.45,1.73,2.71,2.98,3.77l1.41.98v-5.81h2.81v10.78H3.33Zm19.08-.7v-2.95c2.37-.91,4.27-2.41,5.67-4.52,1.41-2.11,2.11-4.43,2.11-6.96,0-1.5-.37-3.02-1.1-4.57-.73-1.55-1.7-2.91-2.88-4.1l-1.36-1.22v5.81h-2.81V3h10.78v2.81h-6.14l.7.66c1.88,1.75,3.28,3.63,4.22,5.63.94,2,1.41,3.92,1.41,5.77,0,3.31-.97,6.3-2.91,8.95-1.94,2.66-4.5,4.48-7.69,5.48Z'%3E%3C/path%3E%3C/svg%3E");
|
| 220 |
+
}
|
| 221 |
+
#refresh_files_button:active {
|
| 222 |
+
background-color: #00000078;
|
| 223 |
+
background-image: url("data:image/svg+xml,%3Csvg id='refresh' xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 36 36'%3E%3Cpath fill='%23fff' opacity='.85' d='m3.33,33v-2.81h6.09l-.7-.56c-2-1.59-3.45-3.33-4.36-5.2-.91-1.88-1.36-3.97-1.36-6.28,0-3.31.98-6.29,2.93-8.93,1.95-2.64,4.52-4.46,7.71-5.46v2.91c-2.34.91-4.23,2.41-5.67,4.52-1.44,2.11-2.16,4.43-2.16,6.96,0,1.97.37,3.68,1.1,5.13.73,1.45,1.73,2.71,2.98,3.77l1.41.98v-5.81h2.81v10.78H3.33Zm19.08-.7v-2.95c2.37-.91,4.27-2.41,5.67-4.52,1.41-2.11,2.11-4.43,2.11-6.96,0-1.5-.37-3.02-1.1-4.57-.73-1.55-1.7-2.91-2.88-4.1l-1.36-1.22v5.81h-2.81V3h10.78v2.81h-6.14l.7.66c1.88,1.75,3.28,3.63,4.22,5.63.94,2,1.41,3.92,1.41,5.77,0,3.31-.97,6.3-2.91,8.95-1.94,2.66-4.5,4.48-7.69,5.48Z'%3E%3C/path%3E%3C/svg%3E");
|
| 224 |
+
transform: rotate(90deg)
|
| 225 |
+
}
|
| 226 |
+
#delete_files_button {
|
| 227 |
+
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='36' viewBox='0 0 32 36'%3E%3Cpath d='m10.05,27.05l5.95-6.05,6,6.05,2.35-2.4-5.95-6.05,5.95-6.05-2.35-2.4-6,6.05-5.95-6.05-2.4,2.4,6,6.05-6,6.05,2.4,2.4Zm-5,8.95c-.8,0-1.5-.3-2.1-.9s-.9-1.3-.9-2.1V4.5H0V1.5h9.4V0h13.2v1.5h9.4v3h-2.05v28.5c0,.8-.3,1.5-.9,2.1s-1.3.9-2.1.9H5.05ZM26.95,4.5H5.05v28.5h21.9V4.5Zm-21.9,0v28.5V4.5Z' opacity='.5' fill='%23fff'/%3E%3C/svg%3E");
|
| 228 |
+
background-size: 62%;
|
| 229 |
+
}
|
| 230 |
+
#delete_files_button:hover {
|
| 231 |
+
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='36' viewBox='0 0 32 36'%3E%3Cpath d='m10.05,27.05l5.95-6.05,6,6.05,2.35-2.4-5.95-6.05,5.95-6.05-2.35-2.4-6,6.05-5.95-6.05-2.4,2.4,6,6.05-6,6.05,2.4,2.4Zm-5,8.95c-.8,0-1.5-.3-2.1-.9s-.9-1.3-.9-2.1V4.5H0V1.5h9.4V0h13.2v1.5h9.4v3h-2.05v28.5c0,.8-.3,1.5-.9,2.1s-1.3.9-2.1.9H5.05ZM26.95,4.5H5.05v28.5h21.9V4.5Zm-21.9,0v28.5V4.5Z' opacity='.7' fill='%23ff2727'/%3E%3C/svg%3E");
|
| 232 |
+
background-size: 62%;
|
| 233 |
+
}
|
| 234 |
+
#delete_files_button:active {
|
| 235 |
+
background-color: #00000078;
|
| 236 |
+
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='36' viewBox='0 0 32 36'%3E%3Cpath d='m10.05,27.05l5.95-6.05,6,6.05,2.35-2.4-5.95-6.05,5.95-6.05-2.35-2.4-6,6.05-5.95-6.05-2.4,2.4,6,6.05-6,6.05,2.4,2.4Zm-5,8.95c-.8,0-1.5-.3-2.1-.9s-.9-1.3-.9-2.1V4.5H0V1.5h9.4V0h13.2v1.5h9.4v3h-2.05v28.5c0,.8-.3,1.5-.9,2.1s-1.3.9-2.1.9H5.05ZM26.95,4.5H5.05v28.5h21.9V4.5Zm-21.9,0v28.5V4.5Z' opacity='1' fill='%23ff2727'/%3E%3C/svg%3E");
|
| 237 |
+
background-size: 62%;
|
| 238 |
+
}
|
| 239 |
+
.models_porgress_loader {
|
| 240 |
+
width: 70%;
|
| 241 |
+
height: 8px;
|
| 242 |
+
display: block;
|
| 243 |
+
background: var(--block-label-border-color);
|
| 244 |
+
position: relative;
|
| 245 |
+
top: 0px;
|
| 246 |
+
overflow: hidden;
|
| 247 |
+
margin: 0 auto;
|
| 248 |
+
}
|
| 249 |
+
.models_porgress_loader::after {
|
| 250 |
+
content: '';
|
| 251 |
+
width: 0%;
|
| 252 |
+
height: 8px;
|
| 253 |
+
background-color: #ffffff2e;
|
| 254 |
+
background-image: linear-gradient(45deg, rgba(0, 0, 0, .25) 25%, transparent 25%, transparent 50%, rgba(0, 0, 0, 0.25) 50%, rgba(0, 0, 0, 0.25) 75%, transparent 75%, transparent);
|
| 255 |
+
background-size: 15px 15px;
|
| 256 |
+
position: absolute;
|
| 257 |
+
top: 0;
|
| 258 |
+
left: 0;
|
| 259 |
+
box-sizing: border-box;
|
| 260 |
+
animation: models_progress_bar_anim 10s cubic-bezier(0.45, 0.05, 0.55, 0.95) infinite;
|
| 261 |
+
}
|
| 262 |
+
@keyframes models_progress_bar_anim {
|
| 263 |
+
0% {
|
| 264 |
+
width: 0;
|
| 265 |
+
}
|
| 266 |
+
100% {
|
| 267 |
+
width: 100%;
|
| 268 |
+
}
|
| 269 |
+
}
|
| 270 |
+
#downloads_result_text,
|
| 271 |
+
#downloads_start_text {
|
| 272 |
+
margin: 32px auto;
|
| 273 |
+
width: fit-content;
|
| 274 |
+
top: 100px;
|
| 275 |
+
font-size: 1.4em;
|
| 276 |
+
}
|
| 277 |
+
#downloads_start_text {
|
| 278 |
+
color: #81d0fb !important
|
| 279 |
+
}
|
| 280 |
+
#downloads_result_text > span {
|
| 281 |
+
display: block;
|
| 282 |
+
text-align: center;
|
| 283 |
+
}
|
| 284 |
+
#downloads_result_text > span.finish_dl_func {
|
| 285 |
+
color: #99fb99 !important
|
| 286 |
+
}
|
| 287 |
+
#downloads_result_text > span.dl_progress_info {
|
| 288 |
+
font-size: 0.7em!important;
|
| 289 |
+
margin-top: 10px;
|
| 290 |
+
}
|
| 291 |
+
#tab_models_list #colab_model_list.colab_model_list {
|
| 292 |
+
background: transparent !important;
|
| 293 |
+
background-image: none !important;
|
| 294 |
+
}
|
| 295 |
+
.request_new_models a {
|
| 296 |
+
color: var(--link-text-color) !important;
|
| 297 |
+
text-decoration: underline dashed !important
|
| 298 |
+
}
|
| 299 |
+
.request_new_models a:hover {
|
| 300 |
+
color: var(--link-text-color-hover) !important;
|
| 301 |
+
text-decoration: underline solid !important
|
| 302 |
+
}
|