Use modifiers card, resize thumbs

This commit is contained in:
JeLuF 2023-08-06 21:47:39 +02:00
parent 7497870455
commit b5e3711038
4 changed files with 68 additions and 24 deletions

View File

@ -681,6 +681,15 @@
</button> </button>
<i class="fa-solid fa-magnifying-glass"></i> <i class="fa-solid fa-magnifying-glass"></i>
<input id="embeddings-search-box" type="text" spellcheck="false" autocomplete="off" placeholder="Search..."> <input id="embeddings-search-box" type="text" spellcheck="false" autocomplete="off" placeholder="Search...">
<label for="embedding-card-size-selector"><small>Thumbnail Size:</small></label>
<select id="embedding-card-size-selector" name="embedding-card-size-selector">
<option value="-2">0</option>
<option value="-1">1</option>
<option value="0">2</option>
<option value="1" selected>3</option>
<option value="2">4</option>
<option value="3">5</option>
</select>
<span style="float:right;"><label>Mode:</label>&nbsp;<select id="embeddings-mode"><option value="insert">Insert at cursor position</option><option value="append">Append at the end</option></select> <span style="float:right;"><label>Mode:</label>&nbsp;<select id="embeddings-mode"><option value="insert">Insert at cursor position</option><option value="append">Append at the end</option></select>
</div> </div>
<div id="embeddings-list"> <div id="embeddings-list">

View File

@ -56,6 +56,7 @@ const SETTINGS_IDS_LIST = [
"tree_toggle", "tree_toggle",
"json_toggle", "json_toggle",
"extract_lora_from_prompt", "extract_lora_from_prompt",
"embedding-card-size-selector",
] ]
const IGNORE_BY_DEFAULT = ["prompt"] const IGNORE_BY_DEFAULT = ["prompt"]

View File

@ -141,6 +141,7 @@ let embeddingsDialogCloseBtn = embeddingsDialog.querySelector("#embeddings-dialo
let embeddingsSearchBox = document.querySelector("#embeddings-search-box") let embeddingsSearchBox = document.querySelector("#embeddings-search-box")
let embeddingsList = document.querySelector("#embeddings-list") let embeddingsList = document.querySelector("#embeddings-list")
let embeddingsModeField = document.querySelector("#embeddings-mode") let embeddingsModeField = document.querySelector("#embeddings-mode")
let embeddingsCardSizeSelector = document.querySelector("#embedding-card-size-selector")
let positiveEmbeddingText = document.querySelector("#positive-embedding-text") let positiveEmbeddingText = document.querySelector("#positive-embedding-text")
let negativeEmbeddingText = document.querySelector("#negative-embedding-text") let negativeEmbeddingText = document.querySelector("#negative-embedding-text")
@ -684,6 +685,7 @@ function onMakeSimilarClick(req, img) {
createTask(newTaskRequest) createTask(newTaskRequest)
} }
// gets a flat list of all models of a certain type, ignoring directories
function getAllModelNames(type) { function getAllModelNames(type) {
function f(tree) { function f(tree) {
if (tree == undefined) { if (tree == undefined) {
@ -808,7 +810,6 @@ useAsThumbSaveBtn.addEventListener("click", (e) => {
}) })
}) })
function enqueueImageVariationTask(req, img, reqDiff) { function enqueueImageVariationTask(req, img, reqDiff) {
const imageSeed = img.getAttribute("data-seed") const imageSeed = img.getAttribute("data-seed")
@ -2645,43 +2646,50 @@ let icl = []
function updateEmbeddingsList(filter = "") { function updateEmbeddingsList(filter = "") {
function html(model, iconlist = [], prefix = "", filter = "") { function html(model, iconlist = [], prefix = "", filter = "") {
filter = filter.toLowerCase() filter = filter.toLowerCase()
let toplevel = "" let toplevel = document.createElement("div")
let folders = "" let folders = document.createElement("div")
console.log(iconlist)
let embIcon = Object.assign({}, ...iconlist.map( x=> ({[x.toLowerCase().split('.').slice(0,-1).join('.')]:x}))) let embIcon = Object.assign({}, ...iconlist.map( x=> ({[x.toLowerCase().split('.').slice(0,-1).join('.')]:x})))
console.log(embIcon)
let profileName = profileNameField.value let profileName = profileNameField.value
model?.forEach((m) => { model?.forEach((m) => {
if (typeof m == "string") { if (typeof m == "string") {
let token=m.toLowerCase() let token=m.toLowerCase()
if (token.search(filter) != -1) { if (token.search(filter) != -1) {
let img = '/media/images/noimg.png' let button
if (token in embIcon) {
img = `/bucket/${profileName}/embeddings/${embIcon[token]}`
}
if (iconlist.length==0) { if (iconlist.length==0) {
img="" button = document.createElement("button")
button.innerText="m"
} else { } else {
img=`<img src="${img}" height="128" width="128"><br>` let img = '/media/images/noimg.png'
if (token in embIcon) {
img = `/bucket/${profileName}/embeddings/${embIcon[token]}`
}
button = createModifierCard(m, [img,img], true)
} }
toplevel += `<button data-embedding="${m}">${img}${m}</button> ` button.dataset["embedding"] = m
button.addEventListener("click", onButtonClick)
toplevel.appendChild(button)
} }
} else { } else {
let subdir = html(m[1], iconlist, prefix + m[0] + "/", filter) let subdir = html(m[1], iconlist, prefix + m[0] + "/", filter)
if (subdir != "") { if (typeof(subdir) == "object") {
folders += let div1 = document.createElement("div")
`<div class="embedding-category"><h4 class="collapsible">${prefix}${m[0]}</h4><div class="collapsible-content">` + let div2 = document.createElement("div")
subdir + div1.classList.add("collapsible-content")
"</div></div>" div1.classList.add("embedding-category")
div1.appendChild(subdir)
div2.replaceChildren(htmlToElement(`<h4 class="collapsible">${prefix}${m[0]}</h4>`), div1)
folders.appendChild(div2)
} }
} }
}) })
return toplevel + folders let result = document.createElement("div")
result.replaceChildren(toplevel, htmlToElement('<br style="clear: both;">'), folders)
return result
} }
function onButtonClick(e) { 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") const insertIntoNegative = e.shiftKey || positiveEmbeddingText.classList.contains("displayNone")
if (embeddingsModeField.value == "insert") { if (embeddingsModeField.value == "insert") {
@ -2717,7 +2725,7 @@ function updateEmbeddingsList(filter = "") {
` `
// Remove after fixing https://github.com/huggingface/diffusers/issues/3922 // Remove after fixing https://github.com/huggingface/diffusers/issues/3922
let warning = "" let warning = "<div></div>"
if (vramUsageLevelField.value == "low") { if (vramUsageLevelField.value == "low") {
warning = ` warning = `
<div style="border-color: var(--accent-color); border-width: 4px; border-radius: 1em; border-style: solid; background: black; text-align: center; padding: 1em; margin: 1em; "> <div style="border-color: var(--accent-color); border-width: 4px; border-radius: 1em; border-style: solid; background: black; text-align: center; padding: 1em; margin: 1em; ">
@ -2731,14 +2739,12 @@ function updateEmbeddingsList(filter = "") {
.then(response => response.status==200 ? response.json(): []) .then(response => response.status==200 ? response.json(): [])
.then(async function(iconlist) { .then(async function(iconlist) {
embeddingsList.innerHTML = warning + html(modelsOptions.embeddings, iconlist, "", filter) embeddingsList.replaceChildren(htmlToElement(warning), html(modelsOptions.embeddings, iconlist, "", filter))
embeddingsList.querySelectorAll("button").forEach((b) => {
b.addEventListener("click", onButtonClick)
})
createCollapsibles(embeddingsList) createCollapsibles(embeddingsList)
if (filter != "") { if (filter != "") {
embeddingsExpandAll() embeddingsExpandAll()
} }
resizeModifierCards(embeddingsCardSizeSelector.value)
}) })
} }
@ -2747,23 +2753,33 @@ function showEmbeddingDialog() {
embeddingsSearchBox.value = "" embeddingsSearchBox.value = ""
embeddingsDialog.showModal() embeddingsDialog.showModal()
} }
embeddingsButton.addEventListener("click", () => { embeddingsButton.addEventListener("click", () => {
positiveEmbeddingText.classList.remove("displayNone") positiveEmbeddingText.classList.remove("displayNone")
negativeEmbeddingText.classList.add("displayNone") negativeEmbeddingText.classList.add("displayNone")
showEmbeddingDialog() showEmbeddingDialog()
}) })
negativeEmbeddingsButton.addEventListener("click", () => { negativeEmbeddingsButton.addEventListener("click", () => {
positiveEmbeddingText.classList.add("displayNone") positiveEmbeddingText.classList.add("displayNone")
negativeEmbeddingText.classList.remove("displayNone") negativeEmbeddingText.classList.remove("displayNone")
showEmbeddingDialog() showEmbeddingDialog()
}) })
embeddingsDialogCloseBtn.addEventListener("click", (e) => { embeddingsDialogCloseBtn.addEventListener("click", (e) => {
embeddingsDialog.close() embeddingsDialog.close()
}) })
embeddingsSearchBox.addEventListener("input", (e) => { embeddingsSearchBox.addEventListener("input", (e) => {
updateEmbeddingsList(embeddingsSearchBox.value) updateEmbeddingsList(embeddingsSearchBox.value)
}) })
embeddingsCardSizeSelector.addEventListener("change", (e) => {
resizeModifierCards(embeddingsCardSizeSelector.value)
})
modalDialogCloseOnBackdropClick(embeddingsDialog) modalDialogCloseOnBackdropClick(embeddingsDialog)
makeDialogDraggable(embeddingsDialog) makeDialogDraggable(embeddingsDialog)

View File

@ -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) { function cropImageDataUrl(dataUrl, x, y, width, height) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const image = new Image() 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) { function modalDialogCloseOnBackdropClick(dialog) {
dialog.addEventListener('mousedown', function (event) { dialog.addEventListener('mousedown', function (event) {