488
ui/index.html
@ -200,33 +200,6 @@
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 2px 0;
|
padding: 2px 0;
|
||||||
}
|
}
|
||||||
.prompt-modifier-tag {
|
|
||||||
border: 1px solid rgb(10, 0, 24);
|
|
||||||
border-radius: 4px;
|
|
||||||
padding: 0pt 3pt;
|
|
||||||
margin-right: 2pt;
|
|
||||||
cursor: pointer;
|
|
||||||
display: inline;
|
|
||||||
background: rgb(163, 163, 163);
|
|
||||||
color: black;
|
|
||||||
line-height: 25pt;
|
|
||||||
float: left;
|
|
||||||
font-size: 9pt;
|
|
||||||
}
|
|
||||||
.prompt-modifier-tag:hover {
|
|
||||||
background: black;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
#editor-modifiers-entries .prompt-modifier-tag {
|
|
||||||
background: #110f0f;
|
|
||||||
color: rgb(212, 212, 212);
|
|
||||||
margin-bottom: 4pt;
|
|
||||||
font-size: 10pt;
|
|
||||||
}
|
|
||||||
#editor-modifiers-entries .prompt-modifier-tag:hover {
|
|
||||||
background: rgb(163, 163, 163);
|
|
||||||
color: black;
|
|
||||||
}
|
|
||||||
#editor-modifiers .editor-modifiers-leaf {
|
#editor-modifiers .editor-modifiers-leaf {
|
||||||
padding-top: 10pt;
|
padding-top: 10pt;
|
||||||
padding-bottom: 10pt;
|
padding-bottom: 10pt;
|
||||||
@ -271,6 +244,221 @@
|
|||||||
height: 23px;
|
height: 23px;
|
||||||
transform: translateY(25%);
|
transform: translateY(25%);
|
||||||
}
|
}
|
||||||
|
.modifier-card {
|
||||||
|
box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);
|
||||||
|
transition: 0.1s;
|
||||||
|
border-radius: 7px;
|
||||||
|
margin: 3pt 3pt;
|
||||||
|
float: left;
|
||||||
|
width: 8em;
|
||||||
|
height: 11.5em;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
grid-template-rows: 8em 3.5em;
|
||||||
|
gap: 0px 0px;
|
||||||
|
grid-auto-flow: row;
|
||||||
|
grid-template-areas:
|
||||||
|
"modifier-card-image-container"
|
||||||
|
"modifier-card-container";
|
||||||
|
border: 2px solid rgba(255, 255, 255, .05);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.modifier-card-size_5 {
|
||||||
|
width: 18em;
|
||||||
|
grid-template-rows: 18em 3.5em;
|
||||||
|
height: 21.5em;
|
||||||
|
}
|
||||||
|
.modifier-card-size_5 .modifier-card-image-overlay {
|
||||||
|
font-size: 8em;
|
||||||
|
}
|
||||||
|
.modifier-card-size_4 {
|
||||||
|
width: 14em;
|
||||||
|
grid-template-rows: 14em 3.5em;
|
||||||
|
height: 17.5em;
|
||||||
|
}
|
||||||
|
.modifier-card-size_4 .modifier-card-image-overlay {
|
||||||
|
font-size: 7em;
|
||||||
|
}
|
||||||
|
.modifier-card-size_3 {
|
||||||
|
width: 11em;
|
||||||
|
grid-template-rows: 11em 3.5em;
|
||||||
|
height: 14.5em;
|
||||||
|
}
|
||||||
|
.modifier-card-size_3 .modifier-card-image-overlay {
|
||||||
|
font-size: 6em;
|
||||||
|
}
|
||||||
|
.modifier-card-size_2 {
|
||||||
|
width: 10em;
|
||||||
|
grid-template-rows: 10em 3.5em;
|
||||||
|
height: 13.5em;
|
||||||
|
}
|
||||||
|
.modifier-card-size_2 .modifier-card-image-overlay {
|
||||||
|
font-size: 6em;
|
||||||
|
}
|
||||||
|
.modifier-card-size_1 {
|
||||||
|
width: 9em;
|
||||||
|
grid-template-rows: 9em 3.5em;
|
||||||
|
height: 12.5em;
|
||||||
|
}
|
||||||
|
.modifier-card-size_1 .modifier-card-image-overlay {
|
||||||
|
font-size: 5em;
|
||||||
|
}
|
||||||
|
.modifier-card-size_-1 {
|
||||||
|
width: 7em;
|
||||||
|
grid-template-rows: 7em 3.5em;
|
||||||
|
height: 10.5em;
|
||||||
|
}
|
||||||
|
.modifier-card-size_-1 .modifier-card-image-overlay {
|
||||||
|
font-size: 4em;
|
||||||
|
}
|
||||||
|
.modifier-card-size_-2 {
|
||||||
|
width: 6em;
|
||||||
|
grid-template-rows: 6em 3.5em;
|
||||||
|
height: 9.5em;
|
||||||
|
}
|
||||||
|
.modifier-card-size_-2 .modifier-card-image-overlay {
|
||||||
|
font-size: 3em;
|
||||||
|
}
|
||||||
|
.modifier-card-size_-3 {
|
||||||
|
width: 5em;
|
||||||
|
grid-template-rows: 5em 3.5em;
|
||||||
|
height: 8.5em;
|
||||||
|
}
|
||||||
|
.modifier-card-size_-3 .modifier-card-image-overlay {
|
||||||
|
font-size: 3em;
|
||||||
|
}
|
||||||
|
.modifier-card-size_-3 p {
|
||||||
|
font-size: 0.8em;
|
||||||
|
}
|
||||||
|
.modifier-card-tiny {
|
||||||
|
width: 6em;
|
||||||
|
height: 9.5em;
|
||||||
|
grid-template-rows: 6em 3.5em;
|
||||||
|
}
|
||||||
|
.modifier-card-tiny p {
|
||||||
|
font-size: 0.7em;
|
||||||
|
}
|
||||||
|
.modifier-card:hover {
|
||||||
|
transform: scale(1.05);
|
||||||
|
box-shadow: 0 5px 16px 5px rgba(0, 0, 0, 0.25);
|
||||||
|
}
|
||||||
|
.modifier-card-image-container {
|
||||||
|
border-radius: 5px 5px 0 0;
|
||||||
|
width: inherit;
|
||||||
|
height: 100%;
|
||||||
|
background-color: rgba(0, 0, 0, .2);
|
||||||
|
grid-area: modifier-card-image-container;
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
color: rgb(255 255 255 / 8%);
|
||||||
|
}
|
||||||
|
.modifier-card-image-container img {
|
||||||
|
width: inherit;
|
||||||
|
height: 100%;
|
||||||
|
border-radius: 5px 5px 0 0;
|
||||||
|
}
|
||||||
|
.modifier-card-image-container * {
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
.modifier-card-container {
|
||||||
|
text-align: center;
|
||||||
|
background-color: rgba(0,0,0,0.5);
|
||||||
|
border-radius: 0 0 5px 5px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
grid-area: modifier-card-container;
|
||||||
|
font-weight: 100;
|
||||||
|
font-size: .9em;
|
||||||
|
width: inherit;
|
||||||
|
}
|
||||||
|
.modifier-card-label {
|
||||||
|
padding: 4px;
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
.modifier-card-image-overlay {
|
||||||
|
width: inherit;
|
||||||
|
height: inherit;
|
||||||
|
background-color: rgb(0 0 0 / 50%);
|
||||||
|
z-index: 2;
|
||||||
|
position: absolute;
|
||||||
|
border-radius: 5px 5px 0 0;
|
||||||
|
opacity: 0;
|
||||||
|
font-size: 5em;
|
||||||
|
font-weight: 900;
|
||||||
|
color: rgb(255 255 255 / 50%);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
.modifier-card-overlay {
|
||||||
|
width: inherit;
|
||||||
|
height: inherit;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 3;
|
||||||
|
}
|
||||||
|
.modifier-card:hover > .modifier-card-image-container .modifier-card-image-overlay {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
.modifier-card:hover > .modifier-card-image-container img {
|
||||||
|
filter: blur(.1em);
|
||||||
|
}
|
||||||
|
.modifier-card:active {
|
||||||
|
transform: scale(0.95);
|
||||||
|
box-shadow: 0 5px 16px 5px rgba(0, 0, 0, 0.5);
|
||||||
|
}
|
||||||
|
#preview-image {
|
||||||
|
margin-top: 0.5em;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
}
|
||||||
|
.modifier-card-active {
|
||||||
|
border: 2px solid rgb(179 82 255 / 94%);
|
||||||
|
box-shadow: 0 0px 10px 0 rgb(170 0 229 / 58%);
|
||||||
|
}
|
||||||
|
.tooltip {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
.tooltip .tooltip-text {
|
||||||
|
visibility: hidden;
|
||||||
|
width: 120px;
|
||||||
|
background: rgb(101,97,181);
|
||||||
|
background: linear-gradient(180deg, rgba(101,97,181,1) 0%, rgba(47,45,85,1) 100%);
|
||||||
|
color: #fff;
|
||||||
|
text-align: center;
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 5px;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1;
|
||||||
|
top: 105%;
|
||||||
|
left: 39%;
|
||||||
|
margin-left: -60px;
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.3s;
|
||||||
|
border: 2px solid rgb(90 100 177 / 94%);
|
||||||
|
box-shadow: 0px 10px 20px 5px rgb(11 0 58 / 55%);
|
||||||
|
width: 10em;
|
||||||
|
}
|
||||||
|
.tooltip .tooltip-text::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
top: -0.9em;
|
||||||
|
left: 50%;
|
||||||
|
margin-left: -5px;
|
||||||
|
border-width: 5px;
|
||||||
|
border-style: solid;
|
||||||
|
border-color: transparent transparent rgb(90 100 177 / 94%) transparent;
|
||||||
|
}
|
||||||
|
.tooltip:hover .tooltip-text {
|
||||||
|
visibility: visible;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
#modifier-card-size-slider {
|
||||||
|
width: 6em;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</html>
|
</html>
|
||||||
<body>
|
<body>
|
||||||
@ -300,8 +488,7 @@
|
|||||||
|
|
||||||
<div id="editor-inputs-tags-container" class="row">
|
<div id="editor-inputs-tags-container" class="row">
|
||||||
<label>Tags: <small>(click a tag to remove it)</small></label>
|
<label>Tags: <small>(click a tag to remove it)</small></label>
|
||||||
<div id="editor-inputs-tags-list">
|
<div id="editor-inputs-tags-list"></div>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button id="makeImage">Make Image</button>
|
<button id="makeImage">Make Image</button>
|
||||||
@ -389,6 +576,15 @@
|
|||||||
<div id="editor-modifiers" class="panel-box">
|
<div id="editor-modifiers" class="panel-box">
|
||||||
<h4 class="collapsible">Image Modifiers (art styles, tags etc)</h4>
|
<h4 class="collapsible">Image Modifiers (art styles, tags etc)</h4>
|
||||||
<div id="editor-modifiers-entries" class="collapsible-content">
|
<div id="editor-modifiers-entries" class="collapsible-content">
|
||||||
|
<label for="preview-image">Preview:</label>
|
||||||
|
<select id="preview-image" name="preview-image" value="portrait">
|
||||||
|
<option value="portrait" selected="">Portrait</option>
|
||||||
|
<option value="landscape">Landscape</option>
|
||||||
|
</select>
|
||||||
|
<div>
|
||||||
|
<label for="modifier-card-size-slider">Card Size:</label>
|
||||||
|
<input id="modifier-card-size-slider" name="modifier-card-size-slider" value="0" type="range" min="-3" max="5">
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -478,6 +674,12 @@ let editorModifierEntries = document.querySelector('#editor-modifiers-entries')
|
|||||||
let editorModifierTagsList = document.querySelector('#editor-inputs-tags-list')
|
let editorModifierTagsList = document.querySelector('#editor-inputs-tags-list')
|
||||||
let editorTagsContainer = document.querySelector('#editor-inputs-tags-container')
|
let editorTagsContainer = document.querySelector('#editor-inputs-tags-container')
|
||||||
|
|
||||||
|
let previewImageField = document.querySelector('#preview-image')
|
||||||
|
previewImageField.onchange = () => changePreviewImages(previewImageField.value);
|
||||||
|
|
||||||
|
let modifierCardSizeSlider = document.querySelector('#modifier-card-size-slider')
|
||||||
|
modifierCardSizeSlider.onchange = () => resizeModifierCards(modifierCardSizeSlider.value);
|
||||||
|
|
||||||
let previewPrompt = document.querySelector('#preview-prompt')
|
let previewPrompt = document.querySelector('#preview-prompt')
|
||||||
|
|
||||||
let showConfigToggle = document.querySelector('#configToggleBtn')
|
let showConfigToggle = document.querySelector('#configToggleBtn')
|
||||||
@ -494,9 +696,13 @@ let modifiersPanelHandle = document.querySelector("#editor-modifiers .collapsibl
|
|||||||
|
|
||||||
let serverStatus = 'offline'
|
let serverStatus = 'offline'
|
||||||
let activeTags = []
|
let activeTags = []
|
||||||
|
let modifiers = []
|
||||||
let lastPromptUsed = ''
|
let lastPromptUsed = ''
|
||||||
let taskStopped = true
|
let taskStopped = true
|
||||||
|
|
||||||
|
const modifierThumbnailPath = 'static/modifier-thumbnails';
|
||||||
|
const activeCardClass = 'modifier-card-active';
|
||||||
|
|
||||||
function getLocalStorageItem(key, fallback) {
|
function getLocalStorageItem(key, fallback) {
|
||||||
let item = localStorage.getItem(key)
|
let item = localStorage.getItem(key)
|
||||||
if (item === null) {
|
if (item === null) {
|
||||||
@ -580,12 +786,12 @@ function setStatus(statusType, msg, msgType) {
|
|||||||
// msg = '<span style="color: red">' + msg + '<span>'
|
// msg = '<span style="color: red">' + msg + '<span>'
|
||||||
serverStatusColor.style.backgroundColor = 'red'
|
serverStatusColor.style.backgroundColor = 'red'
|
||||||
serverStatusMsg.style.color = 'red'
|
serverStatusMsg.style.color = 'red'
|
||||||
serverStatusMsg.innerHTML = 'Stable Diffusion has stopped'
|
serverStatusMsg.innerText = 'Stable Diffusion has stopped'
|
||||||
} else if (msgType == 'success') {
|
} else if (msgType == 'success') {
|
||||||
// msg = '<span style="color: green">' + msg + '<span>'
|
// msg = '<span style="color: green">' + msg + '<span>'
|
||||||
serverStatusColor.style.backgroundColor = 'green'
|
serverStatusColor.style.backgroundColor = 'green'
|
||||||
serverStatusMsg.style.color = 'green'
|
serverStatusMsg.style.color = 'green'
|
||||||
serverStatusMsg.innerHTML = 'Stable Diffusion is ready'
|
serverStatusMsg.innerText = 'Stable Diffusion is ready'
|
||||||
serverStatus = 'online'
|
serverStatus = 'online'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -596,7 +802,7 @@ function logMsg(msg, level) {
|
|||||||
} else if (level === 'warn') {
|
} else if (level === 'warn') {
|
||||||
outputMsg.innerHTML = '<span style="color: orange">Warning: ' + msg + '</span>'
|
outputMsg.innerHTML = '<span style="color: orange">Warning: ' + msg + '</span>'
|
||||||
} else {
|
} else {
|
||||||
outputMsg.innerHTML = msg
|
outputMsg.innerText = msg
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(level, msg)
|
console.log(level, msg)
|
||||||
@ -716,15 +922,15 @@ async function doMakeImage(reqBody) {
|
|||||||
|
|
||||||
let imgSeedLabel = document.createElement('span')
|
let imgSeedLabel = document.createElement('span')
|
||||||
imgSeedLabel.className = 'imgSeedLabel'
|
imgSeedLabel.className = 'imgSeedLabel'
|
||||||
imgSeedLabel.innerHTML = 'Seed: ' + seed
|
imgSeedLabel.innerText = 'Seed: ' + seed
|
||||||
|
|
||||||
let imgUseBtn = document.createElement('button')
|
let imgUseBtn = document.createElement('button')
|
||||||
imgUseBtn.className = 'imgUseBtn'
|
imgUseBtn.className = 'imgUseBtn'
|
||||||
imgUseBtn.innerHTML = 'Use as Input'
|
imgUseBtn.innerText = 'Use as Input'
|
||||||
|
|
||||||
let imgSaveBtn = document.createElement('button')
|
let imgSaveBtn = document.createElement('button')
|
||||||
imgSaveBtn.className = 'imgSaveBtn'
|
imgSaveBtn.className = 'imgSaveBtn'
|
||||||
imgSaveBtn.innerHTML = 'Download'
|
imgSaveBtn.innerText = 'Download'
|
||||||
|
|
||||||
imgItem.appendChild(img)
|
imgItem.appendChild(img)
|
||||||
imgItem.appendChild(imgItemInfo)
|
imgItem.appendChild(imgItemInfo)
|
||||||
@ -815,11 +1021,11 @@ async function makeImage() {
|
|||||||
|
|
||||||
let prompt = promptField.value
|
let prompt = promptField.value
|
||||||
if (activeTags.length > 0) {
|
if (activeTags.length > 0) {
|
||||||
let promptTags = activeTags.join(", ")
|
let promptTags = activeTags.map(x => x.name).join(", ");
|
||||||
prompt += ", " + promptTags
|
prompt += ", " + promptTags;
|
||||||
}
|
}
|
||||||
|
|
||||||
previewPrompt.innerHTML = prompt
|
previewPrompt.innerText = prompt
|
||||||
|
|
||||||
let reqBody = {
|
let reqBody = {
|
||||||
prompt: prompt,
|
prompt: prompt,
|
||||||
@ -870,12 +1076,12 @@ async function makeImage() {
|
|||||||
let success = await doMakeImage(reqBody)
|
let success = await doMakeImage(reqBody)
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
outputMsg.innerHTML = 'Processed batch ' + (i+1) + '/' + batchCount
|
outputMsg.innerText = 'Processed batch ' + (i+1) + '/' + batchCount
|
||||||
successCount++
|
successCount++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
makeImageBtn.innerHTML = 'Make Image'
|
makeImageBtn.innerText = 'Make Image'
|
||||||
makeImageBtn.disabled = false
|
makeImageBtn.disabled = false
|
||||||
makeImageBtn.style.display = 'block'
|
makeImageBtn.style.display = 'block'
|
||||||
stopImageBtn.style.display = 'none'
|
stopImageBtn.style.display = 'none'
|
||||||
@ -888,7 +1094,7 @@ async function makeImage() {
|
|||||||
time /= 1000
|
time /= 1000
|
||||||
|
|
||||||
if (successCount === batchCount) {
|
if (successCount === batchCount) {
|
||||||
outputMsg.innerHTML = 'Processed ' + numOutputsTotal + ' images in ' + time + ' seconds'
|
outputMsg.innerText = 'Processed ' + numOutputsTotal + ' images in ' + time + ' seconds'
|
||||||
|
|
||||||
setStatus('request', 'done', 'success')
|
setStatus('request', 'done', 'success')
|
||||||
}
|
}
|
||||||
@ -1071,7 +1277,7 @@ async function getAppConfig() {
|
|||||||
|
|
||||||
if (config.update_branch === 'beta') {
|
if (config.update_branch === 'beta') {
|
||||||
useBetaChannelField.checked = true
|
useBetaChannelField.checked = true
|
||||||
updateBranchLabel.innerHTML = "(beta)"
|
updateBranchLabel.innerText = "(beta)"
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('get config status response', config)
|
console.log('get config status response', config)
|
||||||
@ -1202,30 +1408,33 @@ function createCollapsibles(node) {
|
|||||||
createCollapsibles()
|
createCollapsibles()
|
||||||
|
|
||||||
function refreshTagsList() {
|
function refreshTagsList() {
|
||||||
editorModifierTagsList.innerHTML = ''
|
editorModifierTagsList.innerHTML = '';
|
||||||
|
|
||||||
if (activeTags.length == 0) {
|
if (activeTags.length == 0) {
|
||||||
editorTagsContainer.style.display = 'none'
|
editorTagsContainer.style.display = 'none';
|
||||||
return
|
return;
|
||||||
} else {
|
} else {
|
||||||
editorTagsContainer.style.display = 'block'
|
editorTagsContainer.style.display = 'block';
|
||||||
}
|
}
|
||||||
|
|
||||||
activeTags.forEach(function(tag) {
|
activeTags.forEach((tag, index) => {
|
||||||
let el = document.createElement('div')
|
tag.element.querySelector('.modifier-card-image-overlay').innerText = '-';
|
||||||
el.className = 'prompt-modifier-tag'
|
tag.element.classList.add('modifier-card-tiny');
|
||||||
el.innerHTML = tag
|
|
||||||
|
|
||||||
editorModifierTagsList.appendChild(el)
|
editorModifierTagsList.appendChild(tag.element);
|
||||||
|
|
||||||
|
tag.element.addEventListener('click', () => {
|
||||||
|
let idx = activeTags.indexOf(tag);
|
||||||
|
|
||||||
el.addEventListener('click', function() {
|
|
||||||
let idx = activeTags.indexOf(tag)
|
|
||||||
if (idx !== -1) {
|
if (idx !== -1) {
|
||||||
activeTags.splice(idx, 1)
|
activeTags[idx].originElement.classList.remove(activeCardClass);
|
||||||
refreshTagsList()
|
activeTags[idx].originElement.querySelector('.modifier-card-image-overlay').innerText = '+';
|
||||||
|
|
||||||
|
activeTags.splice(idx, 1);
|
||||||
|
refreshTagsList();
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
|
|
||||||
let brk = document.createElement('br')
|
let brk = document.createElement('br')
|
||||||
brk.style.clear = 'both'
|
brk.style.clear = 'both'
|
||||||
@ -1253,39 +1462,164 @@ async function getDiskPath() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createModifierCard(name, previews) {
|
||||||
|
const modifierCard = document.createElement('div');
|
||||||
|
modifierCard.className = 'modifier-card';
|
||||||
|
modifierCard.innerHTML = `
|
||||||
|
<div class="modifier-card-overlay"></div>
|
||||||
|
<div class="modifier-card-image-container">
|
||||||
|
<div class="modifier-card-image-overlay">+</div>
|
||||||
|
<p class="modifier-card-error-label"></p>
|
||||||
|
<img onerror="this.remove()" alt="Modifier Image" class="modifier-card-image">
|
||||||
|
</div>
|
||||||
|
<div class="modifier-card-container">
|
||||||
|
<div class="modifier-card-label"><p></p></div>
|
||||||
|
</div>`;
|
||||||
|
|
||||||
|
const image = modifierCard.querySelector('.modifier-card-image');
|
||||||
|
const errorText = modifierCard.querySelector('.modifier-card-error-label');
|
||||||
|
const label = modifierCard.querySelector('.modifier-card-label');
|
||||||
|
|
||||||
|
errorText.innerText = 'No Image';
|
||||||
|
|
||||||
|
if (typeof previews == 'object') {
|
||||||
|
image.src = previews[0]; // portrait
|
||||||
|
image.setAttribute('preview-type', 'portrait');
|
||||||
|
} else {
|
||||||
|
image.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
const maxLabelLength = 30;
|
||||||
|
const nameWithoutBy = name.replace('by ', '');
|
||||||
|
|
||||||
|
if(nameWithoutBy.length <= maxLabelLength) {
|
||||||
|
label.querySelector('p').innerText = nameWithoutBy;
|
||||||
|
} else {
|
||||||
|
const tooltipText = document.createElement('span');
|
||||||
|
tooltipText.className = 'tooltip-text';
|
||||||
|
tooltipText.innerText = name;
|
||||||
|
|
||||||
|
label.classList.add('tooltip');
|
||||||
|
label.appendChild(tooltipText);
|
||||||
|
|
||||||
|
label.querySelector('p').innerText = nameWithoutBy.substring(0, maxLabelLength) + '...';
|
||||||
|
}
|
||||||
|
|
||||||
|
return modifierCard;
|
||||||
|
}
|
||||||
|
|
||||||
|
function changePreviewImages(val) {
|
||||||
|
const previewImages = document.querySelectorAll('.modifier-card-image-container img');
|
||||||
|
|
||||||
|
let previewArr = [];
|
||||||
|
|
||||||
|
modifiers.map(x => x.modifiers).forEach(x => previewArr.push(...x.map(m => m.previews)));
|
||||||
|
|
||||||
|
previewArr = previewArr.map(x => {
|
||||||
|
let obj = {};
|
||||||
|
|
||||||
|
x.forEach(preview => {
|
||||||
|
obj[preview.name] = preview.path;
|
||||||
|
});
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
});
|
||||||
|
|
||||||
|
previewImages.forEach(previewImage => {
|
||||||
|
const currentPreviewType = previewImage.getAttribute('preview-type');
|
||||||
|
const relativePreviewPath = previewImage.src.split(modifierThumbnailPath + '/').pop();
|
||||||
|
|
||||||
|
const previews = previewArr.find(preview => relativePreviewPath == preview[currentPreviewType]);
|
||||||
|
|
||||||
|
if(typeof previews == 'object') {
|
||||||
|
let preview = null;
|
||||||
|
|
||||||
|
if (val == 'portrait') {
|
||||||
|
preview = previews.portrait;
|
||||||
|
}
|
||||||
|
else if (val == 'landscape') {
|
||||||
|
preview = previews.landscape;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(preview != null) {
|
||||||
|
previewImage.src = `${modifierThumbnailPath}/${preview}`;
|
||||||
|
previewImage.setAttribute('preview-type', val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function resizeModifierCards(val) {
|
||||||
|
const cardSizePrefix = 'modifier-card-size_';
|
||||||
|
const modifierCardClass = 'modifier-card';
|
||||||
|
|
||||||
|
const modifierCards = document.querySelectorAll(`.${modifierCardClass}`);
|
||||||
|
const cardSize = n => `${cardSizePrefix}${n}`;
|
||||||
|
|
||||||
|
modifierCards.forEach(card => {
|
||||||
|
// remove existing size classes
|
||||||
|
const classes = card.className.split(' ').filter(c => !c.startsWith(cardSizePrefix));
|
||||||
|
card.className = classes.join(' ').trim();
|
||||||
|
|
||||||
|
if(val != 0)
|
||||||
|
card.classList.add(cardSize(val));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
async function loadModifiers() {
|
async function loadModifiers() {
|
||||||
try {
|
try {
|
||||||
let res = await fetch('/modifiers.json')
|
let res = await fetch('/modifiers.json')
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
res = await res.json()
|
res = await res.json()
|
||||||
|
|
||||||
res.forEach(function(m) {
|
modifiers = res; // update global variable
|
||||||
let title = m[0]
|
|
||||||
let modifiers = m[1]
|
|
||||||
|
|
||||||
let titleEl = document.createElement('h5')
|
res.forEach(modifierGroup => {
|
||||||
titleEl.className = 'collapsible'
|
const title = modifierGroup.category;
|
||||||
titleEl.innerHTML = title
|
const modifiers = modifierGroup.modifiers;
|
||||||
|
|
||||||
let modifiersEl = document.createElement('div')
|
const titleEl = document.createElement('h5');
|
||||||
modifiersEl.classList.add('collapsible-content', 'editor-modifiers-leaf')
|
titleEl.className = 'collapsible';
|
||||||
|
titleEl.innerText = title;
|
||||||
|
|
||||||
modifiers.forEach(function(modifier) {
|
const modifiersEl = document.createElement('div');
|
||||||
let tagEl = document.createElement('div')
|
modifiersEl.classList.add('collapsible-content', 'editor-modifiers-leaf');
|
||||||
tagEl.className = 'prompt-modifier-tag'
|
|
||||||
tagEl.innerHTML = modifier
|
|
||||||
|
|
||||||
modifiersEl.appendChild(tagEl)
|
modifiers.forEach(modObj => {
|
||||||
|
const modifierName = modObj.modifier;
|
||||||
|
const modifierPreviews = modObj?.previews?.map(preview => `${modifierThumbnailPath}/${preview.path}`);
|
||||||
|
|
||||||
tagEl.addEventListener('click', function() {
|
const modifierCard = createModifierCard(modifierName, modifierPreviews);
|
||||||
if (activeTags.includes(modifier)) {
|
|
||||||
return
|
if(typeof modifierCard == 'object') {
|
||||||
|
modifiersEl.appendChild(modifierCard);
|
||||||
|
|
||||||
|
modifierCard.addEventListener('click', () => {
|
||||||
|
if (activeTags.map(x => x.name).includes(modifierName)) {
|
||||||
|
// remove modifier from active array
|
||||||
|
activeTags = activeTags.filter(x => x.name != modifierName);
|
||||||
|
modifierCard.classList.remove(activeCardClass);
|
||||||
|
|
||||||
|
modifierCard.querySelector('.modifier-card-image-overlay').innerText = '+';
|
||||||
|
} else {
|
||||||
|
// add modifier to active array
|
||||||
|
activeTags.push({
|
||||||
|
'name': modifierName,
|
||||||
|
'element': modifierCard.cloneNode(true),
|
||||||
|
'originElement': modifierCard,
|
||||||
|
'previews': modifierPreviews
|
||||||
|
});
|
||||||
|
|
||||||
|
modifierCard.classList.add(activeCardClass);
|
||||||
|
|
||||||
|
modifierCard.querySelector('.modifier-card-image-overlay').innerText = '-';
|
||||||
}
|
}
|
||||||
|
|
||||||
activeTags.push(modifier)
|
refreshTagsList();
|
||||||
refreshTagsList()
|
});
|
||||||
})
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
let brk = document.createElement('br')
|
let brk = document.createElement('br')
|
||||||
brk.style.clear = 'both'
|
brk.style.clear = 'both'
|
||||||
modifiersEl.appendChild(brk)
|
modifiersEl.appendChild(brk)
|
||||||
|
2949
ui/modifiers.json
@ -10,11 +10,14 @@ print('started in ', SCRIPT_DIR)
|
|||||||
SD_UI_DIR = os.getenv('SD_UI_PATH', None)
|
SD_UI_DIR = os.getenv('SD_UI_PATH', None)
|
||||||
sys.path.append(os.path.dirname(SD_UI_DIR))
|
sys.path.append(os.path.dirname(SD_UI_DIR))
|
||||||
|
|
||||||
|
STATIC_DIR = os.path.join(SD_UI_DIR, "static")
|
||||||
|
|
||||||
CONFIG_DIR = os.path.join(SD_UI_DIR, '..', 'scripts')
|
CONFIG_DIR = os.path.join(SD_UI_DIR, '..', 'scripts')
|
||||||
|
|
||||||
OUTPUT_DIRNAME = "Stable Diffusion UI" # in the user's home folder
|
OUTPUT_DIRNAME = "Stable Diffusion UI" # in the user's home folder
|
||||||
|
|
||||||
from fastapi import FastAPI, HTTPException
|
from fastapi import FastAPI, HTTPException
|
||||||
|
from fastapi.staticfiles import StaticFiles
|
||||||
from starlette.responses import FileResponse
|
from starlette.responses import FileResponse
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
import logging
|
import logging
|
||||||
@ -196,5 +199,7 @@ class HealthCheckLogFilter(logging.Filter):
|
|||||||
|
|
||||||
logging.getLogger('uvicorn.access').addFilter(HealthCheckLogFilter())
|
logging.getLogger('uvicorn.access').addFilter(HealthCheckLogFilter())
|
||||||
|
|
||||||
|
app.mount("/static", StaticFiles(directory=STATIC_DIR), name="static")
|
||||||
|
|
||||||
# start the browser ui
|
# start the browser ui
|
||||||
import webbrowser; webbrowser.open('http://localhost:9000')
|
import webbrowser; webbrowser.open('http://localhost:9000')
|
BIN
ui/static/modifier-thumbnails/artist/artstation/landscape-0.jpg
Normal file
After Width: | Height: | Size: 38 KiB |
BIN
ui/static/modifier-thumbnails/artist/artstation/portrait-0.jpg
Normal file
After Width: | Height: | Size: 27 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 27 KiB |
After Width: | Height: | Size: 36 KiB |
After Width: | Height: | Size: 33 KiB |
After Width: | Height: | Size: 90 KiB |
BIN
ui/static/modifier-thumbnails/artist/by_alex_grey/portrait-0.jpg
Normal file
After Width: | Height: | Size: 59 KiB |
After Width: | Height: | Size: 66 KiB |
After Width: | Height: | Size: 66 KiB |
After Width: | Height: | Size: 75 KiB |
After Width: | Height: | Size: 45 KiB |
After Width: | Height: | Size: 76 KiB |
After Width: | Height: | Size: 41 KiB |
BIN
ui/static/modifier-thumbnails/artist/by_artgerm/landscape-0.jpg
Normal file
After Width: | Height: | Size: 51 KiB |
BIN
ui/static/modifier-thumbnails/artist/by_artgerm/portrait-0.jpg
Normal file
After Width: | Height: | Size: 34 KiB |
After Width: | Height: | Size: 94 KiB |
After Width: | Height: | Size: 56 KiB |
After Width: | Height: | Size: 77 KiB |
After Width: | Height: | Size: 44 KiB |
BIN
ui/static/modifier-thumbnails/artist/by_banksy/landscape-0.jpg
Normal file
After Width: | Height: | Size: 48 KiB |
BIN
ui/static/modifier-thumbnails/artist/by_banksy/portrait-0.jpg
Normal file
After Width: | Height: | Size: 54 KiB |
BIN
ui/static/modifier-thumbnails/artist/by_beeple/landscape-0.jpg
Normal file
After Width: | Height: | Size: 46 KiB |
BIN
ui/static/modifier-thumbnails/artist/by_beeple/portrait-0.jpg
Normal file
After Width: | Height: | Size: 31 KiB |
After Width: | Height: | Size: 30 KiB |
After Width: | Height: | Size: 32 KiB |
After Width: | Height: | Size: 56 KiB |
After Width: | Height: | Size: 52 KiB |
After Width: | Height: | Size: 54 KiB |
After Width: | Height: | Size: 42 KiB |
After Width: | Height: | Size: 42 KiB |
After Width: | Height: | Size: 33 KiB |
After Width: | Height: | Size: 47 KiB |
After Width: | Height: | Size: 56 KiB |
After Width: | Height: | Size: 52 KiB |
After Width: | Height: | Size: 62 KiB |
After Width: | Height: | Size: 110 KiB |
After Width: | Height: | Size: 84 KiB |
After Width: | Height: | Size: 38 KiB |
After Width: | Height: | Size: 38 KiB |
After Width: | Height: | Size: 47 KiB |
After Width: | Height: | Size: 40 KiB |
After Width: | Height: | Size: 41 KiB |
After Width: | Height: | Size: 27 KiB |
After Width: | Height: | Size: 52 KiB |
After Width: | Height: | Size: 44 KiB |
After Width: | Height: | Size: 48 KiB |
After Width: | Height: | Size: 42 KiB |
After Width: | Height: | Size: 62 KiB |
After Width: | Height: | Size: 50 KiB |
After Width: | Height: | Size: 41 KiB |
After Width: | Height: | Size: 354 KiB |
After Width: | Height: | Size: 34 KiB |
After Width: | Height: | Size: 35 KiB |
After Width: | Height: | Size: 43 KiB |
After Width: | Height: | Size: 34 KiB |
After Width: | Height: | Size: 57 KiB |
After Width: | Height: | Size: 87 KiB |
After Width: | Height: | Size: 55 KiB |
After Width: | Height: | Size: 57 KiB |
After Width: | Height: | Size: 80 KiB |
BIN
ui/static/modifier-thumbnails/artist/by_h_r_giger/portrait-0.jpg
Normal file
After Width: | Height: | Size: 60 KiB |
After Width: | Height: | Size: 58 KiB |
After Width: | Height: | Size: 38 KiB |
After Width: | Height: | Size: 56 KiB |
After Width: | Height: | Size: 43 KiB |
After Width: | Height: | Size: 45 KiB |
After Width: | Height: | Size: 56 KiB |
After Width: | Height: | Size: 72 KiB |
After Width: | Height: | Size: 46 KiB |
After Width: | Height: | Size: 61 KiB |
After Width: | Height: | Size: 50 KiB |
After Width: | Height: | Size: 88 KiB |
After Width: | Height: | Size: 67 KiB |
After Width: | Height: | Size: 84 KiB |
After Width: | Height: | Size: 60 KiB |
After Width: | Height: | Size: 53 KiB |
BIN
ui/static/modifier-thumbnails/artist/by_jim_burns/portrait-0.jpg
Normal file
After Width: | Height: | Size: 33 KiB |
After Width: | Height: | Size: 38 KiB |
After Width: | Height: | Size: 420 KiB |
After Width: | Height: | Size: 58 KiB |
After Width: | Height: | Size: 47 KiB |
After Width: | Height: | Size: 60 KiB |
After Width: | Height: | Size: 51 KiB |
After Width: | Height: | Size: 29 KiB |
After Width: | Height: | Size: 29 KiB |
After Width: | Height: | Size: 31 KiB |
After Width: | Height: | Size: 31 KiB |
After Width: | Height: | Size: 65 KiB |
After Width: | Height: | Size: 53 KiB |
After Width: | Height: | Size: 90 KiB |
After Width: | Height: | Size: 72 KiB |
After Width: | Height: | Size: 75 KiB |
After Width: | Height: | Size: 54 KiB |
After Width: | Height: | Size: 29 KiB |
After Width: | Height: | Size: 41 KiB |
After Width: | Height: | Size: 43 KiB |