File size: 14,997 Bytes
b1c669d 7e8922a b1c669d 7e8922a b1c669d 7e8922a b1c669d 7e8922a b1c669d 7e8922a b1c669d 7e8922a b1c669d 7e8922a b1c669d 7e8922a b1c669d 7e8922a b1c669d 7e8922a b1c669d 7e8922a b1c669d 7e8922a b1c669d 7e8922a b1c669d 7e8922a |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 |
document.addEventListener('DOMContentLoaded', () => {
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.addedNodes) {
mutation.addedNodes.forEach((node) => {
if (node.id === 'tab_models_list') {
// запуск кода после загрузки элементов
Array.from(document.querySelectorAll('#tabs > div.tab-nav > button')).find(button => button.textContent.includes('модели')).click();
// получение инфы по кд о свободном пространтсве из скрытого уродского текстбокса в красивый элементик в шапочке
const freespacetextarea = document.querySelector("#free_space_area > label > textarea");
const frespace_out = document.querySelector("#frespace_out");
let prevValue = freespacetextarea.value;
setInterval(function () {
const currentValue = freespacetextarea.value;
if (currentValue !== prevValue) {
frespace_out.innerHTML = `${currentValue}`;
prevValue = currentValue;
}
}, 100);
// скликивание реальной, но скрытой уродской кнопки с обработчиком проверки свободного места при нажатии на фейковую но красивую кнопочку
const freespace_getButton = document.querySelector("#freespace_get");
const free_spaceOrigButton = document.querySelector("#free_space_button");
freespace_getButton.addEventListener("click", function () {
free_spaceOrigButton.click();
});
// небольшой css-фикс
const ModelDLHeaderContainer = document.querySelector('.models_dl_header').closest('div').parentNode;
ModelDLHeaderContainer.style.cssText = `display: flex; flex-direction: row; align-items: center; justify-content: flex-start; flex-wrap: wrap;`;
document.querySelector('.models_dl_header').parentNode.marginRight = "50px";
// автоматическое скликивание скрытых кнопок для подгрузки установленных моделей и свободного места после загрузки дополнения через 1 сек
setTimeout(() => document.querySelector("#files_button").click(), 1000);
setTimeout(() => document.querySelector("#free_space_button").click(), 1000);
// файловый менеджер на тексбоксах
setTimeout(() => {
const filesArea = document.querySelector("#files_area > label > textarea");
const filesCheckbox = document.querySelector("#files_checkbox");
const deleteArea = document.querySelector("#delete_area > label > textarea");
// обновление списка чекбоксов с файлами при изменении списка путей в текстбоксе
function addCheckboxEventListeners() {
const delete_checkboxes = document.querySelectorAll("#files_checkbox > label > input[type=checkbox]");
delete_checkboxes.forEach(checkbox => {
checkbox.addEventListener("change", event => {
// отмеченные на удаление делаем красными и зачеркнутыми
const delete_span = event.target.parentElement.querySelector("span");
if (event.target.checked) {
delete_span.style.textDecoration = "line-through";
delete_span.style.color = "#ed5252";
} else {
delete_span.style.textDecoration = "none";
delete_span.style.color = "";
}
});
});
}
// функция для обновления чекбоксов с файлами почти в реальном времени
function updateCheckboxes() {
while (filesCheckbox.firstChild) {
filesCheckbox.removeChild(filesCheckbox.firstChild);
}
const fileNames = filesArea.value.split("\n").map(path => path.split("/").pop());
if (fileNames.length === 0 || (fileNames.length === 1 && fileNames[0] === "")) {
const message = document.createElement("p");
message.textContent = "ничего не найдено";
filesCheckbox.appendChild(message);
} else {
fileNames.forEach(fileName => {
const checkbox = document.createElement("input");
checkbox.type = "checkbox";
checkbox.id = fileName;
checkbox.addEventListener("change", event => {
if (event.target.checked) {
deleteArea.value += (deleteArea.value ? "\n" : "") + fileName;
} else {
const lines = deleteArea.value.split("\n");
const index = lines.indexOf(fileName);
if (index !== -1) {
lines.splice(index, 1);
deleteArea.value = lines.join("\n");
}
}
deleteArea.dispatchEvent(new Event('input')); // имитация ввода, это самая важная часть кода
});
const label = document.createElement("label");
label.htmlFor = fileName;
label.className = "filecheckbox";
const span = document.createElement("span");
span.textContent = fileName;
label.appendChild(checkbox);
label.appendChild(span);
filesCheckbox.appendChild(label);
});
}
deleteArea.value = deleteArea.value.trim();
deleteArea.dispatchEvent(new Event('input')); // имитация ввода, без этого не работает
addCheckboxEventListeners()
}
// наблюдаем за скрытым тексбоксом с путями до моделей и обновлям чекбоксы
const observer = new MutationObserver(updateCheckboxes);
observer.observe(filesArea, { characterData: true, subtree: true });
updateCheckboxes();
// скликивание реальной, но скрытой уродской кнопки с обработчиком обновления списка файлов при нажатии на фейковую но красивую кнопочку
const RefreshFilesButton = document.querySelector("#refresh_files_button");
RefreshFilesButton.addEventListener("click", () => {
document.querySelector("#files_button").click();
// задержки по 3 секунды необходимы, чтобы колаб одуплился
setTimeout(function () { updateCheckboxes(); }, 3000);
});
// при клике на фейковую кнопочку удаления - произойдет и обновление списка файлов с задержкой 3 сек
document.querySelector("#delete_button").addEventListener("click", function () {
setTimeout(function () {
document.querySelector("#files_button").click();
// задержки по 3 секунды необходимы, чтобы колаб одуплился
setTimeout(function () { updateCheckboxes(); }, 3000);
}, 3000);
});
// скликивание реальной, но скрытой уродской кнопки с обработчиком удаления моделей при нажатии на фейковую но красивую кнопочку
const OrigDelButton = document.querySelector("#delete_button");
const CustomDelButton = document.querySelector("#delete_files_button");
CustomDelButton.addEventListener("click", () => {
OrigDelButton.click();
});
// проверка выхлопа из функции загрузки в скрытом текстбоксе
setInterval(function () {
const DLresultText = document.querySelector("#downloads_result_text > span.finish_dl_func");
DLresultText.textContent = document.querySelector("#dlresultbox > label > textarea").value;
// функция скрытия прогрессбара
function checkDLresult(element, text) {
if (element.textContent.includes(text)) {
document.querySelector("div.downloads_result_container > div.models_porgress_loader").style.removeProperty("display");
document.querySelector("#downloads_start_text").style.removeProperty("display");
document.querySelector("#downloads_result_text > span.dl_progress_info").textContent = "чтобы новые файлы появились в выпадающем списке моделей, нужно обновить их список по соответсвующей кнопке";
}
}
// просто скрываем прогрессбар если в выхлопе есть фраза о завершении или предупреждение
checkDLresult(DLresultText, "заверш");
checkDLresult(DLresultText, "слишком");
checkDLresult(DLresultText, "ОШИБКА");
// раскрашиваем текст сообщения о результате выполнения, если что-то пошло не так
if (DLresultText) {
if (DLresultText.textContent.includes("слишком")) {
DLresultText.style.setProperty("color", "#ff4f8b", "important");
} else if (DLresultText.textContent.includes("ОШИБКА")) {
DLresultText.style.setProperty("color", "#de2f2f", "important");
} else if (DLresultText.textContent.includes("заверш")) {
DLresultText.style.setProperty("color", "#99fb99", "important");
}
}
}, 200);
// действия по клику на фейковую, но видимую кнопку для скачивания
document.querySelector("#general_download_button").addEventListener("click", function () {
// очистка текстбокса от выхлопа предыдущего выполнения
const resultTextareaDL = document.querySelector("#dlresultbox > label > textarea");
resultTextareaDL.value = "";
const resultClearOut = new Event("input", {bubbles: true}); // без этого не будет работать обноволение .value
resultTextareaDL.dispatchEvent(resultClearOut);
// делаем прогрессбар и место для результирующего текста видимыми
const DLprogressBar = document.querySelector("div.downloads_result_container > div.models_porgress_loader");
DLprogressBar.style.setProperty("display", "block", "important");
const DLresultText = document.querySelector("#downloads_result_text");
DLresultText.style.setProperty("display", "block", "important");
document.querySelector("#downloads_start_text").style.setProperty("display", "block", "important");
// скликивание реальных, но скрытых кнопок с обработчиками загрузки файлов по чекбоксам и кастомных ссылок при нажатии на фейковую но кнопочку
// формирование списка из кастомных ссылок
document.querySelector("#ownlinks_download_button").click();
setTimeout(function () {
// через 3 сек. добавим его к списку ссылок из чекбоксов и отправим на загрузку вместе
document.querySelector("#checkboxes_download_button").click();
}, 3000); // задержка, чтобы колаб успел одуплиться
});
// если кнопка загрузки уже нажата, запрещаем кликать еще раз пока функция загрузки не выплюнет ответ
const GendownloadButton = document.querySelector("#general_download_button");
const DLprogressBar = document.querySelector("div.downloads_result_container > div.models_porgress_loader");
if (GendownloadButton && DLprogressBar) {
const DLobserver = new MutationObserver(function (mutations) {
mutations.forEach(function (mutation) {
if (mutation.type === "attributes" && mutation.attributeName === "style") { // отслеживание видимости прогрессбара
if (DLprogressBar.style.display === "block") {
GendownloadButton.setAttribute("disabled", "disabled");
} else {
setTimeout(function () {
GendownloadButton.removeAttribute("disabled");
}, 3000); // не сразу даем кликнуть снова, а после ожидания 3 секунды, чтобы не закликали
}
}
});
});
DLobserver.observe(DLprogressBar, { attributes: true });
}
}, 9000); // запуск скриптов через 9 секунд после загрузки вебуи, чтобы успели отработать скрипты других дополнений и градио
}
});
}
});
});
observer.observe(document.body, { childList: true, subtree: true });
}); |