From b5e371103801621c6cb7e1290cbb0b6be505e428 Mon Sep 17 00:00:00 2001 From: JeLuF Date: Sun, 6 Aug 2023 21:47:39 +0200 Subject: [PATCH] Use modifiers card, resize thumbs --- ui/index.html | 9 ++++++ ui/media/js/auto-save.js | 1 + ui/media/js/main.js | 64 +++++++++++++++++++++++++--------------- ui/media/js/utils.js | 18 +++++++++++ 4 files changed, 68 insertions(+), 24 deletions(-) diff --git a/ui/index.html b/ui/index.html index f69efd0b..d0c53041 100644 --- a/ui/index.html +++ b/ui/index.html @@ -681,6 +681,15 @@ + +  
diff --git a/ui/media/js/auto-save.js b/ui/media/js/auto-save.js index 5ada13d5..bcfd4bc6 100644 --- a/ui/media/js/auto-save.js +++ b/ui/media/js/auto-save.js @@ -56,6 +56,7 @@ const SETTINGS_IDS_LIST = [ "tree_toggle", "json_toggle", "extract_lora_from_prompt", + "embedding-card-size-selector", ] const IGNORE_BY_DEFAULT = ["prompt"] diff --git a/ui/media/js/main.js b/ui/media/js/main.js index 30ed6012..b440e794 100644 --- a/ui/media/js/main.js +++ b/ui/media/js/main.js @@ -141,6 +141,7 @@ let embeddingsDialogCloseBtn = embeddingsDialog.querySelector("#embeddings-dialo let embeddingsSearchBox = document.querySelector("#embeddings-search-box") let embeddingsList = document.querySelector("#embeddings-list") let embeddingsModeField = document.querySelector("#embeddings-mode") +let embeddingsCardSizeSelector = document.querySelector("#embedding-card-size-selector") let positiveEmbeddingText = document.querySelector("#positive-embedding-text") let negativeEmbeddingText = document.querySelector("#negative-embedding-text") @@ -684,6 +685,7 @@ function onMakeSimilarClick(req, img) { createTask(newTaskRequest) } +// gets a flat list of all models of a certain type, ignoring directories function getAllModelNames(type) { function f(tree) { if (tree == undefined) { @@ -808,7 +810,6 @@ useAsThumbSaveBtn.addEventListener("click", (e) => { }) }) - function enqueueImageVariationTask(req, img, reqDiff) { const imageSeed = img.getAttribute("data-seed") @@ -2645,43 +2646,50 @@ let icl = [] function updateEmbeddingsList(filter = "") { function html(model, iconlist = [], prefix = "", filter = "") { filter = filter.toLowerCase() - let toplevel = "" - let folders = "" - console.log(iconlist) + let toplevel = document.createElement("div") + let folders = document.createElement("div") let embIcon = Object.assign({}, ...iconlist.map( x=> ({[x.toLowerCase().split('.').slice(0,-1).join('.')]:x}))) - console.log(embIcon) let profileName = profileNameField.value model?.forEach((m) => { if (typeof m == "string") { let token=m.toLowerCase() if (token.search(filter) != -1) { - let img = '/media/images/noimg.png' - if (token in embIcon) { - img = `/bucket/${profileName}/embeddings/${embIcon[token]}` - } + let button if (iconlist.length==0) { - img="" + button = document.createElement("button") + button.innerText="m" } else { - img=`
` + let img = '/media/images/noimg.png' + if (token in embIcon) { + img = `/bucket/${profileName}/embeddings/${embIcon[token]}` + } + button = createModifierCard(m, [img,img], true) } - toplevel += ` ` + button.dataset["embedding"] = m + button.addEventListener("click", onButtonClick) + toplevel.appendChild(button) } } else { let subdir = html(m[1], iconlist, prefix + m[0] + "/", filter) - if (subdir != "") { - folders += - `

${prefix}${m[0]}

` + - subdir + - "
" + if (typeof(subdir) == "object") { + let div1 = document.createElement("div") + let div2 = document.createElement("div") + div1.classList.add("collapsible-content") + div1.classList.add("embedding-category") + div1.appendChild(subdir) + div2.replaceChildren(htmlToElement(`

${prefix}${m[0]}

`), div1) + folders.appendChild(div2) } } }) - return toplevel + folders + let result = document.createElement("div") + result.replaceChildren(toplevel, htmlToElement('
'), folders) + return result } function onButtonClick(e) { - let text = e.target.closest("button").dataset["embedding"] + let text = e.target.closest("[data-embedding]").dataset["embedding"] const insertIntoNegative = e.shiftKey || positiveEmbeddingText.classList.contains("displayNone") if (embeddingsModeField.value == "insert") { @@ -2717,7 +2725,7 @@ function updateEmbeddingsList(filter = "") { ` // Remove after fixing https://github.com/huggingface/diffusers/issues/3922 - let warning = "" + let warning = "
" if (vramUsageLevelField.value == "low") { warning = `
@@ -2731,14 +2739,12 @@ function updateEmbeddingsList(filter = "") { .then(response => response.status==200 ? response.json(): []) .then(async function(iconlist) { - embeddingsList.innerHTML = warning + html(modelsOptions.embeddings, iconlist, "", filter) - embeddingsList.querySelectorAll("button").forEach((b) => { - b.addEventListener("click", onButtonClick) - }) + embeddingsList.replaceChildren(htmlToElement(warning), html(modelsOptions.embeddings, iconlist, "", filter)) createCollapsibles(embeddingsList) if (filter != "") { embeddingsExpandAll() } + resizeModifierCards(embeddingsCardSizeSelector.value) }) } @@ -2747,23 +2753,33 @@ function showEmbeddingDialog() { embeddingsSearchBox.value = "" embeddingsDialog.showModal() } + embeddingsButton.addEventListener("click", () => { positiveEmbeddingText.classList.remove("displayNone") negativeEmbeddingText.classList.add("displayNone") showEmbeddingDialog() }) + negativeEmbeddingsButton.addEventListener("click", () => { positiveEmbeddingText.classList.add("displayNone") negativeEmbeddingText.classList.remove("displayNone") showEmbeddingDialog() }) + embeddingsDialogCloseBtn.addEventListener("click", (e) => { embeddingsDialog.close() }) + embeddingsSearchBox.addEventListener("input", (e) => { updateEmbeddingsList(embeddingsSearchBox.value) }) +embeddingsCardSizeSelector.addEventListener("change", (e) => { + resizeModifierCards(embeddingsCardSizeSelector.value) +}) + + + modalDialogCloseOnBackdropClick(embeddingsDialog) makeDialogDraggable(embeddingsDialog) diff --git a/ui/media/js/utils.js b/ui/media/js/utils.js index 673ba3dd..8fef9450 100644 --- a/ui/media/js/utils.js +++ b/ui/media/js/utils.js @@ -1097,6 +1097,14 @@ async function deleteKeys(keyToDelete) { } } +/** + * @param {String} Data URL of the image + * @param {Integer} Top left X-coordinate of the crop area + * @param {Integer} Top left Y-coordinate of the crop area + * @param {Integer} Width of the crop area + * @param {Integer} Height of the crop area + * @return {String} + */ function cropImageDataUrl(dataUrl, x, y, width, height) { return new Promise((resolve, reject) => { const image = new Image() @@ -1120,6 +1128,16 @@ function cropImageDataUrl(dataUrl, x, y, width, height) { }) } +/** + * @param {String} HTML representing a single element + * @return {Element} + */ +function htmlToElement(html) { + var template = document.createElement('template'); + html = html.trim(); // Never return a text node of whitespace as the result + template.innerHTML = html; + return template.content.firstChild; +} function modalDialogCloseOnBackdropClick(dialog) { dialog.addEventListener('mousedown', function (event) {