fix txt_fullfn

pull/827/head
Vladimir Mandic 2023-05-08 11:56:59 -04:00
parent 68b9b44015
commit 4d9fab4984
26 changed files with 1291 additions and 1268 deletions

3
.gitignore vendored
View File

@ -10,6 +10,9 @@ __pycache__
/webui-user.bat /webui-user.bat
/webui-user.sh /webui-user.sh
/javascript/themes.json /javascript/themes.json
node_modules
pnpm-lock.yaml
package-lock.json
venv venv
# all models and temp files # all models and temp files

View File

@ -31,7 +31,7 @@ Stuff to be added...
Stuff to be investigated... Stuff to be investigated...
- Torch Compile - Torch Compile
- `Torch-DirectML` - TXT2IMG: <https://github.com/vladmandic/automatic/discussions/814>
- `TensorRT` - `TensorRT`
- [Temporal Weighing](https://github.com/comfyanonymous/ComfyUI/discussions/473) - [Temporal Weighing](https://github.com/comfyanonymous/ComfyUI/discussions/473)

@ -1 +1 @@
Subproject commit 05d88c7809587c45fd97d136c717af1f21d06eda Subproject commit e535ea6aea2356a13da3e0452b92b3d68861f539

20
javascript/.eslintrc.json Normal file
View File

@ -0,0 +1,20 @@
{
"globals": {},
"env": {
"browser": true,
"commonjs": false,
"node": false,
"jquery": false,
"es2020": true
},
"parserOptions": { "ecmaVersion": 2020 },
"plugins": [],
"extends": ["eslint:recommended", "airbnb-base"],
"rules": {
"max-len": [1, 220, 3],
"camelcase":"off",
"no-unused-vars":"off",
"no-plusplus":"off",
"no-param-reassign":"off"
}
}

View File

@ -1,116 +1,107 @@
let currentWidth = null; let currentWidth = null;
let currentHeight = null; let currentHeight = null;
let arFrameTimeout = setTimeout(function(){},0); let arFrameTimeout = setTimeout(() => {}, 0);
function dimensionChange(e, is_width, is_height){ function dimensionChange(e, is_width, is_height) {
if (is_width) {
currentWidth = e.target.value * 1.0;
}
if (is_height) {
currentHeight = e.target.value * 1.0;
}
if(is_width){ const inImg2img = gradioApp().querySelector('#tab_img2img').style.display == 'block';
currentWidth = e.target.value*1.0
}
if(is_height){
currentHeight = e.target.value*1.0
}
var inImg2img = gradioApp().querySelector("#tab_img2img").style.display == "block"; if (!inImg2img) {
return;
}
if(!inImg2img){ let targetElement = null;
return;
}
var targetElement = null; const tabIndex = get_tab_index('mode_img2img');
if (tabIndex == 0) { // img2img
targetElement = gradioApp().querySelector('#img2img_image div[data-testid=image] img');
} else if (tabIndex == 1) { // Sketch
targetElement = gradioApp().querySelector('#img2img_sketch div[data-testid=image] img');
} else if (tabIndex == 2) { // Inpaint
targetElement = gradioApp().querySelector('#img2maskimg div[data-testid=image] img');
} else if (tabIndex == 3) { // Inpaint sketch
targetElement = gradioApp().querySelector('#inpaint_sketch div[data-testid=image] img');
}
var tabIndex = get_tab_index('mode_img2img') if (targetElement) {
if(tabIndex == 0){ // img2img let arPreviewRect = gradioApp().querySelector('#imageARPreview');
targetElement = gradioApp().querySelector('#img2img_image div[data-testid=image] img'); if (!arPreviewRect) {
} else if(tabIndex == 1){ //Sketch arPreviewRect = document.createElement('div');
targetElement = gradioApp().querySelector('#img2img_sketch div[data-testid=image] img'); arPreviewRect.id = 'imageARPreview';
} else if(tabIndex == 2){ // Inpaint gradioApp().appendChild(arPreviewRect);
targetElement = gradioApp().querySelector('#img2maskimg div[data-testid=image] img'); }
} else if(tabIndex == 3){ // Inpaint sketch
targetElement = gradioApp().querySelector('#inpaint_sketch div[data-testid=image] img');
}
const viewportOffset = targetElement.getBoundingClientRect();
if(targetElement){ viewportscale = Math.min(targetElement.clientWidth / targetElement.naturalWidth, targetElement.clientHeight / targetElement.naturalHeight);
var arPreviewRect = gradioApp().querySelector('#imageARPreview'); scaledx = targetElement.naturalWidth * viewportscale;
if(!arPreviewRect){ scaledy = targetElement.naturalHeight * viewportscale;
arPreviewRect = document.createElement('div')
arPreviewRect.id = "imageARPreview";
gradioApp().appendChild(arPreviewRect)
}
cleintRectTop = (viewportOffset.top + window.scrollY);
cleintRectLeft = (viewportOffset.left + window.scrollX);
cleintRectCentreY = cleintRectTop + (targetElement.clientHeight / 2);
cleintRectCentreX = cleintRectLeft + (targetElement.clientWidth / 2);
viewRectTop = cleintRectCentreY - (scaledy / 2);
viewRectLeft = cleintRectCentreX - (scaledx / 2);
arRectWidth = scaledx;
arRectHeight = scaledy;
var viewportOffset = targetElement.getBoundingClientRect(); arscale = Math.min(arRectWidth / currentWidth, arRectHeight / currentHeight);
arscaledx = currentWidth * arscale;
arscaledy = currentHeight * arscale;
viewportscale = Math.min( targetElement.clientWidth/targetElement.naturalWidth, targetElement.clientHeight/targetElement.naturalHeight ) arRectTop = cleintRectCentreY - (arscaledy / 2);
arRectLeft = cleintRectCentreX - (arscaledx / 2);
arRectWidth = arscaledx;
arRectHeight = arscaledy;
scaledx = targetElement.naturalWidth*viewportscale arPreviewRect.style.top = `${arRectTop}px`;
scaledy = targetElement.naturalHeight*viewportscale arPreviewRect.style.left = `${arRectLeft}px`;
arPreviewRect.style.width = `${arRectWidth}px`;
cleintRectTop = (viewportOffset.top+window.scrollY) arPreviewRect.style.height = `${arRectHeight}px`;
cleintRectLeft = (viewportOffset.left+window.scrollX)
cleintRectCentreY = cleintRectTop + (targetElement.clientHeight/2)
cleintRectCentreX = cleintRectLeft + (targetElement.clientWidth/2)
viewRectTop = cleintRectCentreY-(scaledy/2)
viewRectLeft = cleintRectCentreX-(scaledx/2)
arRectWidth = scaledx
arRectHeight = scaledy
arscale = Math.min( arRectWidth/currentWidth, arRectHeight/currentHeight )
arscaledx = currentWidth*arscale
arscaledy = currentHeight*arscale
arRectTop = cleintRectCentreY-(arscaledy/2)
arRectLeft = cleintRectCentreX-(arscaledx/2)
arRectWidth = arscaledx
arRectHeight = arscaledy
arPreviewRect.style.top = arRectTop+'px';
arPreviewRect.style.left = arRectLeft+'px';
arPreviewRect.style.width = arRectWidth+'px';
arPreviewRect.style.height = arRectHeight+'px';
clearTimeout(arFrameTimeout); clearTimeout(arFrameTimeout);
arFrameTimeout = setTimeout(function(){ arFrameTimeout = setTimeout(() => {
arPreviewRect.style.display = 'none'; arPreviewRect.style.display = 'none';
},2000); }, 2000);
arPreviewRect.style.display = 'block'; arPreviewRect.style.display = 'block';
}
}
} }
onUiUpdate(() => {
const arPreviewRect = gradioApp().querySelector('#imageARPreview');
if (arPreviewRect) {
arPreviewRect.style.display = 'none';
}
const tabImg2img = gradioApp().querySelector('#tab_img2img');
if (tabImg2img) {
const inImg2img = tabImg2img.style.display == 'block';
if (inImg2img) {
const inputs = gradioApp().querySelectorAll('input');
inputs.forEach((e) => {
const is_width = e.parentElement.id == 'img2img_width';
const is_height = e.parentElement.id == 'img2img_height';
onUiUpdate(function(){ if ((is_width || is_height) && !e.classList.contains('scrollwatch')) {
var arPreviewRect = gradioApp().querySelector('#imageARPreview'); e.addEventListener('input', (e) => { dimensionChange(e, is_width, is_height); });
if(arPreviewRect){ e.classList.add('scrollwatch');
arPreviewRect.style.display = 'none';
}
var tabImg2img = gradioApp().querySelector("#tab_img2img");
if (tabImg2img) {
var inImg2img = tabImg2img.style.display == "block";
if(inImg2img){
let inputs = gradioApp().querySelectorAll('input');
inputs.forEach(function(e){
var is_width = e.parentElement.id == "img2img_width"
var is_height = e.parentElement.id == "img2img_height"
if((is_width || is_height) && !e.classList.contains('scrollwatch')){
e.addEventListener('input', function(e){dimensionChange(e, is_width, is_height)} )
e.classList.add('scrollwatch')
}
if(is_width){
currentWidth = e.value*1.0
}
if(is_height){
currentHeight = e.value*1.0
}
})
} }
if (is_width) {
currentWidth = e.value * 1.0;
}
if (is_height) {
currentHeight = e.value * 1.0;
}
});
} }
}
}); });

View File

@ -1,178 +1,176 @@
contextMenuInit = function () {
let eventListenerApplied = false;
const menuSpecs = new Map();
contextMenuInit = function(){ const uid = function () {
let eventListenerApplied=false;
let menuSpecs = new Map();
const uid = function(){
return Date.now().toString(36) + Math.random().toString(36).substr(2); return Date.now().toString(36) + Math.random().toString(36).substr(2);
} };
function showContextMenu(event,element,menuEntries){ function showContextMenu(event, element, menuEntries) {
let posx = event.clientX + document.body.scrollLeft + document.documentElement.scrollLeft; const posx = event.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
let posy = event.clientY + document.body.scrollTop + document.documentElement.scrollTop; const posy = event.clientY + document.body.scrollTop + document.documentElement.scrollTop;
let oldMenu = gradioApp().querySelector('#context-menu') const oldMenu = gradioApp().querySelector('#context-menu');
if(oldMenu){ if (oldMenu) {
oldMenu.remove() oldMenu.remove();
} }
let tabButton = uiCurrentTab const tabButton = uiCurrentTab;
let baseStyle = window.getComputedStyle(tabButton) const baseStyle = window.getComputedStyle(tabButton);
const contextMenu = document.createElement('nav') const contextMenu = document.createElement('nav');
contextMenu.id = "context-menu" contextMenu.id = 'context-menu';
contextMenu.style.background = baseStyle.background contextMenu.style.background = baseStyle.background;
contextMenu.style.color = baseStyle.color contextMenu.style.color = baseStyle.color;
contextMenu.style.fontFamily = baseStyle.fontFamily contextMenu.style.fontFamily = baseStyle.fontFamily;
contextMenu.style.top = posy+'px' contextMenu.style.top = `${posy}px`;
contextMenu.style.left = posx+'px' contextMenu.style.left = `${posx}px`;
const contextMenuList = document.createElement('ul');
const contextMenuList = document.createElement('ul')
contextMenuList.className = 'context-menu-items'; contextMenuList.className = 'context-menu-items';
contextMenu.append(contextMenuList); contextMenu.append(contextMenuList);
menuEntries.forEach(function(entry){ menuEntries.forEach((entry) => {
let contextMenuEntry = document.createElement('a') const contextMenuEntry = document.createElement('a');
contextMenuEntry.innerHTML = entry['name'] contextMenuEntry.innerHTML = entry.name;
contextMenuEntry.addEventListener("click", function(e) { contextMenuEntry.addEventListener('click', (e) => {
entry['func'](); entry.func();
}) });
contextMenuList.append(contextMenuEntry); contextMenuList.append(contextMenuEntry);
});
}) gradioApp().appendChild(contextMenu);
gradioApp().appendChild(contextMenu) const menuWidth = contextMenu.offsetWidth + 4;
const menuHeight = contextMenu.offsetHeight + 4;
let menuWidth = contextMenu.offsetWidth + 4; const windowWidth = window.innerWidth;
let menuHeight = contextMenu.offsetHeight + 4; const windowHeight = window.innerHeight;
let windowWidth = window.innerWidth; if ((windowWidth - posx) < menuWidth) {
let windowHeight = window.innerHeight; contextMenu.style.left = `${windowWidth - menuWidth}px`;
if ( (windowWidth - posx) < menuWidth ) {
contextMenu.style.left = windowWidth - menuWidth + "px";
} }
if ( (windowHeight - posy) < menuHeight ) { if ((windowHeight - posy) < menuHeight) {
contextMenu.style.top = windowHeight - menuHeight + "px"; contextMenu.style.top = `${windowHeight - menuHeight}px`;
} }
} }
function appendContextMenuOption(targetElementSelector,entryName,entryFunction){ function appendContextMenuOption(targetElementSelector, entryName, entryFunction) {
currentItems = menuSpecs.get(targetElementSelector);
currentItems = menuSpecs.get(targetElementSelector) if (!currentItems) {
currentItems = [];
if(!currentItems){ menuSpecs.set(targetElementSelector, currentItems);
currentItems = []
menuSpecs.set(targetElementSelector,currentItems);
} }
let newItem = {'id':targetElementSelector+'_'+uid(), const newItem = {
'name':entryName, id: `${targetElementSelector}_${uid()}`,
'func':entryFunction, name: entryName,
'isNew':true} func: entryFunction,
isNew: true,
};
currentItems.push(newItem) currentItems.push(newItem);
return newItem['id'] return newItem.id;
} }
function removeContextMenuOption(uid){ function removeContextMenuOption(uid) {
menuSpecs.forEach(function(v,k) { menuSpecs.forEach((v, k) => {
let index = -1 let index = -1;
v.forEach(function(e,ei){if(e['id']==uid){index=ei}}) v.forEach((e, ei) => { if (e.id == uid) { index = ei; } });
if(index>=0){ if (index >= 0) {
v.splice(index, 1); v.splice(index, 1);
} }
}) });
} }
function addContextMenuEventListener(){ function addContextMenuEventListener() {
if(eventListenerApplied){ if (eventListenerApplied) {
return; return;
} }
gradioApp().addEventListener("click", function(e) { gradioApp().addEventListener('click', (e) => {
let source = e.composedPath()[0] const source = e.composedPath()[0];
if(source.id && source.id.indexOf('check_progress')>-1){ if (source.id && source.id.indexOf('check_progress') > -1) {
return return;
} }
let oldMenu = gradioApp().querySelector('#context-menu') const oldMenu = gradioApp().querySelector('#context-menu');
if(oldMenu){ if (oldMenu) {
oldMenu.remove() oldMenu.remove();
} }
}); });
gradioApp().addEventListener("contextmenu", function(e) { gradioApp().addEventListener('contextmenu', (e) => {
let oldMenu = gradioApp().querySelector('#context-menu') const oldMenu = gradioApp().querySelector('#context-menu');
if(oldMenu){ if (oldMenu) {
oldMenu.remove() oldMenu.remove();
} }
menuSpecs.forEach(function(v,k) { menuSpecs.forEach((v, k) => {
if(e.composedPath()[0].matches(k)){ if (e.composedPath()[0].matches(k)) {
showContextMenu(e,e.composedPath()[0],v) showContextMenu(e, e.composedPath()[0], v);
e.preventDefault() e.preventDefault();
return
} }
}) });
}); });
eventListenerApplied=true eventListenerApplied = true;
} }
return [appendContextMenuOption, removeContextMenuOption, addContextMenuEventListener] return [appendContextMenuOption, removeContextMenuOption, addContextMenuEventListener];
} };
initResponse = contextMenuInit(); initResponse = contextMenuInit();
appendContextMenuOption = initResponse[0]; appendContextMenuOption = initResponse[0];
removeContextMenuOption = initResponse[1]; removeContextMenuOption = initResponse[1];
addContextMenuEventListener = initResponse[2]; addContextMenuEventListener = initResponse[2];
(function(){ (function () {
//Start example Context Menu Items // Start example Context Menu Items
let generateOnRepeat = function(genbuttonid,interruptbuttonid){ const generateOnRepeat = function (genbuttonid, interruptbuttonid) {
let genbutton = gradioApp().querySelector(genbuttonid); const genbutton = gradioApp().querySelector(genbuttonid);
const busy = document.getElementById('progressbar')?.style.display == "block" const busy = document.getElementById('progressbar')?.style.display == 'block';
if(!busy){ if (!busy) {
genbutton.click(); genbutton.click();
} }
clearInterval(window.generateOnRepeatInterval) clearInterval(window.generateOnRepeatInterval);
window.generateOnRepeatInterval = setInterval(function(){ window.generateOnRepeatInterval = setInterval(
const busy = document.getElementById('progressbar')?.style.display == "block" () => {
if(!busy){ const busy = document.getElementById('progressbar')?.style.display == 'block';
genbutton.click(); if (!busy) {
} genbutton.click();
}
},
500,
);
};
appendContextMenuOption('#txt2img_generate', 'Generate forever', () => {
generateOnRepeat('#txt2img_generate', '#txt2img_interrupt');
});
appendContextMenuOption('#img2img_generate', 'Generate forever', () => {
generateOnRepeat('#img2img_generate', '#img2img_interrupt');
});
const cancelGenerateForever = function () {
clearInterval(window.generateOnRepeatInterval);
};
appendContextMenuOption('#txt2img_interrupt', 'Cancel generate forever', cancelGenerateForever);
appendContextMenuOption('#txt2img_generate', 'Cancel generate forever', cancelGenerateForever);
appendContextMenuOption('#img2img_interrupt', 'Cancel generate forever', cancelGenerateForever);
appendContextMenuOption('#img2img_generate', 'Cancel generate forever', cancelGenerateForever);
appendContextMenuOption(
'#roll',
'Roll three',
() => {
const rollbutton = get_uiCurrentTabContent().querySelector('#roll');
setTimeout(() => { rollbutton.click(); }, 100);
setTimeout(() => { rollbutton.click(); }, 200);
setTimeout(() => { rollbutton.click(); }, 300);
}, },
500) );
} }());
// End example Context Menu Items
appendContextMenuOption('#txt2img_generate','Generate forever',function(){ onUiUpdate(() => {
generateOnRepeat('#txt2img_generate','#txt2img_interrupt'); addContextMenuEventListener();
})
appendContextMenuOption('#img2img_generate','Generate forever',function(){
generateOnRepeat('#img2img_generate','#img2img_interrupt');
})
let cancelGenerateForever = function(){
clearInterval(window.generateOnRepeatInterval)
}
appendContextMenuOption('#txt2img_interrupt','Cancel generate forever',cancelGenerateForever)
appendContextMenuOption('#txt2img_generate', 'Cancel generate forever',cancelGenerateForever)
appendContextMenuOption('#img2img_interrupt','Cancel generate forever',cancelGenerateForever)
appendContextMenuOption('#img2img_generate', 'Cancel generate forever',cancelGenerateForever)
appendContextMenuOption('#roll','Roll three',
function(){
let rollbutton = get_uiCurrentTabContent().querySelector('#roll');
setTimeout(function(){rollbutton.click()},100)
setTimeout(function(){rollbutton.click()},200)
setTimeout(function(){rollbutton.click()},300)
}
)
})();
//End example Context Menu Items
onUiUpdate(function(){
addContextMenuEventListener()
}); });

126
javascript/dragdrop.js vendored
View File

@ -1,75 +1,75 @@
// allows drag-dropping files into gradio image elements, and also pasting images from clipboard // allows drag-dropping files into gradio image elements, and also pasting images from clipboard
function isValidImageList( files ) { function isValidImageList(files) {
return files && files?.length === 1 && ['image/png', 'image/gif', 'image/jpeg'].includes(files[0].type); return files && files?.length === 1 && ['image/png', 'image/gif', 'image/jpeg'].includes(files[0].type);
} }
function dropReplaceImage( imgWrap, files ) { function dropReplaceImage(imgWrap, files) {
if (!isValidImageList(files)) return; if (!isValidImageList(files)) return;
const tmpFile = files[0]; const tmpFile = files[0];
imgWrap.querySelector('.modify-upload button + button, .touch-none + div button + button')?.click(); imgWrap.querySelector('.modify-upload button + button, .touch-none + div button + button')?.click();
const callback = () => { const callback = () => {
const fileInput = imgWrap.querySelector('input[type="file"]'); const fileInput = imgWrap.querySelector('input[type="file"]');
if (fileInput) { if (fileInput) {
if (files.length === 0) { if (files.length === 0) {
files = new DataTransfer(); files = new DataTransfer();
files.items.add(tmpFile); files.items.add(tmpFile);
fileInput.files = files.files; fileInput.files = files.files;
} else { } else {
fileInput.files = files; fileInput.files = files;
} }
fileInput.dispatchEvent(new Event('change')); fileInput.dispatchEvent(new Event('change'));
}
};
if (imgWrap.closest('#pnginfo_image')) {
// special treatment for PNG Info tab, wait for fetch request to finish
const oldFetch = window.fetch;
window.fetch = async (input, options) => {
const response = await oldFetch(input, options);
if ( 'api/predict/' === input ) {
const content = await response.text();
window.fetch = oldFetch;
window.requestAnimationFrame( () => callback() );
return new Response(content, {
status: response.status,
statusText: response.statusText,
headers: response.headers
})
}
return response;
};
} else {
window.requestAnimationFrame(() => callback());
} }
};
if (imgWrap.closest('#pnginfo_image')) {
// special treatment for PNG Info tab, wait for fetch request to finish
const oldFetch = window.fetch;
window.fetch = async (input, options) => {
const response = await oldFetch(input, options);
if (input === 'api/predict/') {
const content = await response.text();
window.fetch = oldFetch;
window.requestAnimationFrame(() => callback());
return new Response(content, {
status: response.status,
statusText: response.statusText,
headers: response.headers,
});
}
return response;
};
} else {
window.requestAnimationFrame(() => callback());
}
} }
window.document.addEventListener('dragover', e => { window.document.addEventListener('dragover', (e) => {
const target = e.composedPath()[0]; const target = e.composedPath()[0];
const imgWrap = target.closest('[data-testid="image"]'); const imgWrap = target.closest('[data-testid="image"]');
if ( !imgWrap && target.placeholder && target.placeholder.indexOf("Prompt") == -1) return; if (!imgWrap && target.placeholder && target.placeholder.indexOf('Prompt') == -1) return;
e.stopPropagation(); e.stopPropagation();
e.preventDefault(); e.preventDefault();
e.dataTransfer.dropEffect = 'copy'; e.dataTransfer.dropEffect = 'copy';
}); });
window.document.addEventListener('drop', e => { window.document.addEventListener('drop', (e) => {
const target = e.composedPath()[0]; const target = e.composedPath()[0];
if (!target.placeholder) return; if (!target.placeholder) return;
if (target.placeholder.indexOf("Prompt") == -1) return; if (target.placeholder.indexOf('Prompt') == -1) return;
const imgWrap = target.closest('[data-testid="image"]'); const imgWrap = target.closest('[data-testid="image"]');
if (!imgWrap) return; if (!imgWrap) return;
e.stopPropagation(); e.stopPropagation();
e.preventDefault(); e.preventDefault();
const files = e.dataTransfer.files; const { files } = e.dataTransfer;
dropReplaceImage(imgWrap, files); dropReplaceImage(imgWrap, files);
}); });
window.addEventListener('paste', e => { window.addEventListener('paste', (e) => {
const files = e.clipboardData.files; const { files } = e.clipboardData;
if ( ! isValidImageList( files ) ) return; if (!isValidImageList(files)) return;
const visibleImageFields = [...gradioApp().querySelectorAll('[data-testid="image"]')].filter(el => uiElementIsVisible(el)); const visibleImageFields = [...gradioApp().querySelectorAll('[data-testid="image"]')].filter((el) => uiElementIsVisible(el));
if ( ! visibleImageFields.length ) return; if (!visibleImageFields.length) return;
const firstFreeImageField = visibleImageFields.filter(el => el.querySelector('input[type=file]'))?.[0]; const firstFreeImageField = visibleImageFields.filter((el) => el.querySelector('input[type=file]'))?.[0];
dropReplaceImage(firstFreeImageField ? firstFreeImageField : visibleImageFields[visibleImageFields.length - 1], files); dropReplaceImage(firstFreeImageField || visibleImageFields[visibleImageFields.length - 1], files);
}); });

View File

@ -1,120 +1,119 @@
function keyupEditAttention(event){ function keyupEditAttention(event) {
let target = event.originalTarget || event.composedPath()[0]; const target = event.originalTarget || event.composedPath()[0];
if (! target.matches("[id*='_toprow'] [id*='_prompt'] textarea")) return; if (!target.matches("[id*='_toprow'] [id*='_prompt'] textarea")) return;
if (! (event.metaKey || event.ctrlKey)) return; if (!(event.metaKey || event.ctrlKey)) return;
let isPlus = event.key == "ArrowUp" const isPlus = event.key == 'ArrowUp';
let isMinus = event.key == "ArrowDown" const isMinus = event.key == 'ArrowDown';
if (!isPlus && !isMinus) return; if (!isPlus && !isMinus) return;
let selectionStart = target.selectionStart; let { selectionStart } = target;
let selectionEnd = target.selectionEnd; let { selectionEnd } = target;
let text = target.value; let text = target.value;
function selectCurrentParenthesisBlock(OPEN, CLOSE){ function selectCurrentParenthesisBlock(OPEN, CLOSE) {
if (selectionStart !== selectionEnd) return false; if (selectionStart !== selectionEnd) return false;
// Find opening parenthesis around current cursor // Find opening parenthesis around current cursor
const before = text.substring(0, selectionStart); const before = text.substring(0, selectionStart);
let beforeParen = before.lastIndexOf(OPEN); let beforeParen = before.lastIndexOf(OPEN);
if (beforeParen == -1) return false; if (beforeParen == -1) return false;
let beforeParenClose = before.lastIndexOf(CLOSE); let beforeParenClose = before.lastIndexOf(CLOSE);
while (beforeParenClose !== -1 && beforeParenClose > beforeParen) { while (beforeParenClose !== -1 && beforeParenClose > beforeParen) {
beforeParen = before.lastIndexOf(OPEN, beforeParen - 1); beforeParen = before.lastIndexOf(OPEN, beforeParen - 1);
beforeParenClose = before.lastIndexOf(CLOSE, beforeParenClose - 1); beforeParenClose = before.lastIndexOf(CLOSE, beforeParenClose - 1);
}
// Find closing parenthesis around current cursor
const after = text.substring(selectionStart);
let afterParen = after.indexOf(CLOSE);
if (afterParen == -1) return false;
let afterParenOpen = after.indexOf(OPEN);
while (afterParenOpen !== -1 && afterParen > afterParenOpen) {
afterParen = after.indexOf(CLOSE, afterParen + 1);
afterParenOpen = after.indexOf(OPEN, afterParenOpen + 1);
}
if (beforeParen === -1 || afterParen === -1) return false;
// Set the selection to the text between the parenthesis
const parenContent = text.substring(beforeParen + 1, selectionStart + afterParen);
const lastColon = parenContent.lastIndexOf(":");
selectionStart = beforeParen + 1;
selectionEnd = selectionStart + lastColon;
target.setSelectionRange(selectionStart, selectionEnd);
return true;
} }
function selectCurrentWord(){ // Find closing parenthesis around current cursor
if (selectionStart !== selectionEnd) return false; const after = text.substring(selectionStart);
const delimiters = opts.keyedit_delimiters + " \r\n\t"; let afterParen = after.indexOf(CLOSE);
if (afterParen == -1) return false;
let afterParenOpen = after.indexOf(OPEN);
while (afterParenOpen !== -1 && afterParen > afterParenOpen) {
afterParen = after.indexOf(CLOSE, afterParen + 1);
afterParenOpen = after.indexOf(OPEN, afterParenOpen + 1);
}
if (beforeParen === -1 || afterParen === -1) return false;
// seek backward until to find beggining // Set the selection to the text between the parenthesis
while (!delimiters.includes(text[selectionStart - 1]) && selectionStart > 0) { const parenContent = text.substring(beforeParen + 1, selectionStart + afterParen);
selectionStart--; const lastColon = parenContent.lastIndexOf(':');
} selectionStart = beforeParen + 1;
selectionEnd = selectionStart + lastColon;
target.setSelectionRange(selectionStart, selectionEnd);
return true;
}
// seek forward to find end function selectCurrentWord() {
while (!delimiters.includes(text[selectionEnd]) && selectionEnd < text.length) { if (selectionStart !== selectionEnd) return false;
selectionEnd++; const delimiters = `${opts.keyedit_delimiters} \r\n\t`;
}
target.setSelectionRange(selectionStart, selectionEnd); // seek backward until to find beggining
return true; while (!delimiters.includes(text[selectionStart - 1]) && selectionStart > 0) {
selectionStart--;
} }
// If the user hasn't selected anything, let's select their current parenthesis block or word // seek forward to find end
if (!selectCurrentParenthesisBlock('<', '>') && !selectCurrentParenthesisBlock('(', ')')) { while (!delimiters.includes(text[selectionEnd]) && selectionEnd < text.length) {
selectCurrentWord(); selectionEnd++;
} }
event.preventDefault(); target.setSelectionRange(selectionStart, selectionEnd);
return true;
}
closeCharacter = ')' // If the user hasn't selected anything, let's select their current parenthesis block or word
delta = opts.keyedit_precision_attention if (!selectCurrentParenthesisBlock('<', '>') && !selectCurrentParenthesisBlock('(', ')')) {
selectCurrentWord();
}
if (selectionStart > 0 && text[selectionStart - 1] == '<'){ event.preventDefault();
closeCharacter = '>'
delta = opts.keyedit_precision_extra
} else if (selectionStart == 0 || text[selectionStart - 1] != "(") {
// do not include spaces at the end closeCharacter = ')';
while(selectionEnd > selectionStart && text[selectionEnd-1] == ' '){ delta = opts.keyedit_precision_attention;
selectionEnd -= 1;
}
if(selectionStart == selectionEnd){
return
}
text = text.slice(0, selectionStart) + "(" + text.slice(selectionStart, selectionEnd) + ":1.0)" + text.slice(selectionEnd); if (selectionStart > 0 && text[selectionStart - 1] == '<') {
closeCharacter = '>';
selectionStart += 1; delta = opts.keyedit_precision_extra;
selectionEnd += 1; } else if (selectionStart == 0 || text[selectionStart - 1] != '(') {
// do not include spaces at the end
while (selectionEnd > selectionStart && text[selectionEnd - 1] == ' ') {
selectionEnd -= 1;
}
if (selectionStart == selectionEnd) {
return;
} }
end = text.slice(selectionEnd + 1).indexOf(closeCharacter) + 1; text = `${text.slice(0, selectionStart)}(${text.slice(selectionStart, selectionEnd)}:1.0)${text.slice(selectionEnd)}`;
weight = parseFloat(text.slice(selectionEnd + 1, selectionEnd + 1 + end));
if (isNaN(weight)) return;
weight += isPlus ? delta : -delta; selectionStart += 1;
weight = parseFloat(weight.toPrecision(12)); selectionEnd += 1;
if(String(weight).length == 1) weight += ".0" }
if (closeCharacter == ')' && weight == 1) { end = text.slice(selectionEnd + 1).indexOf(closeCharacter) + 1;
text = text.slice(0, selectionStart - 1) + text.slice(selectionStart, selectionEnd) + text.slice(selectionEnd + 5); weight = parseFloat(text.slice(selectionEnd + 1, selectionEnd + 1 + end));
selectionStart--; if (isNaN(weight)) return;
selectionEnd--;
} else {
text = text.slice(0, selectionEnd + 1) + weight + text.slice(selectionEnd + 1 + end - 1);
}
target.focus(); weight += isPlus ? delta : -delta;
target.value = text; weight = parseFloat(weight.toPrecision(12));
target.selectionStart = selectionStart; if (String(weight).length == 1) weight += '.0';
target.selectionEnd = selectionEnd;
updateInput(target) if (closeCharacter == ')' && weight == 1) {
text = text.slice(0, selectionStart - 1) + text.slice(selectionStart, selectionEnd) + text.slice(selectionEnd + 5);
selectionStart--;
selectionEnd--;
} else {
text = text.slice(0, selectionEnd + 1) + weight + text.slice(selectionEnd + 1 + end - 1);
}
target.focus();
target.value = text;
target.selectionStart = selectionStart;
target.selectionEnd = selectionEnd;
updateInput(target);
} }
addEventListener('keydown', (event) => { addEventListener('keydown', (event) => {
keyupEditAttention(event); keyupEditAttention(event);
}); });

View File

@ -1,5 +1,4 @@
function extensions_apply(_a, _b, disable_all){
function extensions_apply(_, _, disable_all){
var disable = [] var disable = []
var update = [] var update = []
gradioApp().querySelectorAll('#extensions input[type="checkbox"]').forEach(function(x){ gradioApp().querySelectorAll('#extensions input[type="checkbox"]').forEach(function(x){

View File

@ -1,170 +1,170 @@
function setupExtraNetworksForTab(tabname){ function setupExtraNetworksForTab(tabname) {
gradioApp().querySelector('#'+tabname+'_extra_tabs').classList.add('extra-networks') gradioApp().querySelector(`#${tabname}_extra_tabs`).classList.add('extra-networks');
var tabs = gradioApp().querySelector('#'+tabname+'_extra_tabs > div') const tabs = gradioApp().querySelector(`#${tabname}_extra_tabs > div`);
var search = gradioApp().querySelector('#'+tabname+'_extra_search textarea') const search = gradioApp().querySelector(`#${tabname}_extra_search textarea`);
var refresh = gradioApp().getElementById(tabname+'_extra_refresh') const refresh = gradioApp().getElementById(`${tabname}_extra_refresh`);
var descriptInput = gradioApp().getElementById(tabname+ '_description_input') const descriptInput = gradioApp().getElementById(`${tabname}_description_input`);
var close = gradioApp().getElementById(tabname+'_extra_close') const close = gradioApp().getElementById(`${tabname}_extra_close`);
search.classList.add('search') search.classList.add('search');
tabs.appendChild(search) tabs.appendChild(search);
tabs.appendChild(refresh) tabs.appendChild(refresh);
tabs.appendChild(close) tabs.appendChild(close);
tabs.appendChild(descriptInput) tabs.appendChild(descriptInput);
search.addEventListener("input", function(evt){ search.addEventListener('input', (evt) => {
searchTerm = search.value.toLowerCase() searchTerm = search.value.toLowerCase();
gradioApp().querySelectorAll('#'+tabname+'_extra_tabs div.card').forEach(function(elem){ gradioApp().querySelectorAll(`#${tabname}_extra_tabs div.card`).forEach((elem) => {
text = elem.querySelector('.name').textContent.toLowerCase() + " " + elem.querySelector('.search_term').textContent.toLowerCase() text = `${elem.querySelector('.name').textContent.toLowerCase()} ${elem.querySelector('.search_term').textContent.toLowerCase()}`;
elem.style.display = text.indexOf(searchTerm) == -1 ? "none" : "" elem.style.display = text.indexOf(searchTerm) == -1 ? 'none' : '';
})
}); });
});
} }
var activePromptTextarea = {}; const activePromptTextarea = {};
function setupExtraNetworks(){ function setupExtraNetworks() {
setupExtraNetworksForTab('txt2img') setupExtraNetworksForTab('txt2img');
setupExtraNetworksForTab('img2img') setupExtraNetworksForTab('img2img');
function registerPrompt(tabname, id){ function registerPrompt(tabname, id) {
var textarea = gradioApp().querySelector("#" + id + " > label > textarea"); const textarea = gradioApp().querySelector(`#${id} > label > textarea`);
if ( !activePromptTextarea[tabname]) activePromptTextarea[tabname] = textarea if (!activePromptTextarea[tabname]) activePromptTextarea[tabname] = textarea;
textarea.addEventListener("focus", function(){ textarea.addEventListener('focus', () => {
activePromptTextarea[tabname] = textarea; activePromptTextarea[tabname] = textarea;
}); });
}
registerPrompt('txt2img', 'txt2img_prompt');
registerPrompt('txt2img', 'txt2img_neg_prompt');
registerPrompt('img2img', 'img2img_prompt');
registerPrompt('img2img', 'img2img_neg_prompt');
}
onUiLoaded(setupExtraNetworks);
const re_extranet = /<([^:]+:[^:]+):[\d\.]+>/;
const re_extranet_g = /\s+<([^:]+:[^:]+):[\d\.]+>/g;
function tryToRemoveExtraNetworkFromPrompt(textarea, text) {
let m = text.match(re_extranet);
if (!m) return false;
const partToSearch = m[1];
let replaced = false;
const newTextareaText = textarea.value.replaceAll(re_extranet_g, (found, index) => {
m = found.match(re_extranet);
if (m[1] == partToSearch) {
replaced = true;
return '';
} }
registerPrompt('txt2img', 'txt2img_prompt') return found;
registerPrompt('txt2img', 'txt2img_neg_prompt') });
registerPrompt('img2img', 'img2img_prompt') if (replaced) {
registerPrompt('img2img', 'img2img_neg_prompt') textarea.value = newTextareaText;
return true;
}
return false;
} }
onUiLoaded(setupExtraNetworks) function cardClicked(tabname, textToAdd, allowNegativePrompt) {
var re_extranet = /<([^:]+:[^:]+):[\d\.]+>/; const textarea = allowNegativePrompt ? activePromptTextarea[tabname] : gradioApp().querySelector(`#${tabname}_prompt > label > textarea`);
var re_extranet_g = /\s+<([^:]+:[^:]+):[\d\.]+>/g; if (!tryToRemoveExtraNetworkFromPrompt(textarea, textToAdd)) textarea.value = textarea.value + opts.extra_networks_add_text_separator + textToAdd;
updateInput(textarea);
}
function tryToRemoveExtraNetworkFromPrompt(textarea, text){ function saveCardPreview(event, tabname, filename) {
var m = text.match(re_extranet) const textarea = gradioApp().querySelector(`#${tabname}_preview_filename > label > textarea`);
if(! m) return false const button = gradioApp().getElementById(`${tabname}_save_preview`);
var partToSearch = m[1] textarea.value = filename;
var replaced = false updateInput(textarea);
var newTextareaText = textarea.value.replaceAll(re_extranet_g, function(found, index){ button.click();
m = found.match(re_extranet); event.stopPropagation();
if(m[1] == partToSearch){ event.preventDefault();
replaced = true; }
return ""
} function saveCardDescription(event, tabname, filename, descript) {
return found; const textarea = gradioApp().querySelector(`#${tabname}_description_filename > label > textarea`);
}) const button = gradioApp().getElementById(`${tabname}_save_description`);
if(replaced){ const description = gradioApp().getElementById(`${tabname}_description_input`);
textarea.value = newTextareaText textarea.value = filename;
return true; description.value = descript;
updateInput(textarea);
button.click();
event.stopPropagation();
event.preventDefault();
}
function readCardDescription(event, tabname, filename, descript, extraPage, cardName) {
const textarea = gradioApp().querySelector(`#${tabname}_description_filename > label > textarea`);
const description_textarea = gradioApp().querySelector(`#${tabname}_description_input > label > textarea`);
const button = gradioApp().getElementById(`${tabname}_read_description`);
textarea.value = filename;
description_textarea.value = descript;
updateInput(textarea);
updateInput(description_textarea);
button.click();
event.stopPropagation();
event.preventDefault();
}
function extraNetworksSearchButton(tabs_id, event) {
searchTextarea = gradioApp().querySelector(`#${tabs_id} > div > textarea`);
button = event.target;
text = button.classList.contains('search-all') ? '' : button.textContent.trim();
searchTextarea.value = text;
updateInput(searchTextarea);
}
let globalPopup = null;
let globalPopupInner = null;
function popup(contents) {
if (!globalPopup) {
globalPopup = document.createElement('div');
globalPopup.onclick = function () { globalPopup.style.display = 'none'; };
globalPopup.classList.add('global-popup');
const close = document.createElement('div');
close.classList.add('global-popup-close');
close.onclick = function () { globalPopup.style.display = 'none'; };
close.title = 'Close';
globalPopup.appendChild(close);
globalPopupInner = document.createElement('div');
globalPopupInner.onclick = function (event) { event.stopPropagation(); return false; };
globalPopupInner.classList.add('global-popup-inner');
globalPopup.appendChild(globalPopupInner);
gradioApp().appendChild(globalPopup);
}
globalPopupInner.innerHTML = '';
globalPopupInner.appendChild(contents);
globalPopup.style.display = 'flex';
}
function readCardMetadata(event, extraPage, cardName) {
requestGet('./sd_extra_networks/metadata', { page: extraPage, item: cardName }, (data) => {
if (data && data.metadata) {
elem = document.createElement('pre');
elem.classList.add('popup-metadata');
elem.textContent = data.metadata;
popup(elem);
} }
return false }, () => {});
event.stopPropagation();
event.preventDefault();
} }
function cardClicked(tabname, textToAdd, allowNegativePrompt){ function requestGet(url, data, handler, errorHandler) {
var textarea = allowNegativePrompt ? activePromptTextarea[tabname] : gradioApp().querySelector("#" + tabname + "_prompt > label > textarea") const xhr = new XMLHttpRequest();
if (!tryToRemoveExtraNetworkFromPrompt(textarea, textToAdd)) textarea.value = textarea.value + opts.extra_networks_add_text_separator + textToAdd const args = Object.keys(data).map((k) => `${encodeURIComponent(k)}=${encodeURIComponent(data[k])}`).join('&');
updateInput(textarea) xhr.open('GET', `${url}?${args}`, true);
} xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
function saveCardPreview(event, tabname, filename){ if (xhr.status === 200) {
var textarea = gradioApp().querySelector("#" + tabname + '_preview_filename > label > textarea') try {
var button = gradioApp().getElementById(tabname + '_save_preview') const js = JSON.parse(xhr.responseText);
textarea.value = filename handler(js);
updateInput(textarea) } catch (error) {
button.click() console.error(error);
event.stopPropagation() errorHandler();
event.preventDefault() }
} } else {
errorHandler();
function saveCardDescription(event, tabname, filename, descript){ }
var textarea = gradioApp().querySelector("#" + tabname + '_description_filename > label > textarea')
var button = gradioApp().getElementById(tabname + '_save_description')
var description = gradioApp().getElementById(tabname+ '_description_input')
textarea.value = filename
description.value=descript
updateInput(textarea)
button.click()
event.stopPropagation()
event.preventDefault()
}
function readCardDescription(event, tabname, filename, descript, extraPage, cardName){
var textarea = gradioApp().querySelector("#" + tabname + '_description_filename > label > textarea')
var description_textarea = gradioApp().querySelector("#" + tabname+ '_description_input > label > textarea')
var button = gradioApp().getElementById(tabname + '_read_description')
textarea.value = filename
description_textarea.value = descript
updateInput(textarea)
updateInput(description_textarea)
button.click()
event.stopPropagation()
event.preventDefault()
}
function extraNetworksSearchButton(tabs_id, event){
searchTextarea = gradioApp().querySelector("#" + tabs_id + ' > div > textarea')
button = event.target
text = button.classList.contains("search-all") ? "" : button.textContent.trim()
searchTextarea.value = text
updateInput(searchTextarea)
}
var globalPopup = null;
var globalPopupInner = null;
function popup(contents){
if(! globalPopup){
globalPopup = document.createElement('div')
globalPopup.onclick = function(){ globalPopup.style.display = "none"; };
globalPopup.classList.add('global-popup');
var close = document.createElement('div')
close.classList.add('global-popup-close');
close.onclick = function(){ globalPopup.style.display = "none"; };
close.title = "Close";
globalPopup.appendChild(close)
globalPopupInner = document.createElement('div')
globalPopupInner.onclick = function(event){ event.stopPropagation(); return false; };
globalPopupInner.classList.add('global-popup-inner');
globalPopup.appendChild(globalPopupInner)
gradioApp().appendChild(globalPopup);
} }
globalPopupInner.innerHTML = ''; };
globalPopupInner.appendChild(contents); const js = JSON.stringify(data);
globalPopup.style.display = "flex"; xhr.send(js);
}
function readCardMetadata(event, extraPage, cardName){
requestGet("./sd_extra_networks/metadata", {"page": extraPage, "item": cardName}, function(data){
if (data && data.metadata){
elem = document.createElement('pre')
elem.classList.add('popup-metadata');
elem.textContent = data.metadata;
popup(elem);
}
}, () => {})
event.stopPropagation()
event.preventDefault()
}
function requestGet(url, data, handler, errorHandler){
var xhr = new XMLHttpRequest();
var args = Object.keys(data).map(function(k){ return encodeURIComponent(k) + '=' + encodeURIComponent(data[k]) }).join('&')
xhr.open("GET", url + "?" + args, true);
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
try {
var js = JSON.parse(xhr.responseText);
handler(js)
} catch (error) {
console.error(error);
errorHandler()
}
} else{
errorHandler()
}
}
};
var js = JSON.stringify(data);
xhr.send(js);
} }

View File

@ -1,30 +1,30 @@
// attaches listeners to the txt2img and img2img galleries to update displayed generation param text when the image changes // attaches listeners to the txt2img and img2img galleries to update displayed generation param text when the image changes
let txt2img_gallery, img2img_gallery, modal = undefined; let txt2img_gallery; let img2img_gallery; let
onUiUpdate(function(){ modal;
if (!txt2img_gallery) txt2img_gallery = attachGalleryListeners("txt2img") onUiUpdate(() => {
if (!img2img_gallery) img2img_gallery = attachGalleryListeners("img2img") if (!txt2img_gallery) txt2img_gallery = attachGalleryListeners('txt2img');
if (!modal) { if (!img2img_gallery) img2img_gallery = attachGalleryListeners('img2img');
modal = gradioApp().getElementById('lightboxModal') if (!modal) {
modalObserver.observe(modal, { attributes : true, attributeFilter : ['style'] }); modal = gradioApp().getElementById('lightboxModal');
} modalObserver.observe(modal, { attributes: true, attributeFilter: ['style'] });
}
}); });
let modalObserver = new MutationObserver(function(mutations) { let modalObserver = new MutationObserver((mutations) => {
mutations.forEach((mutationRecord) => { mutations.forEach((mutationRecord) => {
let selectedTab = gradioApp().querySelector('#tabs div button.selected')?.innerText let selectedTab = gradioApp().querySelector('#tabs div button.selected')?.innerText;
if (!selectedTab) selectedTab = gradioApp().querySelector('#tabs div button')?.innerText if (!selectedTab) selectedTab = gradioApp().querySelector('#tabs div button')?.innerText;
if (mutationRecord.target.style.display === 'none' && (selectedTab === 'txt2img' || selectedTab === 'img2img')) if (mutationRecord.target.style.display === 'none' && (selectedTab === 'txt2img' || selectedTab === 'img2img')) { gradioApp().getElementById(`${selectedTab}_generation_info_button`)?.click(); }
gradioApp().getElementById(selectedTab+"_generation_info_button")?.click() });
});
}); });
function attachGalleryListeners(tab_name) { function attachGalleryListeners(tab_name) {
gallery = gradioApp().querySelector('#'+tab_name+'_gallery') gallery = gradioApp().querySelector(`#${tab_name}_gallery`);
gallery?.addEventListener('click', () => gradioApp().getElementById(tab_name+"_generation_info_button").click()); gallery?.addEventListener('click', () => gradioApp().getElementById(`${tab_name}_generation_info_button`).click());
gallery?.addEventListener('keydown', (e) => { gallery?.addEventListener('keydown', (e) => {
if (e.keyCode == 37 || e.keyCode == 39) // left or right arrow if (e.keyCode == 37 || e.keyCode == 39) // left or right arrow
gradioApp().getElementById(tab_name+"_generation_info_button").click() { gradioApp().getElementById(`${tab_name}_generation_info_button`).click(); }
}); });
return gallery; return gallery;
} }

View File

@ -1,147 +1,146 @@
// mouseover tooltips for various UI elements // mouseover tooltips for various UI elements
titles = { titles = {
"Sampling steps": "How many times to improve the generated image iteratively; higher values take longer; very low values can produce bad results", 'Sampling steps': 'How many times to improve the generated image iteratively; higher values take longer; very low values can produce bad results',
"Sampling method": "Which algorithm to use to produce the image", 'Sampling method': 'Which algorithm to use to produce the image',
"GFPGAN": "Restore low quality faces using GFPGAN neural network", GFPGAN: 'Restore low quality faces using GFPGAN neural network',
"Euler a": "Euler Ancestral - very creative, each can get a completely different picture depending on step count, setting steps higher than 30-40 does not help", 'Euler a': 'Euler Ancestral - very creative, each can get a completely different picture depending on step count, setting steps higher than 30-40 does not help',
"DDIM": "Denoising Diffusion Implicit Models - best at inpainting", DDIM: 'Denoising Diffusion Implicit Models - best at inpainting',
"UniPC": "Unified Predictor-Corrector Framework for Fast Sampling of Diffusion Models", UniPC: 'Unified Predictor-Corrector Framework for Fast Sampling of Diffusion Models',
"DPM adaptive": "Ignores step count - uses a number of steps determined by the CFG and resolution", 'DPM adaptive': 'Ignores step count - uses a number of steps determined by the CFG and resolution',
"Batch count": "How many batches of images to create (has no impact on generation performance or VRAM usage)", 'Batch count': 'How many batches of images to create (has no impact on generation performance or VRAM usage)',
"Batch size": "How many image to create in a single batch (increases generation performance at cost of higher VRAM usage)", 'Batch size': 'How many image to create in a single batch (increases generation performance at cost of higher VRAM usage)',
"CFG Scale": "Classifier Free Guidance Scale - how strongly the image should conform to prompt - lower values produce more creative results", 'CFG Scale': 'Classifier Free Guidance Scale - how strongly the image should conform to prompt - lower values produce more creative results',
"Seed": "A value that determines the output of random number generator - if you create an image with same parameters and seed as another image, you'll get the same result", Seed: "A value that determines the output of random number generator - if you create an image with same parameters and seed as another image, you'll get the same result",
"\u{1f3b2}\ufe0f": "Set seed to -1, which will cause a new random number to be used every time", '\u{1f3b2}\ufe0f': 'Set seed to -1, which will cause a new random number to be used every time',
"\u267b\ufe0f": "Reuse seed from last generation, mostly useful if it was randomed", '\u267b\ufe0f': 'Reuse seed from last generation, mostly useful if it was randomed',
"\u2199\ufe0f": "Read generation parameters from prompt or last generation if prompt is empty into user interface.", '\u2199\ufe0f': 'Read generation parameters from prompt or last generation if prompt is empty into user interface.',
"\u{1f4c2}": "Open images output directory", '\u{1f4c2}': 'Open images output directory',
"\u{1f4be}": "Save style", '\u{1f4be}': 'Save style',
"\u{1f5d1}\ufe0f": "Clear prompt", '\u{1f5d1}\ufe0f': 'Clear prompt',
"\u{1f4cb}": "Apply selected styles to current prompt", '\u{1f4cb}': 'Apply selected styles to current prompt',
"\u{1f4d2}": "Paste available values into the field", '\u{1f4d2}': 'Paste available values into the field',
"\u{1f3b4}": "Show/hide extra networks", '\u{1f3b4}': 'Show/hide extra networks',
"Inpaint a part of image": "Draw a mask over an image, and the script will regenerate the masked area with content according to prompt", 'Inpaint a part of image': 'Draw a mask over an image, and the script will regenerate the masked area with content according to prompt',
"SD upscale": "Upscale image normally, split result into tiles, improve each tile using img2img, merge whole image back", 'SD upscale': 'Upscale image normally, split result into tiles, improve each tile using img2img, merge whole image back',
"Just resize": "Resize image to target resolution. Unless height and width match, you will get incorrect aspect ratio.", 'Just resize': 'Resize image to target resolution. Unless height and width match, you will get incorrect aspect ratio.',
"Crop and resize": "Resize the image so that entirety of target resolution is filled with the image. Crop parts that stick out.", 'Crop and resize': 'Resize the image so that entirety of target resolution is filled with the image. Crop parts that stick out.',
"Resize and fill": "Resize the image so that entirety of image is inside target resolution. Fill empty space with image's colors.", 'Resize and fill': "Resize the image so that entirety of image is inside target resolution. Fill empty space with image's colors.",
"Mask blur": "How much to blur the mask before processing, in pixels.", 'Mask blur': 'How much to blur the mask before processing, in pixels.',
"Masked content": "What to put inside the masked area before processing it with Stable Diffusion.", 'Masked content': 'What to put inside the masked area before processing it with Stable Diffusion.',
"fill": "fill it with colors of the image", fill: 'fill it with colors of the image',
"original": "keep whatever was there originally", original: 'keep whatever was there originally',
"latent noise": "fill it with latent space noise", 'latent noise': 'fill it with latent space noise',
"latent nothing": "fill it with latent space zeroes", 'latent nothing': 'fill it with latent space zeroes',
"Inpaint at full resolution": "Upscale masked region to target resolution, do inpainting, downscale back and paste into original image", 'Inpaint at full resolution': 'Upscale masked region to target resolution, do inpainting, downscale back and paste into original image',
"Denoising strength": "Determines how little respect the algorithm should have for image's content. At 0, nothing will change, and at 1 you'll get an unrelated image. With values below 1.0, processing will take less steps than the Sampling Steps slider specifies.", 'Denoising strength': "Determines how little respect the algorithm should have for image's content. At 0, nothing will change, and at 1 you'll get an unrelated image. With values below 1.0, processing will take less steps than the Sampling Steps slider specifies.",
"Skip": "Stop processing current image and continue processing.", Skip: 'Stop processing current image and continue processing.',
"Interrupt": "Stop processing images and return any results accumulated so far.", Interrupt: 'Stop processing images and return any results accumulated so far.',
"Save": "Write image to a directory (default - log/images) and generation parameters into csv file.", Save: 'Write image to a directory (default - log/images) and generation parameters into csv file.',
"X values": "Separate values for X axis using commas.", 'X values': 'Separate values for X axis using commas.',
"Y values": "Separate values for Y axis using commas.", 'Y values': 'Separate values for Y axis using commas.',
"None": "Do not do anything special", None: 'Do not do anything special',
"Prompt matrix": "Separate prompts into parts using vertical pipe character (|) and the script will create a picture for every combination of them (except for the first part, which will be present in all combinations)", 'Prompt matrix': 'Separate prompts into parts using vertical pipe character (|) and the script will create a picture for every combination of them (except for the first part, which will be present in all combinations)',
"X/Y/Z plot": "Create grid(s) where images will have different parameters. Use inputs below to specify which parameters will be shared by columns and rows", 'X/Y/Z plot': 'Create grid(s) where images will have different parameters. Use inputs below to specify which parameters will be shared by columns and rows',
"Custom code": "Run Python code. Advanced user only. Must run program with --allow-code for this to work", 'Custom code': 'Run Python code. Advanced user only. Must run program with --allow-code for this to work',
"Prompt S/R": "Separate a list of words with commas, and the first word will be used as a keyword: script will search for this word in the prompt, and replace it with others", 'Prompt S/R': 'Separate a list of words with commas, and the first word will be used as a keyword: script will search for this word in the prompt, and replace it with others',
"Prompt order": "Separate a list of words with commas, and the script will make a variation of prompt with those words for their every possible order", 'Prompt order': 'Separate a list of words with commas, and the script will make a variation of prompt with those words for their every possible order',
"Tiling": "Produce an image that can be tiled.", Tiling: 'Produce an image that can be tiled.',
"Tile overlap": "For SD upscale, how much overlap in pixels should there be between tiles. Tiles overlap so that when they are merged back into one picture, there is no clearly visible seam.", 'Tile overlap': 'For SD upscale, how much overlap in pixels should there be between tiles. Tiles overlap so that when they are merged back into one picture, there is no clearly visible seam.',
"Variation seed": "Seed of a different picture to be mixed into the generation.", 'Variation seed': 'Seed of a different picture to be mixed into the generation.',
"Variation strength": "How strong of a variation to produce. At 0, there will be no effect. At 1, you will get the complete picture with variation seed (except for ancestral samplers, where you will just get something).", 'Variation strength': 'How strong of a variation to produce. At 0, there will be no effect. At 1, you will get the complete picture with variation seed (except for ancestral samplers, where you will just get something).',
"Resize seed from height": "Make an attempt to produce a picture similar to what would have been produced with same seed at specified resolution", 'Resize seed from height': 'Make an attempt to produce a picture similar to what would have been produced with same seed at specified resolution',
"Resize seed from width": "Make an attempt to produce a picture similar to what would have been produced with same seed at specified resolution", 'Resize seed from width': 'Make an attempt to produce a picture similar to what would have been produced with same seed at specified resolution',
"Interrogate": "Reconstruct prompt from existing image and put it into the prompt field.", Interrogate: 'Reconstruct prompt from existing image and put it into the prompt field.',
"Images filename pattern": "Use following tags to define how filenames for images are chosen: [steps], [cfg], [prompt_hash], [prompt], [prompt_no_styles], [prompt_spaces], [width], [height], [styles], [sampler], [seed], [model_hash], [model_name], [prompt_words], [date], [datetime], [datetime<Format>], [datetime<Format><Time Zone>], [job_timestamp]; leave empty for default.", 'Images filename pattern': 'Use following tags to define how filenames for images are chosen: [steps], [cfg], [prompt_hash], [prompt], [prompt_no_styles], [prompt_spaces], [width], [height], [styles], [sampler], [seed], [model_hash], [model_name], [prompt_words], [date], [datetime], [datetime<Format>], [datetime<Format><Time Zone>], [job_timestamp]; leave empty for default.',
"Directory name pattern": "Use following tags to define how subdirectories for images and grids are chosen: [steps], [cfg],[prompt_hash], [prompt], [prompt_no_styles], [prompt_spaces], [width], [height], [styles], [sampler], [seed], [model_hash], [model_name], [prompt_words], [date], [datetime], [datetime<Format>], [datetime<Format><Time Zone>], [job_timestamp]; leave empty for default.", 'Directory name pattern': 'Use following tags to define how subdirectories for images and grids are chosen: [steps], [cfg],[prompt_hash], [prompt], [prompt_no_styles], [prompt_spaces], [width], [height], [styles], [sampler], [seed], [model_hash], [model_name], [prompt_words], [date], [datetime], [datetime<Format>], [datetime<Format><Time Zone>], [job_timestamp]; leave empty for default.',
"Max prompt words": "Set the maximum number of words to be used in the [prompt_words] option; ATTENTION: If the words are too long, they may exceed the maximum length of the file path that the system can handle", 'Max prompt words': 'Set the maximum number of words to be used in the [prompt_words] option; ATTENTION: If the words are too long, they may exceed the maximum length of the file path that the system can handle',
"Loopback": "Performs img2img processing multiple times. Output images are used as input for the next loop.", Loopback: 'Performs img2img processing multiple times. Output images are used as input for the next loop.',
"Loops": "How many times to process an image. Each output is used as the input of the next loop. If set to 1, behavior will be as if this script were not used.", Loops: 'How many times to process an image. Each output is used as the input of the next loop. If set to 1, behavior will be as if this script were not used.',
"Final denoising strength": "The denoising strength for the final loop of each image in the batch.", 'Final denoising strength': 'The denoising strength for the final loop of each image in the batch.',
"Denoising strength curve": "The denoising curve controls the rate of denoising strength change each loop. Aggressive: Most of the change will happen towards the start of the loops. Linear: Change will be constant through all loops. Lazy: Most of the change will happen towards the end of the loops.", 'Denoising strength curve': 'The denoising curve controls the rate of denoising strength change each loop. Aggressive: Most of the change will happen towards the start of the loops. Linear: Change will be constant through all loops. Lazy: Most of the change will happen towards the end of the loops.',
"Style 1": "Style to apply; styles have components for both positive and negative prompts and apply to both", 'Style 1': 'Style to apply; styles have components for both positive and negative prompts and apply to both',
"Style 2": "Style to apply; styles have components for both positive and negative prompts and apply to both", 'Style 2': 'Style to apply; styles have components for both positive and negative prompts and apply to both',
"Apply style": "Insert selected styles into prompt fields", 'Apply style': 'Insert selected styles into prompt fields',
"Create style": "Save current prompts as a style. If you add the token {prompt} to the text, the style uses that as a placeholder for your prompt when you use the style in the future.", 'Create style': 'Save current prompts as a style. If you add the token {prompt} to the text, the style uses that as a placeholder for your prompt when you use the style in the future.',
"Checkpoint name": "Loads weights from checkpoint before making images. You can either use hash or a part of filename (as seen in settings) for checkpoint name. Recommended to use with Y axis for less switching.", 'Checkpoint name': 'Loads weights from checkpoint before making images. You can either use hash or a part of filename (as seen in settings) for checkpoint name. Recommended to use with Y axis for less switching.',
"Inpainting conditioning mask strength": "Only applies to inpainting models. Determines how strongly to mask off the original image for inpainting and img2img. 1.0 means fully masked, which is the default behaviour. 0.0 means a fully unmasked conditioning. Lower values will help preserve the overall composition of the image, but will struggle with large changes.", 'Inpainting conditioning mask strength': 'Only applies to inpainting models. Determines how strongly to mask off the original image for inpainting and img2img. 1.0 means fully masked, which is the default behaviour. 0.0 means a fully unmasked conditioning. Lower values will help preserve the overall composition of the image, but will struggle with large changes.',
"vram": "Torch active: Peak amount of VRAM used by Torch during generation, excluding cached data.\nTorch reserved: Peak amount of VRAM allocated by Torch, including all active and cached data.\nSys VRAM: Peak amount of VRAM allocation across all applications / total GPU VRAM (peak utilization%).", vram: 'Torch active: Peak amount of VRAM used by Torch during generation, excluding cached data.\nTorch reserved: Peak amount of VRAM allocated by Torch, including all active and cached data.\nSys VRAM: Peak amount of VRAM allocation across all applications / total GPU VRAM (peak utilization%).',
"Eta noise seed delta": "If this values is non-zero, it will be added to seed and used to initialize RNG for noises when using samplers with Eta. You can use this to produce even more variation of images, or you can use this to match images of other software if you know what you are doing.", 'Eta noise seed delta': 'If this values is non-zero, it will be added to seed and used to initialize RNG for noises when using samplers with Eta. You can use this to produce even more variation of images, or you can use this to match images of other software if you know what you are doing.',
"Do not add watermark to images": "If this option is enabled, watermark will not be added to created images. Warning: if you do not add watermark, you may be behaving in an unethical manner.", 'Do not add watermark to images': 'If this option is enabled, watermark will not be added to created images. Warning: if you do not add watermark, you may be behaving in an unethical manner.',
"Filename word regex": "This regular expression will be used extract words from filename, and they will be joined using the option below into label text used for training. Leave empty to keep filename text as it is.", 'Filename word regex': 'This regular expression will be used extract words from filename, and they will be joined using the option below into label text used for training. Leave empty to keep filename text as it is.',
"Filename join string": "This string will be used to join split words into a single line if the option above is enabled.", 'Filename join string': 'This string will be used to join split words into a single line if the option above is enabled.',
"Quicksettings list": "List of setting names, separated by commas, for settings that should go to the quick access bar at the top, rather than the usual setting tab. See modules/shared.py for setting names. Requires restarting to apply.", 'Quicksettings list': 'List of setting names, separated by commas, for settings that should go to the quick access bar at the top, rather than the usual setting tab. See modules/shared.py for setting names. Requires restarting to apply.',
"Weighted sum": "Result = A * (1 - M) + B * M", 'Weighted sum': 'Result = A * (1 - M) + B * M',
"Add difference": "Result = A + (B - C) * M", 'Add difference': 'Result = A + (B - C) * M',
"No interpolation": "Result = A", 'No interpolation': 'Result = A',
"Initialization text": "If the number of tokens is more than the number of vectors, some may be skipped.\nLeave the textbox empty to start with zeroed out vectors", 'Initialization text': 'If the number of tokens is more than the number of vectors, some may be skipped.\nLeave the textbox empty to start with zeroed out vectors',
"Learning rate": "How fast should training go. Low values will take longer to train, high values may fail to converge (not generate accurate results) and/or may break the embedding (This has happened if you see Loss: nan in the training info textbox. If this happens, you need to manually restore your embedding from an older not-broken backup).\n\nYou can set a single numeric value, or multiple learning rates using the syntax:\n\n rate_1:max_steps_1, rate_2:max_steps_2, ...\n\nEG: 0.005:100, 1e-3:1000, 1e-5\n\nWill train with rate of 0.005 for first 100 steps, then 1e-3 until 1000 steps, then 1e-5 for all remaining steps.", 'Learning rate': 'How fast should training go. Low values will take longer to train, high values may fail to converge (not generate accurate results) and/or may break the embedding (This has happened if you see Loss: nan in the training info textbox. If this happens, you need to manually restore your embedding from an older not-broken backup).\n\nYou can set a single numeric value, or multiple learning rates using the syntax:\n\n rate_1:max_steps_1, rate_2:max_steps_2, ...\n\nEG: 0.005:100, 1e-3:1000, 1e-5\n\nWill train with rate of 0.005 for first 100 steps, then 1e-3 until 1000 steps, then 1e-5 for all remaining steps.',
"Clip skip": "Early stopping parameter for CLIP model; 1 is stop at last layer as usual, 2 is stop at penultimate layer, etc.", 'Clip skip': 'Early stopping parameter for CLIP model; 1 is stop at last layer as usual, 2 is stop at penultimate layer, etc.',
"Approx NN": "Cheap neural network approximation. Very fast compared to VAE, but produces pictures with 4 times smaller horizontal/vertical resolution and lower quality.", 'Approx NN': 'Cheap neural network approximation. Very fast compared to VAE, but produces pictures with 4 times smaller horizontal/vertical resolution and lower quality.',
"Approx cheap": "Very cheap approximation. Very fast compared to VAE, but produces pictures with 8 times smaller horizontal/vertical resolution and extremely low quality.", 'Approx cheap': 'Very cheap approximation. Very fast compared to VAE, but produces pictures with 8 times smaller horizontal/vertical resolution and extremely low quality.',
"Hires. fix": "Use a two step process to partially create an image at smaller resolution, upscale, and then improve details in it without changing composition", 'Hires. fix': 'Use a two step process to partially create an image at smaller resolution, upscale, and then improve details in it without changing composition',
"Hires steps": "Number of sampling steps for upscaled picture. If 0, uses same as for original.", 'Hires steps': 'Number of sampling steps for upscaled picture. If 0, uses same as for original.',
"Upscale by": "Adjusts the size of the image by multiplying the original width and height by the selected value. Ignored if either Resize width to or Resize height to are non-zero.", 'Upscale by': 'Adjusts the size of the image by multiplying the original width and height by the selected value. Ignored if either Resize width to or Resize height to are non-zero.',
"Resize width to": "Resizes image to this width. If 0, width is inferred from either of two nearby sliders.", 'Resize width to': 'Resizes image to this width. If 0, width is inferred from either of two nearby sliders.',
"Resize height to": "Resizes image to this height. If 0, height is inferred from either of two nearby sliders.", 'Resize height to': 'Resizes image to this height. If 0, height is inferred from either of two nearby sliders.',
"Multiplier for extra networks": "When adding extra network such as Hypernetwork or Lora to prompt, use this multiplier for it.", 'Multiplier for extra networks': 'When adding extra network such as Hypernetwork or Lora to prompt, use this multiplier for it.',
"Discard weights with matching name": "Regular expression; if weights's name matches it, the weights is not written to the resulting checkpoint. Use ^model_ema to discard EMA weights.", 'Discard weights with matching name': "Regular expression; if weights's name matches it, the weights is not written to the resulting checkpoint. Use ^model_ema to discard EMA weights.",
"Extra networks tab order": "Comma-separated list of tab names; tabs listed here will appear in the extra networks UI first and in order lsited." 'Extra networks tab order': 'Comma-separated list of tab names; tabs listed here will appear in the extra networks UI first and in order lsited.',
} };
onUiUpdate(() => {
gradioApp().querySelectorAll('span, button, select, p').forEach((span) => {
tooltip = titles[span.textContent];
onUiUpdate(function(){ if (!tooltip) {
gradioApp().querySelectorAll('span, button, select, p').forEach(function(span){
tooltip = titles[span.textContent];
if(!tooltip){
tooltip = titles[span.value]; tooltip = titles[span.value];
} }
if(!tooltip){ if (!tooltip) {
for (const c of span.classList) { for (const c of span.classList) {
if (c in titles) { if (c in titles) {
tooltip = titles[c]; tooltip = titles[c];
break; break;
} }
} }
} }
if(tooltip){ if (tooltip) {
span.title = tooltip; span.title = tooltip;
} }
}) });
gradioApp().querySelectorAll('select').forEach(function(select){ gradioApp().querySelectorAll('select').forEach((select) => {
if (select.onchange != null) return; if (select.onchange != null) return;
select.onchange = function(){ select.onchange = function () {
select.title = titles[select.value] || ""; select.title = titles[select.value] || '';
} };
}) });
}) });

View File

@ -1,22 +1,16 @@
function setInactive(elem, inactive) {
function setInactive(elem, inactive){ if (inactive) elem.classList.add('inactive');
if(inactive){ else elem.classList.remove('inactive');
elem.classList.add('inactive')
} else{
elem.classList.remove('inactive')
}
} }
function onCalcResolutionHires(enable, width, height, hr_scale, hr_resize_x, hr_resize_y){ function onCalcResolutionHires(enable, width, height, hr_scale, hr_resize_x, hr_resize_y) {
hrUpscaleBy = gradioApp().getElementById('txt2img_hr_scale') const hrUpscaleBy = gradioApp().getElementById('txt2img_hr_scale');
hrResizeX = gradioApp().getElementById('txt2img_hr_resize_x') const hrResizeX = gradioApp().getElementById('txt2img_hr_resize_x');
hrResizeY = gradioApp().getElementById('txt2img_hr_resize_y') const hrResizeY = gradioApp().getElementById('txt2img_hr_resize_y');
gradioApp().getElementById('txt2img_hires_fix_row2').style.display = opts.use_old_hires_fix_width_height ? 'none' : '';
gradioApp().getElementById('txt2img_hires_fix_row2').style.display = opts.use_old_hires_fix_width_height ? "none" : "" setInactive(hrUpscaleBy, opts.use_old_hires_fix_width_height || hr_resize_x > 0 || hr_resize_y > 0);
setInactive(hrResizeX, opts.use_old_hires_fix_width_height || hr_resize_x === 0);
setInactive(hrUpscaleBy, opts.use_old_hires_fix_width_height || hr_resize_x > 0 || hr_resize_y > 0) setInactive(hrResizeY, opts.use_old_hires_fix_width_height || hr_resize_y === 0);
setInactive(hrResizeX, opts.use_old_hires_fix_width_height || hr_resize_x == 0) // return [enable, width, height, hr_scale, hr_resize_x, hr_resize_y];
setInactive(hrResizeY, opts.use_old_hires_fix_width_height || hr_resize_y == 0) setTimeout(() => [enable, width, height, hr_scale, hr_resize_x, hr_resize_y], 100);
return [enable, width, height, hr_scale, hr_resize_x, hr_resize_y]
} }

View File

@ -2,44 +2,44 @@
* temporary fix for https://github.com/AUTOMATIC1111/stable-diffusion-webui/issues/668 * temporary fix for https://github.com/AUTOMATIC1111/stable-diffusion-webui/issues/668
* @see https://github.com/gradio-app/gradio/issues/1721 * @see https://github.com/gradio-app/gradio/issues/1721
*/ */
window.addEventListener( 'resize', () => imageMaskResize()); window.addEventListener('resize', () => imageMaskResize());
function imageMaskResize() { function imageMaskResize() {
const canvases = gradioApp().querySelectorAll('#img2maskimg .touch-none canvas'); const canvases = gradioApp().querySelectorAll('#img2maskimg .touch-none canvas');
if ( ! canvases.length ) { if (!canvases.length) {
canvases_fixed = false; canvases_fixed = false;
window.removeEventListener( 'resize', imageMaskResize ); window.removeEventListener('resize', imageMaskResize);
return; return;
} }
const wrapper = canvases[0].closest('.touch-none'); const wrapper = canvases[0].closest('.touch-none');
const previewImage = wrapper.previousElementSibling; const previewImage = wrapper.previousElementSibling;
if ( ! previewImage.complete ) { if (!previewImage.complete) {
previewImage.addEventListener( 'load', () => imageMaskResize()); previewImage.addEventListener('load', () => imageMaskResize());
return; return;
} }
const w = previewImage.width; const w = previewImage.width;
const h = previewImage.height; const h = previewImage.height;
const nw = previewImage.naturalWidth; const nw = previewImage.naturalWidth;
const nh = previewImage.naturalHeight; const nh = previewImage.naturalHeight;
const portrait = nh > nw; const portrait = nh > nw;
const factor = portrait; const factor = portrait;
const wW = Math.min(w, portrait ? h/nh*nw : w/nw*nw); const wW = Math.min(w, portrait ? h / nh * nw : w / nw * nw);
const wH = Math.min(h, portrait ? h/nh*nh : w/nw*nh); const wH = Math.min(h, portrait ? h / nh * nh : w / nw * nh);
wrapper.style.width = `${wW}px`; wrapper.style.width = `${wW}px`;
wrapper.style.height = `${wH}px`; wrapper.style.height = `${wH}px`;
wrapper.style.left = `0px`; wrapper.style.left = '0px';
wrapper.style.top = `0px`; wrapper.style.top = '0px';
canvases.forEach( c => { canvases.forEach((c) => {
c.style.width = c.style.height = ''; c.style.width = c.style.height = '';
c.style.maxWidth = '100%'; c.style.maxWidth = '100%';
c.style.maxHeight = '100%'; c.style.maxHeight = '100%';
c.style.objectFit = 'contain'; c.style.objectFit = 'contain';
}); });
} }
onUiUpdate(() => imageMaskResize()); onUiUpdate(() => imageMaskResize());

View File

@ -1,20 +1,20 @@
window.onload = (function(){ window.onload = (function () {
window.addEventListener('drop', e => { window.addEventListener('drop', (e) => {
const target = e.composedPath()[0]; const target = e.composedPath()[0];
if (!target.placeholder) return; if (!target.placeholder) return;
const idx = selected_gallery_index(); const idx = selected_gallery_index();
if (target.placeholder.indexOf("Prompt") == -1) return; if (target.placeholder.indexOf('Prompt') == -1) return;
let prompt_target = get_tab_index('tabs') == 1 ? "img2img_prompt_image" : "txt2img_prompt_image"; const prompt_target = get_tab_index('tabs') == 1 ? 'img2img_prompt_image' : 'txt2img_prompt_image';
e.stopPropagation(); e.stopPropagation();
e.preventDefault(); e.preventDefault();
const imgParent = gradioApp().getElementById(prompt_target); const imgParent = gradioApp().getElementById(prompt_target);
const files = e.dataTransfer.files; const { files } = e.dataTransfer;
const fileInput = imgParent.querySelector('input[type="file"]'); const fileInput = imgParent.querySelector('input[type="file"]');
if ( fileInput ) { if (fileInput) {
fileInput.files = files; fileInput.files = files;
fileInput.dispatchEvent(new Event('change')); fileInput.dispatchEvent(new Event('change'));
} }
}); });
}); });

View File

@ -1,219 +1,218 @@
// A full size 'lightbox' preview modal shown when left clicking on gallery previews // A full size 'lightbox' preview modal shown when left clicking on gallery previews
function closeModal() { function closeModal() {
gradioApp().getElementById("lightboxModal").style.display = "none"; gradioApp().getElementById('lightboxModal').style.display = 'none';
} }
function showModal(event) { function showModal(event) {
const source = event.target || event.srcElement; const source = event.target || event.srcElement;
const modalImage = gradioApp().getElementById("modalImage") const modalImage = gradioApp().getElementById('modalImage');
const lb = gradioApp().getElementById("lightboxModal") const lb = gradioApp().getElementById('lightboxModal');
modalImage.src = source.src modalImage.src = source.src;
if (modalImage.style.display === 'none') lb.style.setProperty('background-image', 'url(' + source.src + ')'); if (modalImage.style.display === 'none') lb.style.setProperty('background-image', `url(${source.src})`);
lb.style.display = "flex"; lb.style.display = 'flex';
lb.focus() lb.focus();
const tabTxt2Img = gradioApp().getElementById("tab_txt2img") const tabTxt2Img = gradioApp().getElementById('tab_txt2img');
const tabImg2Img = gradioApp().getElementById("tab_img2img") const tabImg2Img = gradioApp().getElementById('tab_img2img');
// show the save button in modal only on txt2img or img2img tabs // show the save button in modal only on txt2img or img2img tabs
if (tabTxt2Img.style.display != "none" || tabImg2Img.style.display != "none") gradioApp().getElementById("modal_save").style.display = "inline" if (tabTxt2Img.style.display != 'none' || tabImg2Img.style.display != 'none') gradioApp().getElementById('modal_save').style.display = 'inline';
else gradioApp().getElementById("modal_save").style.display = "none" else gradioApp().getElementById('modal_save').style.display = 'none';
event.stopPropagation() event.stopPropagation();
} }
function negmod(n, m) { function negmod(n, m) {
return ((n % m) + m) % m; return ((n % m) + m) % m;
} }
function updateOnBackgroundChange() { function updateOnBackgroundChange() {
const modalImage = gradioApp().getElementById("modalImage") const modalImage = gradioApp().getElementById('modalImage');
if (modalImage && modalImage.offsetParent) { if (modalImage && modalImage.offsetParent) {
let currentButton = selected_gallery_button(); const currentButton = selected_gallery_button();
if (currentButton?.children?.length > 0 && modalImage.src != currentButton.children[0].src) { if (currentButton?.children?.length > 0 && modalImage.src != currentButton.children[0].src) {
modalImage.src = currentButton.children[0].src; modalImage.src = currentButton.children[0].src;
if (modalImage.style.display === 'none') modal.style.setProperty('background-image', `url(${modalImage.src})`) if (modalImage.style.display === 'none') modal.style.setProperty('background-image', `url(${modalImage.src})`);
}
} }
}
} }
function modalImageSwitch(offset) { function modalImageSwitch(offset) {
var galleryButtons = all_gallery_buttons(); const galleryButtons = all_gallery_buttons();
if (galleryButtons.length > 1) { if (galleryButtons.length > 1) {
var currentButton = selected_gallery_button(); const currentButton = selected_gallery_button();
var result = -1 let result = -1;
galleryButtons.forEach(function(v, i) { galleryButtons.forEach((v, i) => {
if (v == currentButton) result = i if (v == currentButton) result = i;
}) });
if (result != -1) { if (result != -1) {
nextButton = galleryButtons[negmod((result + offset), galleryButtons.length)] nextButton = galleryButtons[negmod((result + offset), galleryButtons.length)];
nextButton.click() nextButton.click();
const modalImage = gradioApp().getElementById("modalImage"); const modalImage = gradioApp().getElementById('modalImage');
const modal = gradioApp().getElementById("lightboxModal"); const modal = gradioApp().getElementById('lightboxModal');
modalImage.src = nextButton.children[0].src; modalImage.src = nextButton.children[0].src;
if (modalImage.style.display === 'none') modal.style.setProperty('background-image', `url(${modalImage.src})`) if (modalImage.style.display === 'none') modal.style.setProperty('background-image', `url(${modalImage.src})`);
setTimeout(() => modal.focus(), 10) setTimeout(() => modal.focus(), 10);
}
} }
}
} }
function saveImage(){ function saveImage() {
const tabTxt2Img = gradioApp().getElementById("tab_txt2img") const tabTxt2Img = gradioApp().getElementById('tab_txt2img');
const tabImg2Img = gradioApp().getElementById("tab_img2img") const tabImg2Img = gradioApp().getElementById('tab_img2img');
const saveTxt2Img = "save_txt2img" const saveTxt2Img = 'save_txt2img';
const saveImg2Img = "save_img2img" const saveImg2Img = 'save_img2img';
if (tabTxt2Img.style.display != "none") gradioApp().getElementById(saveTxt2Img).click() if (tabTxt2Img.style.display != 'none') gradioApp().getElementById(saveTxt2Img).click();
else if (tabImg2Img.style.display != "none") gradioApp().getElementById(saveImg2Img).click() else if (tabImg2Img.style.display != 'none') gradioApp().getElementById(saveImg2Img).click();
else console.error("missing implementation for saving modal of this type") else console.error('missing implementation for saving modal of this type');
} }
function modalSaveImage(event) { function modalSaveImage(event) {
saveImage() saveImage();
event.stopPropagation() event.stopPropagation();
} }
function modalNextImage(event) { function modalNextImage(event) {
modalImageSwitch(1) modalImageSwitch(1);
event.stopPropagation() event.stopPropagation();
} }
function modalPrevImage(event) { function modalPrevImage(event) {
modalImageSwitch(-1) modalImageSwitch(-1);
event.stopPropagation() event.stopPropagation();
} }
function modalKeyHandler(event) { function modalKeyHandler(event) {
switch (event.key) { switch (event.key) {
case "s": case 's':
saveImage() saveImage();
break; break;
case "ArrowLeft": case 'ArrowLeft':
modalPrevImage(event) modalPrevImage(event);
break; break;
case "ArrowRight": case 'ArrowRight':
modalNextImage(event) modalNextImage(event);
break; break;
case "Escape": case 'Escape':
closeModal(); closeModal();
break; break;
} }
} }
function setupImageForLightbox(e) { function setupImageForLightbox(e) {
if (e.dataset.modded) return; if (e.dataset.modded) return;
e.dataset.modded = true; e.dataset.modded = true;
e.style.cursor='pointer' e.style.cursor = 'pointer';
e.style.userSelect='none' e.style.userSelect = 'none';
var isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1 const isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
var event = isFirefox ? 'mousedown' : 'click' const event = isFirefox ? 'mousedown' : 'click';
e.addEventListener(event, function (evt) { e.addEventListener(event, (evt) => {
if (evt.button != 0) return; if (evt.button != 0) return;
initialZoom = (localStorage.getItem('modalZoom') || true) == 'yes' initialZoom = (localStorage.getItem('modalZoom') || true) == 'yes';
modalZoomSet(gradioApp().getElementById('modalImage'), initialZoom) modalZoomSet(gradioApp().getElementById('modalImage'), initialZoom);
evt.preventDefault() evt.preventDefault();
showModal(evt) showModal(evt);
}, true); }, true);
} }
function modalZoomSet(modalImage, enable) { function modalZoomSet(modalImage, enable) {
if (enable) modalImage.classList.add('modalImageFullscreen'); if (enable) modalImage.classList.add('modalImageFullscreen');
else modalImage.classList.remove('modalImageFullscreen'); else modalImage.classList.remove('modalImageFullscreen');
localStorage.setItem('modalZoom', enable ? 'yes' : 'no') localStorage.setItem('modalZoom', enable ? 'yes' : 'no');
} }
function modalZoomToggle(event) { function modalZoomToggle(event) {
modalImage = gradioApp().getElementById("modalImage"); modalImage = gradioApp().getElementById('modalImage');
modalZoomSet(modalImage, !modalImage.classList.contains('modalImageFullscreen')) modalZoomSet(modalImage, !modalImage.classList.contains('modalImageFullscreen'));
event.stopPropagation() event.stopPropagation();
} }
function modalTileImageToggle(event) { function modalTileImageToggle(event) {
const modalImage = gradioApp().getElementById("modalImage"); const modalImage = gradioApp().getElementById('modalImage');
const modal = gradioApp().getElementById("lightboxModal"); const modal = gradioApp().getElementById('lightboxModal');
const isTiling = modalImage.style.display === 'none'; const isTiling = modalImage.style.display === 'none';
if (isTiling) { if (isTiling) {
modalImage.style.display = 'block'; modalImage.style.display = 'block';
modal.style.setProperty('background-image', 'none') modal.style.setProperty('background-image', 'none');
} else { } else {
modalImage.style.display = 'none'; modalImage.style.display = 'none';
modal.style.setProperty('background-image', `url(${modalImage.src})`) modal.style.setProperty('background-image', `url(${modalImage.src})`);
} }
event.stopPropagation() event.stopPropagation();
} }
function galleryImageHandler(e) { function galleryImageHandler(e) {
e.onclick = showGalleryImage; e.onclick = showGalleryImage;
} }
onUiUpdate(function() { onUiUpdate(() => {
fullImg_preview = gradioApp().querySelectorAll('.gradio-gallery > div > img') fullImg_preview = gradioApp().querySelectorAll('.gradio-gallery > div > img');
if (fullImg_preview != null) fullImg_preview.forEach(setupImageForLightbox); if (fullImg_preview != null) fullImg_preview.forEach(setupImageForLightbox);
updateOnBackgroundChange(); updateOnBackgroundChange();
}) });
document.addEventListener("DOMContentLoaded", function() { document.addEventListener('DOMContentLoaded', () => {
//const modalFragment = document.createDocumentFragment(); // const modalFragment = document.createDocumentFragment();
const modal = document.createElement('div') const modal = document.createElement('div');
modal.onclick = closeModal; modal.onclick = closeModal;
modal.id = "lightboxModal"; modal.id = 'lightboxModal';
modal.tabIndex = 0 modal.tabIndex = 0;
modal.addEventListener('keydown', modalKeyHandler, true) modal.addEventListener('keydown', modalKeyHandler, true);
const modalControls = document.createElement('div') const modalControls = document.createElement('div');
modalControls.className = 'modalControls gradio-container'; modalControls.className = 'modalControls gradio-container';
modal.append(modalControls); modal.append(modalControls);
const modalZoom = document.createElement('span') const modalZoom = document.createElement('span');
modalZoom.className = 'modalZoom cursor'; modalZoom.className = 'modalZoom cursor';
modalZoom.innerHTML = '&#10529;' modalZoom.innerHTML = '&#10529;';
modalZoom.addEventListener('click', modalZoomToggle, true) modalZoom.addEventListener('click', modalZoomToggle, true);
modalZoom.title = "Toggle zoomed view"; modalZoom.title = 'Toggle zoomed view';
modalControls.appendChild(modalZoom) modalControls.appendChild(modalZoom);
const modalTileImage = document.createElement('span') const modalTileImage = document.createElement('span');
modalTileImage.className = 'modalTileImage cursor'; modalTileImage.className = 'modalTileImage cursor';
modalTileImage.innerHTML = '&#8862;' modalTileImage.innerHTML = '&#8862;';
modalTileImage.addEventListener('click', modalTileImageToggle, true) modalTileImage.addEventListener('click', modalTileImageToggle, true);
modalTileImage.title = "Preview tiling"; modalTileImage.title = 'Preview tiling';
modalControls.appendChild(modalTileImage) modalControls.appendChild(modalTileImage);
const modalSave = document.createElement("span") const modalSave = document.createElement('span');
modalSave.className = "modalSave cursor" modalSave.className = 'modalSave cursor';
modalSave.id = "modal_save" modalSave.id = 'modal_save';
modalSave.innerHTML = "&#x1F5AB;" modalSave.innerHTML = '&#x1F5AB;';
modalSave.addEventListener("click", modalSaveImage, true) modalSave.addEventListener('click', modalSaveImage, true);
modalSave.title = "Save Image(s)" modalSave.title = 'Save Image(s)';
modalControls.appendChild(modalSave) modalControls.appendChild(modalSave);
const modalClose = document.createElement('span') const modalClose = document.createElement('span');
modalClose.className = 'modalClose cursor'; modalClose.className = 'modalClose cursor';
modalClose.innerHTML = '&times;' modalClose.innerHTML = '&times;';
modalClose.onclick = closeModal; modalClose.onclick = closeModal;
modalClose.title = "Close image viewer"; modalClose.title = 'Close image viewer';
modalControls.appendChild(modalClose) modalControls.appendChild(modalClose);
const modalImage = document.createElement('img') const modalImage = document.createElement('img');
modalImage.id = 'modalImage'; modalImage.id = 'modalImage';
modalImage.onclick = closeModal; modalImage.onclick = closeModal;
modalImage.tabIndex = 0 modalImage.tabIndex = 0;
modalImage.addEventListener('keydown', modalKeyHandler, true) modalImage.addEventListener('keydown', modalKeyHandler, true);
modal.appendChild(modalImage) modal.appendChild(modalImage);
const modalPrev = document.createElement('a') const modalPrev = document.createElement('a');
modalPrev.className = 'modalPrev'; modalPrev.className = 'modalPrev';
modalPrev.innerHTML = '&#10094;' modalPrev.innerHTML = '&#10094;';
modalPrev.tabIndex = 0 modalPrev.tabIndex = 0;
modalPrev.addEventListener('click', modalPrevImage, true); modalPrev.addEventListener('click', modalPrevImage, true);
modalPrev.addEventListener('keydown', modalKeyHandler, true) modalPrev.addEventListener('keydown', modalKeyHandler, true);
modal.appendChild(modalPrev) modal.appendChild(modalPrev);
const modalNext = document.createElement('a') const modalNext = document.createElement('a');
modalNext.className = 'modalNext'; modalNext.className = 'modalNext';
modalNext.innerHTML = '&#10095;' modalNext.innerHTML = '&#10095;';
modalNext.tabIndex = 0 modalNext.tabIndex = 0;
modalNext.addEventListener('click', modalNextImage, true); modalNext.addEventListener('click', modalNextImage, true);
modalNext.addEventListener('keydown', modalKeyHandler, true) modalNext.addEventListener('keydown', modalKeyHandler, true);
modal.appendChild(modalNext) modal.appendChild(modalNext);
try { gradioApp().appendChild(modal); } try { gradioApp().appendChild(modal); } catch (e) { gradioApp().body.appendChild(modal); }
catch (e) { gradioApp().body.appendChild(modal); }
}); });

View File

@ -3,28 +3,27 @@
let lastHeadImg = null; let lastHeadImg = null;
let notificationButton = null; let notificationButton = null;
onUiUpdate(function(){ onUiUpdate(function () {
if (!notificationButton) { if (!notificationButton) {
notificationButton = gradioApp().getElementById('request_notifications') notificationButton = gradioApp().getElementById('request_notifications');
if (notificationButton) notificationButton.addEventListener('click', (evt) => Notification.requestPermission(), true); if (notificationButton) notificationButton.addEventListener('click', (evt) => Notification.requestPermission(), true);
} }
if (document.hasFocus()) return; // window is in focus so don't send notifications if (document.hasFocus()) return; // window is in focus so don't send notifications
const galleryPreviews = gradioApp().querySelectorAll('div[id^="tab_"][style*="display: block"] div[id$="_results"] .thumbnail-item > img'); const galleryPreviews = gradioApp().querySelectorAll('div[id^="tab_"][style*="display: block"] div[id$="_results"] .thumbnail-item > img');
if (!galleryPreviews) return; if (!galleryPreviews) return;
const headImg = galleryPreviews[0]?.src; const headImg = galleryPreviews[0]?.src;
if (!headImg || headImg == lastHeadImg || headImg.endsWith('logo.png')) return; if (!headImg || headImg == lastHeadImg || headImg.endsWith('logo.png')) return;
const audioNotification = gradioApp().querySelector('#audio_notification audio'); const audioNotification = gradioApp().querySelector('#audio_notification audio');
if (audioNotification) audioNotification.play(); if (audioNotification) audioNotification.play();
lastHeadImg = headImg; lastHeadImg = headImg;
const imgs = new Set(Array.from(galleryPreviews).map(img => img.src)); // Multiple copies of the images are in the DOM when one is selected const imgs = new Set(Array.from(galleryPreviews).map((img) => img.src)); // Multiple copies of the images are in the DOM when one is selected
const notification = new Notification( const notification = new Notification('SD.Next', {
'SD.Next', { body: `Generated ${imgs.size > 1 ? imgs.size - opts.return_grid : 1} image${imgs.size > 1 ? 's' : ''}`,
body: `Generated ${imgs.size > 1 ? imgs.size - opts.return_grid : 1} image${imgs.size > 1 ? 's' : ''}`, icon: headImg,
icon: headImg, image: headImg,
image: headImg } });
); notification.onclick = () => {
notification.onclick = () => { parent.focus();
parent.focus(); this.close();
this.close(); };
};
}); });

13
javascript/package.json Normal file
View File

@ -0,0 +1,13 @@
{
"name": "javascript",
"version": "0.0.1",
"description": "",
"main": "script.js",
"keywords": [],
"author": "Vladimir Mandic <mandic00@live.com>",
"license": "MIT",
"dependencies": {
"eslint": "^8.40.0",
"eslint-config-airbnb-base": "^15.0.0"
}
}

View File

@ -1,91 +1,92 @@
function gradioApp() { function gradioApp() {
const elems = document.getElementsByTagName('gradio-app') const elems = document.getElementsByTagName('gradio-app');
const elem = elems.length == 0 ? document : elems[0] const elem = elems.length === 0 ? document : elems[0];
if (elem !== document) elem.getElementById = function(id){ return document.getElementById(id) } if (elem !== document) elem.getElementById = function (id) { return document.getElementById(id); };
return elem.shadowRoot ? elem.shadowRoot : elem return elem.shadowRoot ? elem.shadowRoot : elem;
} }
function get_uiCurrentTab() { function get_uiCurrentTab() {
return gradioApp().querySelector('#tabs button.selected') return gradioApp().querySelector('#tabs button.selected');
} }
function get_uiCurrentTabContent() { function get_uiCurrentTabContent() {
return gradioApp().querySelector('.tabitem[id^=tab_]:not([style*="display: none"])') return gradioApp().querySelector('.tabitem[id^=tab_]:not([style*="display: none"])');
} }
uiUpdateCallbacks = [] uiUpdateCallbacks = [];
uiLoadedCallbacks = [] uiLoadedCallbacks = [];
uiTabChangeCallbacks = [] uiTabChangeCallbacks = [];
optionsChangedCallbacks = [] optionsChangedCallbacks = [];
let uiCurrentTab = null let uiCurrentTab = null;
function onUiUpdate(callback){ function onUiUpdate(callback) {
uiUpdateCallbacks.push(callback) uiUpdateCallbacks.push(callback);
} }
function onUiLoaded(callback){ function onUiLoaded(callback) {
uiLoadedCallbacks.push(callback) uiLoadedCallbacks.push(callback);
} }
function onUiTabChange(callback){ function onUiTabChange(callback) {
uiTabChangeCallbacks.push(callback) uiTabChangeCallbacks.push(callback);
} }
function onOptionsChanged(callback){ function onOptionsChanged(callback) {
optionsChangedCallbacks.push(callback) optionsChangedCallbacks.push(callback);
} }
function runCallback(x, m){ function runCallback(x, m) {
try { x(m) try {
} catch (e) { (console.error || console.log).call(console, e.message, e); } x(m);
} catch (e) { (console.error || console.log).call(console, e.message, e); }
} }
function executeCallbacks(queue, m) { function executeCallbacks(queue, m) {
queue.forEach(function(x){runCallback(x, m)}) queue.forEach((x) => { runCallback(x, m); });
} }
var executedOnLoaded = false; let executedOnLoaded = false;
document.addEventListener("DOMContentLoaded", function() { document.addEventListener('DOMContentLoaded', () => {
var mutationObserver = new MutationObserver(function(m){ const mutationObserver = new MutationObserver((m) => {
if(!executedOnLoaded && gradioApp().querySelector('#txt2img_prompt')){ if (!executedOnLoaded && gradioApp().querySelector('#txt2img_prompt')) {
executedOnLoaded = true; executedOnLoaded = true;
executeCallbacks(uiLoadedCallbacks); executeCallbacks(uiLoadedCallbacks);
} }
executeCallbacks(uiUpdateCallbacks, m); executeCallbacks(uiUpdateCallbacks, m);
const newTab = get_uiCurrentTab(); const newTab = get_uiCurrentTab();
if ( newTab && ( newTab !== uiCurrentTab ) ) { if (newTab && (newTab !== uiCurrentTab)) {
uiCurrentTab = newTab; uiCurrentTab = newTab;
executeCallbacks(uiTabChangeCallbacks); executeCallbacks(uiTabChangeCallbacks);
} }
}); });
mutationObserver.observe( gradioApp(), { childList:true, subtree:true }) mutationObserver.observe(gradioApp(), { childList: true, subtree: true });
}); });
/** /**
* Add a ctrl+enter as a shortcut to start a generation * Add a ctrl+enter as a shortcut to start a generation
*/ */
document.addEventListener('keydown', function(e) { document.addEventListener('keydown', (e) => {
var handled = false; let handled = false;
if (e.key !== undefined) { if (e.key !== undefined) {
if((e.key == "Enter" && (e.metaKey || e.ctrlKey || e.altKey))) handled = true; if ((e.key === 'Enter' && (e.metaKey || e.ctrlKey || e.altKey))) handled = true;
} else if (e.keyCode !== undefined) { } else if (e.keyCode !== undefined) {
if((e.keyCode == 13 && (e.metaKey || e.ctrlKey || e.altKey))) handled = true; if ((e.keyCode === 13 && (e.metaKey || e.ctrlKey || e.altKey))) handled = true;
} }
if (handled) { if (handled) {
button = get_uiCurrentTabContent().querySelector('button[id$=_generate]'); button = get_uiCurrentTabContent().querySelector('button[id$=_generate]');
if (button) button.click(); if (button) button.click();
e.preventDefault(); e.preventDefault();
} }
}) });
/** /**
* checks that a UI element is not in another hidden element or tab content * checks that a UI element is not in another hidden element or tab content
*/ */
function uiElementIsVisible(el) { function uiElementIsVisible(el) {
let isVisible = !el.closest('.\\!hidden'); let isVisible = !el.closest('.\\!hidden');
if (!isVisible) return false;
while (isVisible = el.closest('.tabitem')?.style.display !== 'none') {
if (!isVisible) return false; if (!isVisible) return false;
while( isVisible = el.closest('.tabitem')?.style.display !== 'none' ) { if (el.parentElement) el = el.parentElement;
if ( ! isVisible ) return false; else break;
else if ( el.parentElement ) el = el.parentElement }
else break; return isVisible;
}
return isVisible;
} }

View File

@ -1,280 +1,284 @@
// various functions for interaction with ui.py not large enough to warrant putting them in separate files /* global gradioApp */
function set_theme(theme){ let opts = {};
gradioURL = window.location.href
if (!gradioURL.includes('?__theme=')) window.location.replace(gradioURL + '?__theme=' + theme); function set_theme(theme) {
const gradioURL = window.location.href;
if (!gradioURL.includes('?__theme=')) window.location.replace(`${gradioURL}?__theme=${theme}`);
} }
function all_gallery_buttons() { function all_gallery_buttons() {
var allGalleryButtons = gradioApp().querySelectorAll('[style="display: block;"].tabitem div[id$=_gallery].gradio-gallery .thumbnails > .thumbnail-item.thumbnail-small'); const allGalleryButtons = gradioApp().querySelectorAll('[style="display: block;"].tabitem div[id$=_gallery].gradio-gallery .thumbnails > .thumbnail-item.thumbnail-small');
var visibleGalleryButtons = []; const visibleGalleryButtons = [];
allGalleryButtons.forEach(function(elem) { allGalleryButtons.forEach((elem) => {
if (elem.parentElement.offsetParent) visibleGalleryButtons.push(elem); if (elem.parentElement.offsetParent) visibleGalleryButtons.push(elem);
}) });
return visibleGalleryButtons; return visibleGalleryButtons;
} }
function selected_gallery_button() { function selected_gallery_button() {
var allCurrentButtons = gradioApp().querySelectorAll('[style="display: block;"].tabitem div[id$=_gallery].gradio-gallery .thumbnail-item.thumbnail-small.selected'); const allCurrentButtons = gradioApp().querySelectorAll('[style="display: block;"].tabitem div[id$=_gallery].gradio-gallery .thumbnail-item.thumbnail-small.selected');
var visibleCurrentButton = null; let visibleCurrentButton = null;
allCurrentButtons.forEach(function(elem) { allCurrentButtons.forEach((elem) => {
if (elem.parentElement.offsetParent) visibleCurrentButton = elem; if (elem.parentElement.offsetParent) visibleCurrentButton = elem;
}) });
return visibleCurrentButton; return visibleCurrentButton;
} }
function selected_gallery_index(){ function selected_gallery_index() {
var buttons = all_gallery_buttons(); const buttons = all_gallery_buttons();
var button = selected_gallery_button(); const button = selected_gallery_button();
var result = -1 let result = -1;
buttons.forEach(function(v, i){ if(v==button) { result = i } }) buttons.forEach((v, i) => { if (v === button) { result = i; } });
return result return result;
} }
function extract_image_from_gallery(gallery){ function extract_image_from_gallery(gallery) {
if (gallery.length == 0) return [null]; if (gallery.length === 0) return [null];
if (gallery.length == 1) return [gallery[0]]; if (gallery.length === 1) return [gallery[0]];
index = selected_gallery_index() let index = selected_gallery_index();
if (index < 0 || index >= gallery.length) index = 0; if (index < 0 || index >= gallery.length) index = 0;
return [gallery[index]]; return [gallery[index]];
} }
function args_to_array(args){ function args_to_array(args) {
res = [] const res = [];
for(var i=0;i<args.length;i++) res.push(args[i]) for (let i = 0; i < args.length; i++) res.push(args[i]);
return res return res;
} }
function switch_to_txt2img(){ function switch_to_txt2img(...args) {
gradioApp().querySelector('#tabs').querySelectorAll('button')[0].click(); gradioApp().querySelector('#tabs').querySelectorAll('button')[0].click();
return args_to_array(arguments); return args_to_array(args);
} }
function switch_to_img2img_tab(no){ function switch_to_img2img_tab(no) {
gradioApp().querySelector('#tabs').querySelectorAll('button')[1].click(); gradioApp().querySelector('#tabs').querySelectorAll('button')[1].click();
gradioApp().getElementById('mode_img2img').querySelectorAll('button')[no].click(); gradioApp().getElementById('mode_img2img').querySelectorAll('button')[no].click();
} }
function switch_to_img2img(){ function switch_to_img2img(...args) {
switch_to_img2img_tab(0); switch_to_img2img_tab(0);
return args_to_array(arguments); return args_to_array(args);
} }
function switch_to_sketch(){ function switch_to_sketch(...args) {
switch_to_img2img_tab(1); switch_to_img2img_tab(1);
return args_to_array(arguments); return args_to_array(args);
} }
function switch_to_inpaint(){ function switch_to_inpaint(...args) {
switch_to_img2img_tab(2); switch_to_img2img_tab(2);
return args_to_array(arguments); return args_to_array(args);
} }
function switch_to_inpaint_sketch(){ function switch_to_inpaint_sketch(...args) {
switch_to_img2img_tab(3); switch_to_img2img_tab(3);
return args_to_array(arguments); return args_to_array(args);
} }
function switch_to_inpaint(){ function switch_to_extras(...args) {
gradioApp().querySelector('#tabs').querySelectorAll('button')[1].click(); gradioApp().querySelector('#tabs').querySelectorAll('button')[2].click();
gradioApp().getElementById('mode_img2img').querySelectorAll('button')[2].click(); return args_to_array(args);
return args_to_array(arguments);
} }
function switch_to_extras(){ function get_tab_index(tabId) {
gradioApp().querySelector('#tabs').querySelectorAll('button')[2].click(); let res = 0;
return args_to_array(arguments); gradioApp().getElementById(tabId).querySelector('div').querySelectorAll('button')
.forEach((button, i) => {
if (button.className.indexOf('selected') !== -1) res = i;
});
return res;
} }
function get_tab_index(tabId){ function create_tab_index_args(tabId, args) {
var res = 0 const res = [];
gradioApp().getElementById(tabId).querySelector('div').querySelectorAll('button').forEach(function(button, i){ for (let i = 0; i < args.length; i++) res.push(args[i]);
if(button.className.indexOf('selected') != -1) res = i res[0] = get_tab_index(tabId);
}) return res;
return res
} }
function create_tab_index_args(tabId, args){ function get_img2img_tab_index(...args) {
var res = [] const res = args_to_array(args);
for(var i=0; i<args.length; i++) res.push(args[i]) res.splice(-2);
res[0] = get_tab_index(tabId) res[0] = get_tab_index('mode_img2img');
return res return res;
} }
function get_img2img_tab_index() { function create_submit_args(args) {
let res = args_to_array(arguments) const res = [];
res.splice(-2) for (let i = 0; i < args.length; i++) res.push(args[i]);
res[0] = get_tab_index('mode_img2img') // As it is currently, txt2img and img2img send back the previous output args (txt2img_gallery, generation_info, html_info) whenever you generate a new image.
return res // This can lead to uploading a huge gallery of previously generated images, which leads to an unnecessary delay between submitting and beginning to generate.
// I don't know why gradio is sending outputs along with inputs, but we can prevent sending the image gallery here, which seems to be an issue for some.
// If gradio at some point stops sending outputs, this may break something
if (Array.isArray(res[res.length - 3])) res[res.length - 3] = null;
return res;
} }
function create_submit_args(args){ function showSubmitButtons(tabname, show) {
res = [] gradioApp().getElementById(`${tabname}_interrupt`).style.display = show ? 'none' : 'block';
for(var i=0;i<args.length;i++) res.push(args[i]) gradioApp().getElementById(`${tabname}_skip`).style.display = show ? 'none' : 'block';
// As it is currently, txt2img and img2img send back the previous output args (txt2img_gallery, generation_info, html_info) whenever you generate a new image. // gradioApp().getElementById(tabname+'_interrupt').style.display = "block"
// This can lead to uploading a huge gallery of previously generated images, which leads to an unnecessary delay between submitting and beginning to generate. // gradioApp().getElementById(tabname+'_skip').style.display = "block"
// I don't know why gradio is sending outputs along with inputs, but we can prevent sending the image gallery here, which seems to be an issue for some.
// If gradio at some point stops sending outputs, this may break something
if(Array.isArray(res[res.length - 3])) res[res.length - 3] = null
return res
} }
function showSubmitButtons(tabname, show){ function submit(...args) {
gradioApp().getElementById(tabname+'_interrupt').style.display = show ? "none" : "block" rememberGallerySelection('txt2img_gallery');
gradioApp().getElementById(tabname+'_skip').style.display = show ? "none" : "block" showSubmitButtons('txt2img', false);
// gradioApp().getElementById(tabname+'_interrupt').style.display = "block" const id = randomId();
// gradioApp().getElementById(tabname+'_skip').style.display = "block" const atEnd = () => showSubmitButtons('txt2img', true);
requestProgress(id, gradioApp().getElementById('txt2img_gallery_container'), gradioApp().getElementById('txt2img_gallery'), atEnd);
const res = create_submit_args(args);
res[0] = id;
return res;
} }
function submit(){ function submit_img2img(...args) {
rememberGallerySelection('txt2img_gallery') rememberGallerySelection('img2img_gallery');
showSubmitButtons('txt2img', false) showSubmitButtons('img2img', false);
const id = randomId() const id = randomId();
const atEnd = () => showSubmitButtons('txt2img', true) const atEnd = () => showSubmitButtons('img2img', true);
requestProgress(id, gradioApp().getElementById('txt2img_gallery_container'), gradioApp().getElementById('txt2img_gallery'), atEnd) requestProgress(id, gradioApp().getElementById('img2img_gallery_container'), gradioApp().getElementById('img2img_gallery'), atEnd);
var res = create_submit_args(arguments) const res = create_submit_args(args);
res[0] = id res[0] = id;
return res res[1] = get_tab_index('mode_img2img');
return res;
} }
function submit_img2img(){ function modelmerger(...args) {
rememberGallerySelection('img2img_gallery') const id = randomId();
showSubmitButtons('img2img', false) requestProgress(id, gradioApp().getElementById('modelmerger_results_panel'), null);
const id = randomId() const res = create_submit_args(args);
const atEnd = () => showSubmitButtons('img2img', true) res[0] = id;
requestProgress(id, gradioApp().getElementById('img2img_gallery_container'), gradioApp().getElementById('img2img_gallery'), atEnd) return res;
var res = create_submit_args(arguments)
res[0] = id
res[1] = get_tab_index('mode_img2img')
return res
}
function modelmerger(){
const id = randomId()
requestProgress(id, gradioApp().getElementById('modelmerger_results_panel'), null)
var res = create_submit_args(arguments)
res[0] = id
return res
} }
function ask_for_style_name(_, prompt_text, negative_prompt_text) { function ask_for_style_name(_, prompt_text, negative_prompt_text) {
name_ = prompt('Style name:') const name = prompt('Style name:');
return [name_, prompt_text, negative_prompt_text] return [name, prompt_text, negative_prompt_text];
} }
function confirm_clear_prompt(prompt, negative_prompt) { function confirm_clear_prompt(prompt, negative_prompt) {
prompt = "" prompt = '';
negative_prompt = "" negative_prompt = '';
return [prompt, negative_prompt] return [prompt, negative_prompt];
} }
promptTokecountUpdateFuncs = {} const promptTokecountUpdateFuncs = {};
function recalculatePromptTokens(name){ function recalculatePromptTokens(name) {
if(promptTokecountUpdateFuncs[name]){ if (promptTokecountUpdateFuncs[name]) {
promptTokecountUpdateFuncs[name]() promptTokecountUpdateFuncs[name]();
} }
} }
function recalculate_prompts_txt2img(){ function recalculate_prompts_txt2img(...args) {
recalculatePromptTokens('txt2img_prompt') recalculatePromptTokens('txt2img_prompt');
recalculatePromptTokens('txt2img_neg_prompt') recalculatePromptTokens('txt2img_neg_prompt');
return args_to_array(arguments); return args_to_array(args);
} }
function recalculate_prompts_img2img(){ function recalculate_prompts_img2img(...args) {
recalculatePromptTokens('img2img_prompt') recalculatePromptTokens('img2img_prompt');
recalculatePromptTokens('img2img_neg_prompt') recalculatePromptTokens('img2img_neg_prompt');
return args_to_array(arguments); return args_to_array(args);
} }
opts = {} function recalculate_prompts_inpaint(...args) {
onUiUpdate(function(){ recalculatePromptTokens('img2img_prompt');
if(Object.keys(opts).length != 0) return; recalculatePromptTokens('img2img_neg_prompt');
json_elem = gradioApp().getElementById('settings_json') return args_to_array(args);
if(json_elem == null) return; }
var textarea = json_elem.querySelector('textarea')
var jsdata = textarea.value
opts = JSON.parse(jsdata)
executeCallbacks(optionsChangedCallbacks);
Object.defineProperty(textarea, 'value', {
set: function(newValue) {
var valueProp = Object.getOwnPropertyDescriptor(HTMLTextAreaElement.prototype, 'value');
var oldValue = valueProp.get.call(textarea);
valueProp.set.call(textarea, newValue);
if (oldValue != newValue) opts = JSON.parse(textarea.value)
executeCallbacks(optionsChangedCallbacks);
},
get: function() {
var valueProp = Object.getOwnPropertyDescriptor(HTMLTextAreaElement.prototype, 'value');
return valueProp.get.call(textarea);
}
});
json_elem.parentElement.style.display="none"
function registerTextarea(id, id_counter, id_button){
var prompt = gradioApp().getElementById(id)
var counter = gradioApp().getElementById(id_counter)
var textarea = gradioApp().querySelector("#" + id + " > label > textarea");
if(counter.parentElement == prompt.parentElement) return
prompt.parentElement.insertBefore(counter, prompt)
prompt.parentElement.style.position = "relative"
promptTokecountUpdateFuncs[id] = function(){ update_token_counter(id_button); }
textarea.addEventListener("input", promptTokecountUpdateFuncs[id]);
}
registerTextarea('txt2img_prompt', 'txt2img_token_counter', 'txt2img_token_button')
registerTextarea('txt2img_neg_prompt', 'txt2img_negative_token_counter', 'txt2img_negative_token_button')
registerTextarea('img2img_prompt', 'img2img_token_counter', 'img2img_token_button')
registerTextarea('img2img_neg_prompt', 'img2img_negative_token_counter', 'img2img_negative_token_button')
show_all_pages = gradioApp().getElementById('settings_show_all_pages')
settings_tabs = gradioApp().querySelector('#settings div')
if(show_all_pages && settings_tabs){
settings_tabs.appendChild(show_all_pages)
show_all_pages.onclick = function(){
gradioApp().querySelectorAll('#settings > div').forEach(function(elem){
elem.style.display = "block";
})
}
}
})
onOptionsChanged(function(){ onUiUpdate(() => {
elem = gradioApp().getElementById('sd_checkpoint_hash') if (Object.keys(opts).length !== 0) return;
sd_checkpoint_hash = opts.sd_checkpoint_hash || "" const json_elem = gradioApp().getElementById('settings_json');
shorthash = sd_checkpoint_hash.substr(0,10) if (!json_elem) return;
json_elem.parentElement.style.display = 'none';
const textarea = json_elem.querySelector('textarea');
const jsdata = textarea.value;
opts = JSON.parse(jsdata);
executeCallbacks(optionsChangedCallbacks);
if(elem && elem.textContent != shorthash){ Object.defineProperty(textarea, 'value', {
elem.textContent = shorthash set(newValue) {
elem.title = sd_checkpoint_hash const valueProp = Object.getOwnPropertyDescriptor(HTMLTextAreaElement.prototype, 'value');
elem.href = "https://google.com/search?q=" + sd_checkpoint_hash const oldValue = valueProp.get.call(textarea);
} valueProp.set.call(textarea, newValue);
}) if (oldValue !== newValue) opts = JSON.parse(textarea.value);
executeCallbacks(optionsChangedCallbacks);
},
get() {
const valueProp = Object.getOwnPropertyDescriptor(HTMLTextAreaElement.prototype, 'value');
return valueProp.get.call(textarea);
},
});
let txt2img_textarea, img2img_textarea = undefined; function registerTextarea(id, id_counter, id_button) {
let wait_time = 800 const prompt = gradioApp().getElementById(id);
let token_timeouts = {}; const counter = gradioApp().getElementById(id_counter);
const localTextarea = gradioApp().querySelector(`#${id} > label > textarea`);
if (counter.parentElement === prompt.parentElement) return;
prompt.parentElement.insertBefore(counter, prompt);
prompt.parentElement.style.position = 'relative';
promptTokecountUpdateFuncs[id] = () => { update_token_counter(id_button); };
localTextarea.addEventListener('input', promptTokecountUpdateFuncs[id]);
}
sort_ui_elements();
registerTextarea('txt2img_prompt', 'txt2img_token_counter', 'txt2img_token_button');
registerTextarea('txt2img_neg_prompt', 'txt2img_negative_token_counter', 'txt2img_negative_token_button');
registerTextarea('img2img_prompt', 'img2img_token_counter', 'img2img_token_button');
registerTextarea('img2img_neg_prompt', 'img2img_negative_token_counter', 'img2img_negative_token_button');
const show_all_pages = gradioApp().getElementById('settings_show_all_pages');
const settings_tabs = gradioApp().querySelector('#settings div');
if (show_all_pages && settings_tabs) {
settings_tabs.appendChild(show_all_pages);
show_all_pages.onclick = () => {
gradioApp().querySelectorAll('#settings > div').forEach((elem) => {
elem.style.display = 'block';
});
};
}
});
onOptionsChanged(() => {
const elem = gradioApp().getElementById('sd_checkpoint_hash');
const sd_checkpoint_hash = opts.sd_checkpoint_hash || '';
const shorthash = sd_checkpoint_hash.substr(0, 10);
if (elem && elem.textContent !== shorthash) {
elem.textContent = shorthash;
elem.title = sd_checkpoint_hash;
elem.href = `https://google.com/search?q=${sd_checkpoint_hash}`;
}
});
let txt2img_textarea;
let img2img_textarea;
const wait_time = 800;
const token_timeouts = {};
function update_txt2img_tokens(...args) { function update_txt2img_tokens(...args) {
update_token_counter("txt2img_token_button") update_token_counter('txt2img_token_button');
if (args.length == 2) if (args.length === 2) return args[0];
return args[0] return args;
return args;
} }
function update_img2img_tokens(...args) { function update_img2img_tokens(...args) {
update_token_counter("img2img_token_button") update_token_counter('img2img_token_button');
if (args.length == 2) if (args.length === 2) return args[0];
return args[0] return args;
return args;
} }
function getTranslation(...args) { function getTranslation(...args) {
return null return null;
} }
function update_token_counter(button_id) { function update_token_counter(button_id) {
if (token_timeouts[button_id]) if (token_timeouts[button_id]) clearTimeout(token_timeouts[button_id]);
clearTimeout(token_timeouts[button_id]); token_timeouts[button_id] = setTimeout(() => gradioApp().getElementById(button_id)?.click(), wait_time);
token_timeouts[button_id] = setTimeout(() => gradioApp().getElementById(button_id)?.click(), wait_time);
} }
function monitor_server_status() { function monitor_server_status() {
@ -298,102 +302,104 @@ function monitor_server_status() {
document.close(); document.close();
} }
function restart_reload(){ function restart_reload() {
document.body.style = "background: #222222; font-size: 1rem; font-family:monospace; margin-top:20%; color:lightgray; text-align:center" document.body.style = 'background: #222222; font-size: 1rem; font-family:monospace; margin-top:20%; color:lightgray; text-align:center';
document.body.innerHTML = "<h1>Server shutdown in progress...</h1>" document.body.innerHTML = '<h1>Server shutdown in progress...</h1>';
fetch('http://127.0.0.1:7860/sdapi/v1/progress') fetch('http://127.0.0.1:7860/sdapi/v1/progress')
.then((res) => setTimeout(restart_reload, 1000)) .then((res) => setTimeout(restart_reload, 1000))
.catch((e) => setTimeout(monitor_server_status, 500)) .catch((e) => setTimeout(monitor_server_status, 500));
return [] return [];
} }
// Simulate an `input` DOM event for Gradio Textbox component. Needed after you edit its contents in javascript, otherwise your edits function updateInput(target) {
// will only visible on web page and not sent to python. const e = new Event('input', { bubbles: true });
function updateInput(target){ Object.defineProperty(e, 'target', { value: target });
let e = new Event("input", { bubbles: true }) target.dispatchEvent(e);
Object.defineProperty(e, "target", {value: target})
target.dispatchEvent(e);
} }
var desiredCheckpointName = null; let desiredCheckpointName = null;
function selectCheckpoint(name){ function selectCheckpoint(name) {
desiredCheckpointName = name; desiredCheckpointName = name;
gradioApp().getElementById('change_checkpoint').click() gradioApp().getElementById('change_checkpoint').click();
} }
function updateImg2imgResizeToTextAfterChangingImage(){ function currentImg2imgSourceResolution(_a, _b, scaleBy) {
// At the time this is called from gradio, the image has no yet been replaced. const img = gradioApp().querySelector('#mode_img2img > div[style="display: block;"] img');
// There may be a better solution, but this is simple and straightforward so I'm going with it. return img ? [img.naturalWidth, img.naturalHeight, scaleBy] : [0, 0, scaleBy];
setTimeout(function() { }
gradioApp().getElementById('img2img_update_resize_to').click()
}, 500);
return [] function updateImg2imgResizeToTextAfterChangingImage() {
setTimeout(() => gradioApp().getElementById('img2img_update_resize_to').click(), 500);
return [];
} }
function create_theme_element() { function create_theme_element() {
el = document.createElement('img'); const el = document.createElement('img');
el.id = 'theme-preview'; el.id = 'theme-preview';
el.className = 'theme-preview'; el.className = 'theme-preview';
el.onclick = () => el.style.display = 'none'; el.onclick = () => { el.style.display = 'none'; };
document.body.appendChild(el); document.body.appendChild(el);
return el; return el;
} }
function sort_ui_elements() {
const tabs = gradioApp().getElementById('tabs');
const scripts = gradioApp().getElementById('scripts_alwayson');
console.log('HERE', opts, tabs, scripts);
}
function preview_theme() { function preview_theme() {
const name = gradioApp().getElementById('setting_gradio_theme').querySelectorAll('input')?.[0].value || ''; const name = gradioApp().getElementById('setting_gradio_theme').querySelectorAll('input')?.[0].value || '';
if (name === 'black-orange' || name.startsWith('gradio/')) { if (name === 'black-orange' || name.startsWith('gradio/')) {
el = document.getElementById('theme-preview') || create_theme_element(); const el = document.getElementById('theme-preview') || create_theme_element();
el.style.display = el.style.display === 'block' ? 'none' : 'block'; el.style.display = el.style.display === 'block' ? 'none' : 'block';
if (name === 'black-orange') el.src = '/file=javascript/black-orange.jpg'; if (name === 'black-orange') el.src = '/file=javascript/black-orange.jpg';
else el.src = `/file=javascript/${name.replace('/', '-')}.jpg`; else el.src = `/file=javascript/${name.replace('/', '-')}.jpg`;
} else { } else {
fetch('/file=javascript/themes.json') fetch('/file=javascript/themes.json')
.then((r) => r.json()) .then((r) => r.json())
.then(themes => { .then((themes) => {
theme = themes.find((t)=> t.id === name); const theme = themes.find((t) => t.id === name);
window.open(theme.subdomain, '_blank'); window.open(theme.subdomain, '_blank');
}); });
} }
} }
function reconnect_ui() { function reconnect_ui() {
const api_logo = Array.from(gradioApp().querySelectorAll("img")).filter((el) => el?.src?.endsWith('api-logo.svg')) const api_logo = Array.from(gradioApp().querySelectorAll('img')).filter((el) => el?.src?.endsWith('api-logo.svg'));
if (api_logo.length > 0) api_logo[0].remove() if (api_logo.length > 0) api_logo[0].remove();
const el1 = gradioApp().getElementById('txt2img_gallery_container') const el1 = gradioApp().getElementById('txt2img_gallery_container');
const el2 = gradioApp().getElementById('txt2img_gallery') const el2 = gradioApp().getElementById('txt2img_gallery');
const task_id = localStorage.getItem('task') const task_id = localStorage.getItem('task');
if (!el1 || !el2) return if (!el1 || !el2) return;
else clearInterval(start_check) clearInterval(start_check);
if (task_id) { if (task_id) {
console.debug('task check:', task_id) console.debug('task check:', task_id);
rememberGallerySelection('txt2img_gallery') rememberGallerySelection('txt2img_gallery');
showSubmitButtons('txt2img', false) showSubmitButtons('txt2img', false);
const atEnd = () => showSubmitButtons('txt2img', true) const atEnd = () => showSubmitButtons('txt2img', true);
requestProgress(task_id, el1, el2, atEnd, null, true) requestProgress(task_id, el1, el2, atEnd, null, true);
} }
sd_model = gradioApp().getElementById("setting_sd_model_checkpoint") const sd_model = gradioApp().getElementById('setting_sd_model_checkpoint');
let loadingStarted = 0; let loadingStarted = 0;
let loadingMonitor = 0; let loadingMonitor = 0;
const sd_model_callback = () => { const sd_model_callback = () => {
loading = sd_model.querySelector(".eta-bar") const loading = sd_model.querySelector('.eta-bar');
if (!loading) { if (!loading) {
loadingStarted = 0 loadingStarted = 0;
clearInterval(loadingMonitor) clearInterval(loadingMonitor);
} else { } else if (loadingStarted === 0) {
if (loadingStarted === 0) { loadingStarted = Date.now();
loadingStarted = Date.now(); loadingMonitor = setInterval(() => {
loadingMonitor = setInterval(() => { const elapsed = Date.now() - loadingStarted;
elapsed = Date.now() - loadingStarted; if (elapsed > 3000 && loading) loading.style.display = 'none';
if (elapsed > 3000 && loading) loading.style.display = 'none'; }, 5000);
}, 5000);
}
} }
}; };
const sd_model_observer = new MutationObserver(sd_model_callback); const sd_model_observer = new MutationObserver(sd_model_callback);
sd_model_observer.observe(sd_model, { attributes: true, childList: true, subtree: true }); sd_model_observer.observe(sd_model, { attributes: true, childList: true, subtree: true });
} }
var start_check = setInterval(reconnect_ui, 50); const start_check = setInterval(reconnect_ui, 50);

View File

@ -589,8 +589,8 @@ def save_image(image, path, basename, seed=None, prompt=None, extension='jpg', i
image.already_saved_as = fullfn image.already_saved_as = fullfn
if opts.save_txt and len(exifinfo_data) > 0: if opts.save_txt and len(exifinfo_data) > 0:
filename_txt = f"{filename}.txt" txt_fullfn = f"{filename}.txt"
with open(filename_txt, "w", encoding="utf8") as file: with open(txt_fullfn, "w", encoding="utf8") as file:
file.write(exifinfo_data + "\n") file.write(exifinfo_data + "\n")
else: else:
txt_fullfn = None txt_fullfn = None

View File

@ -308,11 +308,14 @@ class ScriptRunner:
inputs_alwayson += [script.alwayson for _ in controls] inputs_alwayson += [script.alwayson for _ in controls]
script.args_to = len(inputs) script.args_to = len(inputs)
for script in self.alwayson_scripts: with gr.Group(elem_id='scripts_alwayson'):
with gr.Group() as group: for script in self.alwayson_scripts:
create_script_ui(script, inputs, inputs_alwayson) elem_id = f'script_{"txt2img" if script.is_txt2img else "img2img"}_{script.title().lower().replace(" ", "_")}'
print(elem_id)
with gr.Group(elem_id=elem_id) as group:
create_script_ui(script, inputs, inputs_alwayson)
script.group = group
script.group = group
dropdown = gr.Dropdown(label="Script", elem_id="script_list", choices=["None"] + self.titles, value="None", type="index") dropdown = gr.Dropdown(label="Script", elem_id="script_list", choices=["None"] + self.titles, value="None", type="index")
inputs[0] = dropdown inputs[0] = dropdown
for script in self.selectable_scripts: for script in self.selectable_scripts:

View File

@ -16,7 +16,7 @@ class ScriptPostprocessingForMainUI(scripts.Script):
self.postprocessing_controls = self.script.ui() self.postprocessing_controls = self.script.ui()
return self.postprocessing_controls.values() return self.postprocessing_controls.values()
def postprocess_image(self, p, script_pp, *args): def postprocess_image(self, p, script_pp, *args): # pylint: disable=arguments-differ
args_dict = {k: v for k, v in zip(self.postprocessing_controls, args)} args_dict = {k: v for k, v in zip(self.postprocessing_controls, args)}
pp = scripts_postprocessing.PostprocessedImage(script_pp.image) pp = scripts_postprocessing.PostprocessedImage(script_pp.image)
@ -32,7 +32,7 @@ def create_auto_preprocessing_script_data():
script = next(iter([x for x in scripts.postprocessing_scripts_data if x.script_class.name == name]), None) script = next(iter([x for x in scripts.postprocessing_scripts_data if x.script_class.name == name]), None)
if script is None: if script is None:
continue continue
constructor = lambda s=script: ScriptPostprocessingForMainUI(s.script_class()) constructor = lambda s=script: ScriptPostprocessingForMainUI(s.script_class()) # pylint: disable=unnecessary-lambda-assignment
res.append(scripts.ScriptClassData(script_class=constructor, path=script.path, basedir=script.basedir, module=script.module)) res.append(scripts.ScriptClassData(script_class=constructor, path=script.path, basedir=script.basedir, module=script.module))
return res return res

View File

@ -4,7 +4,6 @@ import time
import shutil import shutil
import errno import errno
import html import html
from datetime import datetime
import git import git
import gradio as gr import gradio as gr
from modules import extensions, shared, paths, errors from modules import extensions, shared, paths, errors

2
wiki

@ -1 +1 @@
Subproject commit de3e442f4b8d49de2daa6a74fc955bef20e35cec Subproject commit d420606fc4f9735aa0a4d31f6e5ef18429508ab9