forked from extern/easydiffusion
Merge branch 'beta' of https://github.com/cmdr2/stable-diffusion-ui.git into multi-gpu
This commit is contained in:
commit
cfd6751777
@ -10,6 +10,10 @@ if exist "Open Developer Console.cmd" del "Open Developer Console.cmd"
|
||||
|
||||
@call python -c "import os; import shutil; frm = 'sd-ui-files\\ui\\hotfix\\9c24e6cd9f499d02c4f21a033736dabd365962dc80fe3aeb57a8f85ea45a20a3.26fead7ea4f0f843f6eb4055dfd25693f1a71f3c6871b184042d4b126244e142'; dst = os.path.join(os.path.expanduser('~'), '.cache', 'huggingface', 'transformers', '9c24e6cd9f499d02c4f21a033736dabd365962dc80fe3aeb57a8f85ea45a20a3.26fead7ea4f0f843f6eb4055dfd25693f1a71f3c6871b184042d4b126244e142'); shutil.copyfile(frm, dst) if os.path.exists(dst) else print(''); print('Hotfixed broken JSON file from OpenAI');"
|
||||
|
||||
if exist "%cd%\profile" (
|
||||
set USERPROFILE=%cd%\profile
|
||||
)
|
||||
|
||||
@>nul grep -c "sd_git_cloned" scripts\install_status.txt
|
||||
@if "%ERRORLEVEL%" EQU "0" (
|
||||
@echo "Stable Diffusion's git repository was already installed. Updating.."
|
||||
@ -59,6 +63,7 @@ if exist "Open Developer Console.cmd" del "Open Developer Console.cmd"
|
||||
@REM prevent conda from using packages from the user's home directory, to avoid conflicts
|
||||
@set PYTHONNOUSERSITE=1
|
||||
|
||||
set USERPROFILE=%cd%\profile
|
||||
set TMP=%cd%\tmp
|
||||
set TEMP=%cd%\tmp
|
||||
|
||||
@ -95,6 +100,7 @@ set PATH=C:\Windows\System32;%PATH%
|
||||
|
||||
@set PYTHONNOUSERSITE=1
|
||||
|
||||
set USERPROFILE=%cd%\profile
|
||||
set TMP=%cd%\tmp
|
||||
set TEMP=%cd%\tmp
|
||||
|
||||
@ -127,6 +133,7 @@ set PATH=C:\Windows\System32;%PATH%
|
||||
|
||||
@set PYTHONNOUSERSITE=1
|
||||
|
||||
set USERPROFILE=%cd%\profile
|
||||
set TMP=%cd%\tmp
|
||||
set TEMP=%cd%\tmp
|
||||
|
||||
@ -153,6 +160,7 @@ set PATH=C:\Windows\System32;%PATH%
|
||||
|
||||
@set PYTHONNOUSERSITE=1
|
||||
|
||||
set USERPROFILE=%cd%\profile
|
||||
set TMP=%cd%\tmp
|
||||
set TEMP=%cd%\tmp
|
||||
|
||||
|
@ -2,21 +2,22 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="icon" type="image/png" href="/media/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="icon" type="image/png" href="/media/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="stylesheet" href="/media/main.css?v=25">
|
||||
<link rel="stylesheet" href="/media/modifier-thumbnails.css?v=1">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.0/css/all.min.css">
|
||||
<link rel="stylesheet" href="/media/drawingboard.min.css">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Work+Sans:wght@400;600;700;800&display=swap" rel="stylesheet">
|
||||
<script src="/media/jquery-3.6.1.min.js"></script>
|
||||
<script src="/media/drawingboard.min.js"></script>
|
||||
<link rel="icon" type="image/png" href="/media/images/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="icon" type="image/png" href="/media/images/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="stylesheet" href="/media/css/fonts.css?v=1">
|
||||
<link rel="stylesheet" href="/media/css/themes.css?v=1">
|
||||
<link rel="stylesheet" href="/media/css/main.css?v=1">
|
||||
<link rel="stylesheet" href="/media/css/modifier-thumbnails.css?v=1">
|
||||
<link rel="stylesheet" href="/media/css/fontawesome-all.min.css?v=1">
|
||||
<link rel="stylesheet" href="/media/css/drawingboard.min.css">
|
||||
<script src="/media/js/jquery-3.6.1.min.js"></script>
|
||||
<script src="/media/js/drawingboard.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="container">
|
||||
<div id="top-nav">
|
||||
<div id="logo">
|
||||
<h1>Stable Diffusion UI <small>v2.27 <span id="updateBranchLabel"></span></small></h1>
|
||||
<h1>Stable Diffusion UI <small>v2.29 <span id="updateBranchLabel"></span></small></h1>
|
||||
</div>
|
||||
<ul id="top-nav-items">
|
||||
<li class="dropdown">
|
||||
@ -239,7 +240,7 @@
|
||||
<div class="line-separator"> </div>
|
||||
|
||||
<div id="footer" class="panel-box">
|
||||
<p>If you found this project useful and want to help keep it alive, please <a href="https://ko-fi.com/cmdr2_stablediffusion_ui" target="_blank"><img src="media/kofi.png" id="coffeeButton"></a> to help cover the cost of development and maintenance! Thank you for your support!</p>
|
||||
<p>If you found this project useful and want to help keep it alive, please <a href="https://ko-fi.com/cmdr2_stablediffusion_ui" target="_blank"><img src="/media/images/kofi.png" id="coffeeButton"></a> to help cover the cost of development and maintenance! Thank you for your support!</p>
|
||||
<p>Please feel free to join the <a href="https://discord.com/invite/u9yhsFmEkB" target="_blank">discord community</a> or <a href="https://github.com/cmdr2/stable-diffusion-ui/issues" target="_blank">file an issue</a> if you have any problems or suggestions in using this interface.</p>
|
||||
<div id="footer-legal">
|
||||
<p><b>Disclaimer:</b> The authors of this project are not responsible for any content generated using this interface.</p>
|
||||
@ -250,8 +251,12 @@
|
||||
</div>
|
||||
</body>
|
||||
|
||||
<script src="media/auto-save.js?v=2"></script>
|
||||
<script src="media/main.js?v=37"></script>
|
||||
<script src="media/js/utils.js?v=1"></script>
|
||||
<script src="media/js/inpainting-editor.js?v=1"></script>
|
||||
<script src="media/js/image-modifiers.js"></script>
|
||||
<script src="media/js/auto-save.js?v=1"></script>
|
||||
<script src="media/js/main.js?v=1"></script>
|
||||
<script src="media/js/themes.js?v=1"></script>
|
||||
<script>
|
||||
async function init() {
|
||||
await loadModifiers()
|
||||
|
49
ui/media/css/auto-save.css
Normal file
49
ui/media/css/auto-save.css
Normal file
@ -0,0 +1,49 @@
|
||||
/* Auto-Settings Styling */
|
||||
#auto_save_settings:not(:checked) ~ button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#save-settings-config {
|
||||
position: fixed;
|
||||
background: rgba(32, 33, 36, 50%);
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
#save-settings-config > div {
|
||||
background: var(--background-color2);
|
||||
max-width: 600px;
|
||||
margin: auto;
|
||||
margin-top: 100px;
|
||||
border-radius: 6px;
|
||||
padding: 30px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#save-settings-config-table {
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
#save-settings-config-table td:first-child,
|
||||
#save-settings-config-table th:first-child {
|
||||
float: right;
|
||||
}
|
||||
|
||||
#save-settings-config-table td:last-child,
|
||||
#save-settings-config-table th:last-child {
|
||||
float: left;
|
||||
}
|
||||
|
||||
#save-settings-config-table td small {
|
||||
color: rgb(153, 153, 153);
|
||||
}
|
||||
|
||||
#save-settings-config-close-btn {
|
||||
float: right;
|
||||
cursor: pointer;
|
||||
padding: 10px;
|
||||
transform: translate(50%, -50%) scaleX(130%);
|
||||
}
|
6
ui/media/css/fontawesome-all.min.css
vendored
Normal file
6
ui/media/css/fontawesome-all.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
40
ui/media/css/fonts.css
Normal file
40
ui/media/css/fonts.css
Normal file
@ -0,0 +1,40 @@
|
||||
/* work-sans-regular - latin */
|
||||
@font-face {
|
||||
font-family: 'Work Sans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local(''),
|
||||
url('/media/fonts/work-sans-v18-latin-regular.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
|
||||
url('/media/fonts/work-sans-v18-latin-regular.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
|
||||
}
|
||||
|
||||
/* work-sans-600 - latin */
|
||||
@font-face {
|
||||
font-family: 'Work Sans';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
src: local(''),
|
||||
url('/media/fonts/work-sans-v18-latin-600.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
|
||||
url('/media/fonts/work-sans-v18-latin-600.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
|
||||
}
|
||||
|
||||
/* work-sans-700 - latin */
|
||||
@font-face {
|
||||
font-family: 'Work Sans';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: local(''),
|
||||
url('/media/fonts/work-sans-v18-latin-700.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
|
||||
url('/media/fonts/work-sans-v18-latin-700.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
|
||||
}
|
||||
|
||||
/* work-sans-800 - latin */
|
||||
@font-face {
|
||||
font-family: 'Work Sans';
|
||||
font-style: normal;
|
||||
font-weight: 800;
|
||||
src: local(''),
|
||||
url('/media/fonts/work-sans-v18-latin-800.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
|
||||
url('/media/fonts/work-sans-v18-latin-800.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
|
||||
}
|
||||
|
@ -1,151 +1,3 @@
|
||||
:root {
|
||||
--background-color1: rgb(32, 33, 36); /* main parts of the page */
|
||||
--background-color2: rgb(44, 45, 48); /* main panels */
|
||||
--background-color3: rgb(47, 49, 53);
|
||||
--background-color4: rgb(18, 18, 19); /* settings dropdowns */
|
||||
|
||||
--accent-hue: 266;
|
||||
--accent-lightness: 36%;
|
||||
--accent-lightness-hover: 40%;
|
||||
|
||||
--text-color: #eee;
|
||||
|
||||
--input-text-color: black;
|
||||
--input-background-color: #e9e9ed;
|
||||
--input-border-color: #8f8f9d;
|
||||
|
||||
--button-text-color: var(--input-text-color);
|
||||
--button-color: #e9e9ed;
|
||||
--button-border: 1px solid #8f8f9d;
|
||||
|
||||
/* other */
|
||||
--input-border-radius: 4px;
|
||||
--input-border-size: 1px;
|
||||
--accent-color: hsl(var(--accent-hue), 100%, var(--accent-lightness));
|
||||
--accent-color-hover: hsl(var(--accent-hue), 100%, var(--accent-lightness-hover));
|
||||
--make-image-border: 2px solid hsl(var(--accent-hue), 100%, calc(var(--accent-lightness) - 21%));
|
||||
}
|
||||
|
||||
.theme-light {
|
||||
--background-color1: white;
|
||||
--background-color2: #dddddd;
|
||||
--background-color3: #e7e9eb;
|
||||
--background-color4: #cccccc;
|
||||
|
||||
--text-color: black;
|
||||
|
||||
--input-text-color: black;
|
||||
--input-background-color: #f8f9fa;
|
||||
--input-border-color: grey;
|
||||
}
|
||||
|
||||
.theme-discord {
|
||||
--background-color1: #36393f;
|
||||
--background-color2: #2f3136;
|
||||
--background-color3: #292b2f;
|
||||
--background-color4: #202225;
|
||||
|
||||
--accent-hue: 235;
|
||||
--accent-lightness: 65%;
|
||||
--make-image-border: none;
|
||||
|
||||
--button-color: var(--accent-color);
|
||||
--button-border: none;
|
||||
|
||||
--input-text-color: #ccc;
|
||||
--input-border-size: 2px;
|
||||
--input-background-color: #202225;
|
||||
--input-border-color: var(--input-background-color);
|
||||
}
|
||||
|
||||
.theme-cool-blue {
|
||||
--main-hue: 222;
|
||||
--main-saturation: 18%;
|
||||
--value-base: 19%;
|
||||
--value-step: 3%;
|
||||
--background-color1: hsl(var(--main-hue), var(--main-saturation), var(--value-base));
|
||||
--background-color2: hsl(var(--main-hue), var(--main-saturation), calc(var(--value-base) - (1 * var(--value-step))));
|
||||
--background-color3: hsl(var(--main-hue), var(--main-saturation), calc(var(--value-base) - (2 * var(--value-step))));
|
||||
--background-color4: hsl(var(--main-hue), var(--main-saturation), calc(var(--value-base) - (3 * var(--value-step))));
|
||||
|
||||
--accent-hue: 212;
|
||||
--make-image-border: none;
|
||||
|
||||
--button-color: var(--accent-color);
|
||||
--button-border: none;
|
||||
|
||||
--input-border-size: 1px;
|
||||
--input-background-color: var(--background-color3);
|
||||
--input-text-color: #ccc;
|
||||
--input-border-color: var(--background-color4);
|
||||
}
|
||||
|
||||
|
||||
.theme-blurple {
|
||||
--main-hue: 235;
|
||||
--main-saturation: 18%;
|
||||
--value-base: 16%;
|
||||
--value-step: 3%;
|
||||
--background-color1: hsl(var(--main-hue), var(--main-saturation), var(--value-base));
|
||||
--background-color2: hsl(var(--main-hue), var(--main-saturation), calc(var(--value-base) - (1 * var(--value-step))));
|
||||
--background-color3: hsl(var(--main-hue), var(--main-saturation), calc(var(--value-base) - (2 * var(--value-step))));
|
||||
--background-color4: hsl(var(--main-hue), var(--main-saturation), calc(var(--value-base) - (3 * var(--value-step))));
|
||||
|
||||
--make-image-border: none;
|
||||
|
||||
--button-color: var(--accent-color);
|
||||
--button-border: none;
|
||||
|
||||
--input-border-size: 1px;
|
||||
--input-background-color: var(--background-color3);
|
||||
--input-text-color: #ccc;
|
||||
--input-border-color: var(--background-color4);
|
||||
}
|
||||
|
||||
.theme-super-dark {
|
||||
--main-hue: 222;
|
||||
--main-saturation: 18%;
|
||||
--value-base: 5%;
|
||||
--value-step: 5%;
|
||||
--background-color1: hsl(var(--main-hue), var(--main-saturation), var(--value-base));
|
||||
--background-color2: hsl(var(--main-hue), var(--main-saturation), calc(var(--value-base) + (1 * var(--value-step))));
|
||||
--background-color3: hsl(var(--main-hue), var(--main-saturation), calc(var(--value-base) + (2 * var(--value-step))));
|
||||
--background-color4: hsl(var(--main-hue), var(--main-saturation), calc(var(--value-base) + (3 * var(--value-step))));
|
||||
|
||||
--make-image-border: none;
|
||||
|
||||
--button-color: var(--accent-color);
|
||||
--button-border: none;
|
||||
|
||||
--input-border-size: 0px;
|
||||
--input-background-color: var(--background-color3);
|
||||
--input-text-color: #ccc;
|
||||
--input-border-color: var(--background-color4);
|
||||
}
|
||||
|
||||
.theme-wild {
|
||||
--main-hue: 128;
|
||||
--main-saturation: 18%;
|
||||
--value-base: 20%;
|
||||
--value-step: 5%;
|
||||
--background-color1: hsl(var(--main-hue), var(--main-saturation), var(--value-base));
|
||||
--background-color2: hsl(var(--main-hue), var(--main-saturation), calc(var(--value-base) - (1 * var(--value-step))));
|
||||
--background-color3: hsl(var(--main-hue), var(--main-saturation), calc(var(--value-base) - (2 * var(--value-step))));
|
||||
--background-color4: hsl(var(--main-hue), var(--main-saturation), calc(var(--value-base) - (3 * var(--value-step))));
|
||||
|
||||
--accent-hue: 212;
|
||||
--make-image-border: none;
|
||||
|
||||
--button-color: var(--accent-color);
|
||||
--button-border: none;
|
||||
|
||||
--input-border-size: 1px;
|
||||
--input-background-color: hsl(222, var(--main-saturation), calc(var(--value-base) - (2 * var(--value-step))));
|
||||
--input-text-color: red;
|
||||
--input-border-color: green;
|
||||
}
|
||||
|
||||
|
||||
* {
|
||||
font-family: Work Sans, Verdana, Geneva, sans-serif;
|
||||
box-sizing: border-box;
|
||||
@ -164,7 +16,7 @@ a:visited {
|
||||
color: rgb(0, 102, 204);
|
||||
}
|
||||
label {
|
||||
font-size: 9pt;
|
||||
font-size: 10pt;
|
||||
}
|
||||
#prompt {
|
||||
width: 100%;
|
||||
@ -252,7 +104,7 @@ label {
|
||||
margin-bottom: 7px;
|
||||
}
|
||||
#container {
|
||||
width: 90%;
|
||||
width: 95%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
@ -681,24 +533,6 @@ input::file-selector-button {
|
||||
height: 19px;
|
||||
}
|
||||
|
||||
/* input[type="range"] {
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
cursor: pointer;
|
||||
line-height: 29px;
|
||||
}
|
||||
|
||||
input[type="range"]::-webkit-slider-thumb,
|
||||
input[type="range"]::-moz-range-thumb {
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border-radius: 12px;
|
||||
} */
|
||||
|
||||
@media screen and (max-width: 700px) {
|
||||
body {
|
||||
margin: 0px;
|
||||
@ -736,56 +570,6 @@ input[type="range"]::-moz-range-thumb {
|
||||
}
|
||||
}
|
||||
|
||||
/* Auto-Settings Styling */
|
||||
#auto_save_settings:not(:checked) ~ button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#save-settings-config {
|
||||
position: fixed;
|
||||
background: rgba(32, 33, 36, 50%);
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
#save-settings-config > div {
|
||||
background: var(--background-color2);
|
||||
max-width: 600px;
|
||||
margin: auto;
|
||||
margin-top: 100px;
|
||||
border-radius: 6px;
|
||||
padding: 30px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#save-settings-config-table {
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
#save-settings-config-table td:first-child,
|
||||
#save-settings-config-table th:first-child {
|
||||
float: right;
|
||||
}
|
||||
|
||||
#save-settings-config-table td:last-child,
|
||||
#save-settings-config-table th:last-child {
|
||||
float: left;
|
||||
}
|
||||
|
||||
#save-settings-config-table td small {
|
||||
color: rgb(153, 153, 153);
|
||||
}
|
||||
|
||||
#save-settings-config-close-btn {
|
||||
float: right;
|
||||
cursor: pointer;
|
||||
padding: 10px;
|
||||
transform: translate(50%, -50%) scaleX(130%);
|
||||
}
|
||||
|
||||
#promptsFromFileBtn {
|
||||
font-size: 9pt;
|
||||
}
|
||||
}
|
146
ui/media/css/themes.css
Normal file
146
ui/media/css/themes.css
Normal file
@ -0,0 +1,146 @@
|
||||
:root {
|
||||
--background-color1: rgb(32, 33, 36); /* main parts of the page */
|
||||
--background-color2: rgb(44, 45, 48); /* main panels */
|
||||
--background-color3: rgb(47, 49, 53);
|
||||
--background-color4: rgb(18, 18, 19); /* settings dropdowns */
|
||||
|
||||
--accent-hue: 266;
|
||||
--accent-lightness: 36%;
|
||||
--accent-lightness-hover: 40%;
|
||||
|
||||
--text-color: #eee;
|
||||
|
||||
--input-text-color: black;
|
||||
--input-background-color: #e9e9ed;
|
||||
--input-border-color: #8f8f9d;
|
||||
|
||||
--button-text-color: var(--input-text-color);
|
||||
--button-color: #e9e9ed;
|
||||
--button-border: 1px solid #8f8f9d;
|
||||
|
||||
/* other */
|
||||
--input-border-radius: 4px;
|
||||
--input-border-size: 1px;
|
||||
--accent-color: hsl(var(--accent-hue), 100%, var(--accent-lightness));
|
||||
--accent-color-hover: hsl(var(--accent-hue), 100%, var(--accent-lightness-hover));
|
||||
--make-image-border: 2px solid hsl(var(--accent-hue), 100%, calc(var(--accent-lightness) - 21%));
|
||||
}
|
||||
|
||||
.theme-light {
|
||||
--background-color1: white;
|
||||
--background-color2: #dddddd;
|
||||
--background-color3: #e7e9eb;
|
||||
--background-color4: #cccccc;
|
||||
|
||||
--text-color: black;
|
||||
|
||||
--input-text-color: black;
|
||||
--input-background-color: #f8f9fa;
|
||||
--input-border-color: grey;
|
||||
}
|
||||
|
||||
.theme-discord {
|
||||
--background-color1: #36393f;
|
||||
--background-color2: #2f3136;
|
||||
--background-color3: #292b2f;
|
||||
--background-color4: #202225;
|
||||
|
||||
--accent-hue: 235;
|
||||
--accent-lightness: 65%;
|
||||
--make-image-border: none;
|
||||
|
||||
--button-color: var(--accent-color);
|
||||
--button-border: none;
|
||||
|
||||
--input-text-color: #ccc;
|
||||
--input-border-size: 2px;
|
||||
--input-background-color: #202225;
|
||||
--input-border-color: var(--input-background-color);
|
||||
}
|
||||
|
||||
.theme-cool-blue {
|
||||
--main-hue: 222;
|
||||
--main-saturation: 18%;
|
||||
--value-base: 19%;
|
||||
--value-step: 3%;
|
||||
--background-color1: hsl(var(--main-hue), var(--main-saturation), var(--value-base));
|
||||
--background-color2: hsl(var(--main-hue), var(--main-saturation), calc(var(--value-base) - (1 * var(--value-step))));
|
||||
--background-color3: hsl(var(--main-hue), var(--main-saturation), calc(var(--value-base) - (2 * var(--value-step))));
|
||||
--background-color4: hsl(var(--main-hue), var(--main-saturation), calc(var(--value-base) - (3 * var(--value-step))));
|
||||
|
||||
--accent-hue: 212;
|
||||
--make-image-border: none;
|
||||
|
||||
--button-color: var(--accent-color);
|
||||
--button-border: none;
|
||||
|
||||
--input-border-size: 1px;
|
||||
--input-background-color: var(--background-color3);
|
||||
--input-text-color: #ccc;
|
||||
--input-border-color: var(--background-color4);
|
||||
}
|
||||
|
||||
|
||||
.theme-blurple {
|
||||
--main-hue: 235;
|
||||
--main-saturation: 18%;
|
||||
--value-base: 16%;
|
||||
--value-step: 3%;
|
||||
--background-color1: hsl(var(--main-hue), var(--main-saturation), var(--value-base));
|
||||
--background-color2: hsl(var(--main-hue), var(--main-saturation), calc(var(--value-base) - (1 * var(--value-step))));
|
||||
--background-color3: hsl(var(--main-hue), var(--main-saturation), calc(var(--value-base) - (2 * var(--value-step))));
|
||||
--background-color4: hsl(var(--main-hue), var(--main-saturation), calc(var(--value-base) - (3 * var(--value-step))));
|
||||
|
||||
--make-image-border: none;
|
||||
|
||||
--button-color: var(--accent-color);
|
||||
--button-border: none;
|
||||
|
||||
--input-border-size: 1px;
|
||||
--input-background-color: var(--background-color3);
|
||||
--input-text-color: #ccc;
|
||||
--input-border-color: var(--background-color4);
|
||||
}
|
||||
|
||||
.theme-super-dark {
|
||||
--main-hue: 222;
|
||||
--main-saturation: 18%;
|
||||
--value-base: 5%;
|
||||
--value-step: 5%;
|
||||
--background-color1: hsl(var(--main-hue), var(--main-saturation), var(--value-base));
|
||||
--background-color2: hsl(var(--main-hue), var(--main-saturation), calc(var(--value-base) + (1 * var(--value-step))));
|
||||
--background-color3: hsl(var(--main-hue), var(--main-saturation), calc(var(--value-base) + (2 * var(--value-step))));
|
||||
--background-color4: hsl(var(--main-hue), var(--main-saturation), calc(var(--value-base) + (3 * var(--value-step))));
|
||||
|
||||
--make-image-border: none;
|
||||
|
||||
--button-color: var(--accent-color);
|
||||
--button-border: none;
|
||||
|
||||
--input-border-size: 0px;
|
||||
--input-background-color: var(--background-color3);
|
||||
--input-text-color: #ccc;
|
||||
--input-border-color: var(--background-color4);
|
||||
}
|
||||
|
||||
.theme-wild {
|
||||
--main-hue: 128;
|
||||
--main-saturation: 18%;
|
||||
--value-base: 20%;
|
||||
--value-step: 5%;
|
||||
--background-color1: hsl(var(--main-hue), var(--main-saturation), var(--value-base));
|
||||
--background-color2: hsl(var(--main-hue), var(--main-saturation), calc(var(--value-base) - (1 * var(--value-step))));
|
||||
--background-color3: hsl(var(--main-hue), var(--main-saturation), calc(var(--value-base) - (2 * var(--value-step))));
|
||||
--background-color4: hsl(var(--main-hue), var(--main-saturation), calc(var(--value-base) - (3 * var(--value-step))));
|
||||
|
||||
--accent-hue: 212;
|
||||
--make-image-border: none;
|
||||
|
||||
--button-color: var(--accent-color);
|
||||
--button-border: none;
|
||||
|
||||
--input-border-size: 1px;
|
||||
--input-background-color: hsl(222, var(--main-saturation), calc(var(--value-base) - (2 * var(--value-step))));
|
||||
--input-text-color: red;
|
||||
--input-border-color: green;
|
||||
}
|
BIN
ui/media/fonts/fa-brands-400.ttf
Normal file
BIN
ui/media/fonts/fa-brands-400.ttf
Normal file
Binary file not shown.
BIN
ui/media/fonts/fa-brands-400.woff2
Normal file
BIN
ui/media/fonts/fa-brands-400.woff2
Normal file
Binary file not shown.
BIN
ui/media/fonts/fa-regular-400.ttf
Normal file
BIN
ui/media/fonts/fa-regular-400.ttf
Normal file
Binary file not shown.
BIN
ui/media/fonts/fa-regular-400.woff2
Normal file
BIN
ui/media/fonts/fa-regular-400.woff2
Normal file
Binary file not shown.
BIN
ui/media/fonts/fa-solid-900.ttf
Normal file
BIN
ui/media/fonts/fa-solid-900.ttf
Normal file
Binary file not shown.
BIN
ui/media/fonts/fa-solid-900.woff2
Normal file
BIN
ui/media/fonts/fa-solid-900.woff2
Normal file
Binary file not shown.
BIN
ui/media/fonts/fa-v4compatibility.ttf
Normal file
BIN
ui/media/fonts/fa-v4compatibility.ttf
Normal file
Binary file not shown.
BIN
ui/media/fonts/fa-v4compatibility.woff2
Normal file
BIN
ui/media/fonts/fa-v4compatibility.woff2
Normal file
Binary file not shown.
BIN
ui/media/fonts/work-sans-v18-latin-600.woff
Normal file
BIN
ui/media/fonts/work-sans-v18-latin-600.woff
Normal file
Binary file not shown.
BIN
ui/media/fonts/work-sans-v18-latin-600.woff2
Normal file
BIN
ui/media/fonts/work-sans-v18-latin-600.woff2
Normal file
Binary file not shown.
BIN
ui/media/fonts/work-sans-v18-latin-700.woff
Normal file
BIN
ui/media/fonts/work-sans-v18-latin-700.woff
Normal file
Binary file not shown.
BIN
ui/media/fonts/work-sans-v18-latin-700.woff2
Normal file
BIN
ui/media/fonts/work-sans-v18-latin-700.woff2
Normal file
Binary file not shown.
BIN
ui/media/fonts/work-sans-v18-latin-800.woff
Normal file
BIN
ui/media/fonts/work-sans-v18-latin-800.woff
Normal file
Binary file not shown.
BIN
ui/media/fonts/work-sans-v18-latin-800.woff2
Normal file
BIN
ui/media/fonts/work-sans-v18-latin-800.woff2
Normal file
Binary file not shown.
BIN
ui/media/fonts/work-sans-v18-latin-regular.woff
Normal file
BIN
ui/media/fonts/work-sans-v18-latin-regular.woff
Normal file
Binary file not shown.
BIN
ui/media/fonts/work-sans-v18-latin-regular.woff2
Normal file
BIN
ui/media/fonts/work-sans-v18-latin-regular.woff2
Normal file
Binary file not shown.
Before Width: | Height: | Size: 466 B After Width: | Height: | Size: 466 B |
Before Width: | Height: | Size: 973 B After Width: | Height: | Size: 973 B |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
230
ui/media/js/image-modifiers.js
Normal file
230
ui/media/js/image-modifiers.js
Normal file
@ -0,0 +1,230 @@
|
||||
let activeTags = []
|
||||
let modifiers = []
|
||||
|
||||
let editorModifierEntries = document.querySelector('#editor-modifiers-entries')
|
||||
let editorModifierTagsList = document.querySelector('#editor-inputs-tags-list')
|
||||
let editorTagsContainer = document.querySelector('#editor-inputs-tags-container')
|
||||
let modifierCardSizeSlider = document.querySelector('#modifier-card-size-slider')
|
||||
let previewImageField = document.querySelector('#preview-image')
|
||||
|
||||
const modifierThumbnailPath = 'media/modifier-thumbnails'
|
||||
const activeCardClass = 'modifier-card-active'
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
async function loadModifiers() {
|
||||
try {
|
||||
let res = await fetch('/get/modifiers')
|
||||
if (res.status === 200) {
|
||||
res = await res.json()
|
||||
|
||||
modifiers = res; // update global variable
|
||||
|
||||
res.forEach((modifierGroup, idx) => {
|
||||
const title = modifierGroup.category
|
||||
const modifiers = modifierGroup.modifiers
|
||||
|
||||
const titleEl = document.createElement('h5')
|
||||
titleEl.className = 'collapsible'
|
||||
titleEl.innerText = title
|
||||
|
||||
const modifiersEl = document.createElement('div')
|
||||
modifiersEl.classList.add('collapsible-content', 'editor-modifiers-leaf')
|
||||
|
||||
if (idx == 0) {
|
||||
titleEl.className += ' active'
|
||||
modifiersEl.style.display = 'block'
|
||||
}
|
||||
|
||||
modifiers.forEach(modObj => {
|
||||
const modifierName = modObj.modifier
|
||||
const modifierPreviews = modObj?.previews?.map(preview => `${modifierThumbnailPath}/${preview.path}`)
|
||||
|
||||
const modifierCard = createModifierCard(modifierName, modifierPreviews)
|
||||
|
||||
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 = '-'
|
||||
}
|
||||
|
||||
refreshTagsList()
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
let brk = document.createElement('br')
|
||||
brk.style.clear = 'both'
|
||||
modifiersEl.appendChild(brk)
|
||||
|
||||
let e = document.createElement('div')
|
||||
e.appendChild(titleEl)
|
||||
e.appendChild(modifiersEl)
|
||||
|
||||
editorModifierEntries.appendChild(e)
|
||||
})
|
||||
|
||||
createCollapsibles(editorModifierEntries)
|
||||
}
|
||||
} catch (e) {
|
||||
console.log('error fetching modifiers', e)
|
||||
}
|
||||
}
|
||||
|
||||
function refreshTagsList() {
|
||||
editorModifierTagsList.innerHTML = ''
|
||||
|
||||
if (activeTags.length == 0) {
|
||||
editorTagsContainer.style.display = 'none'
|
||||
return
|
||||
} else {
|
||||
editorTagsContainer.style.display = 'block'
|
||||
}
|
||||
|
||||
activeTags.forEach((tag, index) => {
|
||||
tag.element.querySelector('.modifier-card-image-overlay').innerText = '-'
|
||||
tag.element.classList.add('modifier-card-tiny')
|
||||
|
||||
editorModifierTagsList.appendChild(tag.element)
|
||||
|
||||
tag.element.addEventListener('click', () => {
|
||||
let idx = activeTags.indexOf(tag)
|
||||
|
||||
if (idx !== -1) {
|
||||
activeTags[idx].originElement.classList.remove(activeCardClass)
|
||||
activeTags[idx].originElement.querySelector('.modifier-card-image-overlay').innerText = '+'
|
||||
|
||||
activeTags.splice(idx, 1)
|
||||
refreshTagsList()
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
let brk = document.createElement('br')
|
||||
brk.style.clear = 'both'
|
||||
editorModifierTagsList.appendChild(brk)
|
||||
}
|
||||
|
||||
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))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
modifierCardSizeSlider.onchange = () => resizeModifierCards(modifierCardSizeSlider.value)
|
||||
previewImageField.onchange = () => changePreviewImages(previewImageField.value)
|
41
ui/media/js/inpainting-editor.js
Normal file
41
ui/media/js/inpainting-editor.js
Normal file
@ -0,0 +1,41 @@
|
||||
const INPAINTING_EDITOR_SIZE = 450
|
||||
|
||||
let inpaintingEditorContainer = document.querySelector('#inpaintingEditor')
|
||||
let inpaintingEditor = new DrawingBoard.Board('inpaintingEditor', {
|
||||
color: "#ffffff",
|
||||
background: false,
|
||||
size: 30,
|
||||
webStorage: false,
|
||||
controls: [{'DrawingMode': {'filler': false}}, 'Size', 'Navigation']
|
||||
})
|
||||
let inpaintingEditorCanvasBackground = document.querySelector('.drawing-board-canvas-wrapper')
|
||||
|
||||
function resizeInpaintingEditor(widthValue, heightValue) {
|
||||
if (widthValue === heightValue) {
|
||||
widthValue = INPAINTING_EDITOR_SIZE
|
||||
heightValue = INPAINTING_EDITOR_SIZE
|
||||
} else if (widthValue > heightValue) {
|
||||
heightValue = (heightValue / widthValue) * INPAINTING_EDITOR_SIZE
|
||||
widthValue = INPAINTING_EDITOR_SIZE
|
||||
} else {
|
||||
widthValue = (widthValue / heightValue) * INPAINTING_EDITOR_SIZE
|
||||
heightValue = INPAINTING_EDITOR_SIZE
|
||||
}
|
||||
if (inpaintingEditor.opts.aspectRatio === (widthValue / heightValue).toFixed(3)) {
|
||||
// Same ratio, don't reset the canvas.
|
||||
return
|
||||
}
|
||||
inpaintingEditor.opts.aspectRatio = (widthValue / heightValue).toFixed(3)
|
||||
|
||||
inpaintingEditorContainer.style.width = widthValue + 'px'
|
||||
inpaintingEditorContainer.style.height = heightValue + 'px'
|
||||
inpaintingEditor.opts.enlargeYourContainer = true
|
||||
|
||||
inpaintingEditor.opts.size = inpaintingEditor.ctx.lineWidth
|
||||
inpaintingEditor.resize()
|
||||
|
||||
inpaintingEditor.ctx.lineCap = "round"
|
||||
inpaintingEditor.ctx.lineJoin = "round"
|
||||
inpaintingEditor.ctx.lineWidth = inpaintingEditor.opts.size
|
||||
inpaintingEditor.setColor(inpaintingEditor.opts.color)
|
||||
}
|
@ -16,7 +16,6 @@ const OUTPUT_FORMAT_KEY = "outputFormat"
|
||||
const AUTO_SAVE_SETTINGS_KEY = "autoSaveSettings"
|
||||
const HEALTH_PING_INTERVAL = 5 // seconds
|
||||
const MAX_INIT_IMAGE_DIMENSION = 768
|
||||
const INPAINTING_EDITOR_SIZE = 450
|
||||
|
||||
const IMAGE_REGEX = new RegExp('data:image/[A-Za-z]+;base64')
|
||||
|
||||
@ -80,16 +79,7 @@ let clearAllPreviewsBtn = document.querySelector("#clear-all-previews")
|
||||
let maskSetting = document.querySelector('#enable_mask')
|
||||
let negativePromptPanelHandle = document.querySelector('#negative_prompt_handle')
|
||||
|
||||
let editorModifierEntries = document.querySelector('#editor-modifiers-entries')
|
||||
let editorModifierTagsList = document.querySelector('#editor-inputs-tags-list')
|
||||
let editorTagsContainer = document.querySelector('#editor-inputs-tags-container')
|
||||
|
||||
let imagePreview = document.querySelector("#preview")
|
||||
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')
|
||||
|
||||
@ -105,15 +95,6 @@ let serverStatusMsg = document.querySelector('#server-status-msg')
|
||||
|
||||
let advancedPanelHandle = document.querySelector("#editor-settings .collapsible")
|
||||
let modifiersPanelHandle = document.querySelector("#editor-modifiers .collapsible")
|
||||
let inpaintingEditorContainer = document.querySelector('#inpaintingEditor')
|
||||
let inpaintingEditor = new DrawingBoard.Board('inpaintingEditor', {
|
||||
color: "#ffffff",
|
||||
background: false,
|
||||
size: 30,
|
||||
webStorage: false,
|
||||
controls: [{'DrawingMode': {'filler': false}}, 'Size', 'Navigation']
|
||||
})
|
||||
let inpaintingEditorCanvasBackground = document.querySelector('.drawing-board-canvas-wrapper')
|
||||
|
||||
document.querySelector('.drawing-board-control-navigation-back').innerHTML = '<i class="fa-solid fa-rotate-left"></i>'
|
||||
document.querySelector('.drawing-board-control-navigation-forward').innerHTML = '<i class="fa-solid fa-rotate-right"></i>'
|
||||
@ -124,17 +105,12 @@ maskResetButton.style.fontWeight = 'normal'
|
||||
maskResetButton.style.fontSize = '10pt'
|
||||
|
||||
let serverState = {'status': 'Offline', 'time': Date.now()}
|
||||
let activeTags = []
|
||||
let modifiers = []
|
||||
let lastPromptUsed = ''
|
||||
let bellPending = false
|
||||
|
||||
let taskQueue = []
|
||||
let currentTask = null
|
||||
|
||||
const modifierThumbnailPath = 'media/modifier-thumbnails'
|
||||
const activeCardClass = 'modifier-card-active'
|
||||
|
||||
function getLocalStorageItem(key, fallback) {
|
||||
let item = localStorage.getItem(key)
|
||||
if (item === null) {
|
||||
@ -336,40 +312,6 @@ async function healthCheck() {
|
||||
setServerStatus('error', 'offline')
|
||||
}
|
||||
}
|
||||
function resizeInpaintingEditor() {
|
||||
if (!maskSetting.checked) {
|
||||
return
|
||||
}
|
||||
let widthValue = parseInt(widthField.value)
|
||||
let heightValue = parseInt(heightField.value)
|
||||
if (widthValue === heightValue) {
|
||||
widthValue = INPAINTING_EDITOR_SIZE
|
||||
heightValue = INPAINTING_EDITOR_SIZE
|
||||
} else if (widthValue > heightValue) {
|
||||
heightValue = (heightValue / widthValue) * INPAINTING_EDITOR_SIZE
|
||||
widthValue = INPAINTING_EDITOR_SIZE
|
||||
} else {
|
||||
widthValue = (widthValue / heightValue) * INPAINTING_EDITOR_SIZE
|
||||
heightValue = INPAINTING_EDITOR_SIZE
|
||||
}
|
||||
if (inpaintingEditor.opts.aspectRatio === (widthValue / heightValue).toFixed(3)) {
|
||||
// Same ratio, don't reset the canvas.
|
||||
return
|
||||
}
|
||||
inpaintingEditor.opts.aspectRatio = (widthValue / heightValue).toFixed(3)
|
||||
|
||||
inpaintingEditorContainer.style.width = widthValue + 'px'
|
||||
inpaintingEditorContainer.style.height = heightValue + 'px'
|
||||
inpaintingEditor.opts.enlargeYourContainer = true
|
||||
|
||||
inpaintingEditor.opts.size = inpaintingEditor.ctx.lineWidth
|
||||
inpaintingEditor.resize()
|
||||
|
||||
inpaintingEditor.ctx.lineCap = "round"
|
||||
inpaintingEditor.ctx.lineJoin = "round"
|
||||
inpaintingEditor.ctx.lineWidth = inpaintingEditor.opts.size
|
||||
inpaintingEditor.setColor(inpaintingEditor.opts.color)
|
||||
}
|
||||
|
||||
function showImages(reqBody, res, outputContainer, livePreview) {
|
||||
let imageItemElements = outputContainer.querySelectorAll('.imgItem')
|
||||
@ -464,9 +406,9 @@ function getUseAsInputHandler(imageItemElem) {
|
||||
|
||||
// maskSetting.style.display = 'block'
|
||||
|
||||
randomSeedField.checked = false
|
||||
seedField.value = imageSeed
|
||||
seedField.disabled = false
|
||||
// randomSeedField.checked = false
|
||||
// seedField.value = imageSeed
|
||||
// seedField.disabled = false
|
||||
}
|
||||
}
|
||||
|
||||
@ -609,7 +551,6 @@ async function doMakeImage(task) {
|
||||
let reader = res.body.getReader()
|
||||
let textDecoder = new TextDecoder()
|
||||
let finalJSON = ''
|
||||
let prevTime = -1
|
||||
let readComplete = false
|
||||
while (!readComplete || finalJSON.length > 0) {
|
||||
let t = Date.now()
|
||||
@ -664,11 +605,11 @@ async function doMakeImage(task) {
|
||||
let percent = 100 * (overallStepCount / totalSteps)
|
||||
percent = (percent > 100 ? 100 : percent)
|
||||
percent = percent.toFixed(0)
|
||||
let timeTaken = (prevTime === -1 ? -1 : t - prevTime)
|
||||
let timeTaken = stepUpdate.step_time // sec
|
||||
|
||||
let stepsRemaining = totalSteps - overallStepCount
|
||||
stepsRemaining = (stepsRemaining < 0 ? 0 : stepsRemaining)
|
||||
let timeRemaining = (timeTaken === -1 ? '' : stepsRemaining * timeTaken) // ms
|
||||
let timeRemaining = (timeTaken === -1 ? '' : stepsRemaining * timeTaken * 1000) // ms
|
||||
|
||||
outputMsg.innerHTML = `Batch ${task.batchesDone+1} of ${batchCount}`
|
||||
outputMsg.innerHTML += `. Generating image(s): ${percent}%`
|
||||
@ -698,7 +639,6 @@ async function doMakeImage(task) {
|
||||
console.log('Stream stopped: ', res)
|
||||
}
|
||||
}
|
||||
prevTime = t
|
||||
}
|
||||
|
||||
if (typeof stepUpdate === 'object' && stepUpdate.status !== 'succeeded') {
|
||||
@ -986,12 +926,19 @@ function createTask(task) {
|
||||
imagePreview.insertBefore(taskEntry, previewTools.nextSibling)
|
||||
|
||||
task.previewPrompt.innerText = task.reqBody.prompt
|
||||
if (task.previewPrompt.innerText.trim() === '') {
|
||||
task.previewPrompt.innerHTML = ' ' // allows the results to be collapsed
|
||||
}
|
||||
|
||||
taskQueue.unshift(task)
|
||||
}
|
||||
|
||||
function getPrompts() {
|
||||
let prompts = promptField.value
|
||||
if (prompts.trim() === '') {
|
||||
return ['']
|
||||
}
|
||||
|
||||
prompts = prompts.split('\n')
|
||||
|
||||
let promptsToMake = []
|
||||
@ -1041,28 +988,6 @@ function permutePrompts(promptBase, promptMatrix) {
|
||||
return prompts
|
||||
}
|
||||
|
||||
function permute(arr) {
|
||||
let permutations = []
|
||||
let n = arr.length
|
||||
let n_permutations = Math.pow(2, n)
|
||||
for (let i = 0; i < n_permutations; i++) {
|
||||
let perm = []
|
||||
let mask = Number(i).toString(2).padStart(n, '0')
|
||||
|
||||
for (let idx = 0; idx < mask.length; idx++) {
|
||||
if (mask[idx] === '1' && arr[idx].trim() !== '') {
|
||||
perm.push(arr[idx])
|
||||
}
|
||||
}
|
||||
|
||||
if (perm.length > 0) {
|
||||
permutations.push(perm)
|
||||
}
|
||||
}
|
||||
|
||||
return permutations
|
||||
}
|
||||
|
||||
// create a file name with embedded prompt and metadata
|
||||
// for easier cateloging and comparison
|
||||
function createFileName(prompt, seed, steps, guidance, outputFormat) {
|
||||
@ -1165,8 +1090,18 @@ outputFormatField.addEventListener('change', handleStringSettingChange(OUTPUT_FO
|
||||
outputFormatField.value = getOutputFormat()
|
||||
|
||||
diskPathField.addEventListener('change', handleStringSettingChange(DISK_PATH_KEY))
|
||||
widthField.addEventListener('change', resizeInpaintingEditor)
|
||||
heightField.addEventListener('change', resizeInpaintingEditor)
|
||||
widthField.addEventListener('change', onDimensionChange)
|
||||
heightField.addEventListener('change', onDimensionChange)
|
||||
|
||||
function onDimensionChange() {
|
||||
if (!maskSetting.checked) {
|
||||
return
|
||||
}
|
||||
let widthValue = parseInt(widthField.value)
|
||||
let heightValue = parseInt(heightField.value)
|
||||
|
||||
resizeInpaintingEditor(widthValue, heightValue)
|
||||
}
|
||||
|
||||
saveToDiskField.addEventListener('click', function(e) {
|
||||
diskPathField.disabled = !this.checked
|
||||
@ -1375,7 +1310,7 @@ initImageClearBtn.addEventListener('click', function() {
|
||||
|
||||
maskSetting.addEventListener('click', function() {
|
||||
inpaintingEditorContainer.style.display = (this.checked ? 'block' : 'none')
|
||||
resizeInpaintingEditor()
|
||||
onDimensionChange()
|
||||
})
|
||||
|
||||
promptsFromFileBtn.addEventListener('click', function() {
|
||||
@ -1399,150 +1334,6 @@ promptsFromFileSelector.addEventListener('change', function() {
|
||||
}
|
||||
})
|
||||
|
||||
// function showMaskImagePreview() {
|
||||
// if (maskImageSelector.files.length === 0) {
|
||||
// // maskImagePreviewContainer.style.display = 'none'
|
||||
// return
|
||||
// }
|
||||
|
||||
// let reader = new FileReader()
|
||||
// let file = maskImageSelector.files[0]
|
||||
|
||||
// reader.addEventListener('load', function() {
|
||||
// // maskImagePreview.src = reader.result
|
||||
// // maskImagePreviewContainer.style.display = 'block'
|
||||
// })
|
||||
|
||||
// if (file) {
|
||||
// reader.readAsDataURL(file)
|
||||
// }
|
||||
// }
|
||||
// maskImageSelector.addEventListener('change', showMaskImagePreview)
|
||||
// showMaskImagePreview()
|
||||
|
||||
// maskImageClearBtn.addEventListener('click', function() {
|
||||
// maskImageSelector.value = null
|
||||
// maskImagePreview.src = ''
|
||||
// // maskImagePreviewContainer.style.display = 'none'
|
||||
// })
|
||||
|
||||
// https://stackoverflow.com/a/8212878
|
||||
function millisecondsToStr(milliseconds) {
|
||||
function numberEnding (number) {
|
||||
return (number > 1) ? 's' : ''
|
||||
}
|
||||
|
||||
var temp = Math.floor(milliseconds / 1000)
|
||||
var hours = Math.floor((temp %= 86400) / 3600)
|
||||
var s = ''
|
||||
if (hours) {
|
||||
s += hours + ' hour' + numberEnding(hours) + ' '
|
||||
}
|
||||
var minutes = Math.floor((temp %= 3600) / 60)
|
||||
if (minutes) {
|
||||
s += minutes + ' minute' + numberEnding(minutes) + ' '
|
||||
}
|
||||
var seconds = temp % 60
|
||||
if (!hours && minutes < 4 && seconds) {
|
||||
s += seconds + ' second' + numberEnding(seconds)
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
// https://gomakethings.com/finding-the-next-and-previous-sibling-elements-that-match-a-selector-with-vanilla-js/
|
||||
function getNextSibling(elem, selector) {
|
||||
// Get the next sibling element
|
||||
var sibling = elem.nextElementSibling
|
||||
|
||||
// If there's no selector, return the first sibling
|
||||
if (!selector) return sibling
|
||||
|
||||
// If the sibling matches our selector, use it
|
||||
// If not, jump to the next sibling and continue the loop
|
||||
while (sibling) {
|
||||
if (sibling.matches(selector)) return sibling
|
||||
sibling = sibling.nextElementSibling
|
||||
}
|
||||
}
|
||||
|
||||
function createCollapsibles(node) {
|
||||
if (!node) {
|
||||
node = document
|
||||
}
|
||||
|
||||
let collapsibles = node.querySelectorAll(".collapsible")
|
||||
collapsibles.forEach(function(c) {
|
||||
let handle = document.createElement('span')
|
||||
handle.className = 'collapsible-handle'
|
||||
|
||||
if (c.className.indexOf('active') !== -1) {
|
||||
handle.innerHTML = '➖' // minus
|
||||
} else {
|
||||
handle.innerHTML = '➕' // plus
|
||||
}
|
||||
c.insertBefore(handle, c.firstChild)
|
||||
|
||||
c.addEventListener('click', function() {
|
||||
this.classList.toggle("active")
|
||||
let content = getNextSibling(this, '.collapsible-content')
|
||||
if (content.style.display === "block") {
|
||||
content.style.display = "none"
|
||||
handle.innerHTML = '➕' // plus
|
||||
} else {
|
||||
content.style.display = "block"
|
||||
handle.innerHTML = '➖' // minus
|
||||
}
|
||||
|
||||
if (this == advancedPanelHandle) {
|
||||
let state = (content.style.display === 'block' ? 'true' : 'false')
|
||||
localStorage.setItem(ADVANCED_PANEL_OPEN_KEY, state)
|
||||
} else if (this == modifiersPanelHandle) {
|
||||
let state = (content.style.display === 'block' ? 'true' : 'false')
|
||||
localStorage.setItem(MODIFIERS_PANEL_OPEN_KEY, state)
|
||||
} else if (this == negativePromptPanelHandle) {
|
||||
let state = (content.style.display === 'block' ? 'true' : 'false')
|
||||
localStorage.setItem(NEGATIVE_PROMPT_PANEL_OPEN_KEY, state)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
createCollapsibles()
|
||||
|
||||
function refreshTagsList() {
|
||||
editorModifierTagsList.innerHTML = ''
|
||||
|
||||
if (activeTags.length == 0) {
|
||||
editorTagsContainer.style.display = 'none'
|
||||
return
|
||||
} else {
|
||||
editorTagsContainer.style.display = 'block'
|
||||
}
|
||||
|
||||
activeTags.forEach((tag, index) => {
|
||||
tag.element.querySelector('.modifier-card-image-overlay').innerText = '-'
|
||||
tag.element.classList.add('modifier-card-tiny')
|
||||
|
||||
editorModifierTagsList.appendChild(tag.element)
|
||||
|
||||
tag.element.addEventListener('click', () => {
|
||||
let idx = activeTags.indexOf(tag)
|
||||
|
||||
if (idx !== -1) {
|
||||
activeTags[idx].originElement.classList.remove(activeCardClass)
|
||||
activeTags[idx].originElement.querySelector('.modifier-card-image-overlay').innerText = '+'
|
||||
|
||||
activeTags.splice(idx, 1)
|
||||
refreshTagsList()
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
let brk = document.createElement('br')
|
||||
brk.style.clear = 'both'
|
||||
editorModifierTagsList.appendChild(brk)
|
||||
}
|
||||
|
||||
async function getDiskPath() {
|
||||
try {
|
||||
let diskPath = getSavedDiskPath()
|
||||
@ -1564,246 +1355,4 @@ 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() {
|
||||
try {
|
||||
let res = await fetch('/get/modifiers')
|
||||
if (res.status === 200) {
|
||||
res = await res.json()
|
||||
|
||||
modifiers = res; // update global variable
|
||||
|
||||
res.forEach((modifierGroup, idx) => {
|
||||
const title = modifierGroup.category
|
||||
const modifiers = modifierGroup.modifiers
|
||||
|
||||
const titleEl = document.createElement('h5')
|
||||
titleEl.className = 'collapsible'
|
||||
titleEl.innerText = title
|
||||
|
||||
const modifiersEl = document.createElement('div')
|
||||
modifiersEl.classList.add('collapsible-content', 'editor-modifiers-leaf')
|
||||
|
||||
if (idx == 0) {
|
||||
titleEl.className += ' active'
|
||||
modifiersEl.style.display = 'block'
|
||||
}
|
||||
|
||||
modifiers.forEach(modObj => {
|
||||
const modifierName = modObj.modifier
|
||||
const modifierPreviews = modObj?.previews?.map(preview => `${modifierThumbnailPath}/${preview.path}`)
|
||||
|
||||
const modifierCard = createModifierCard(modifierName, modifierPreviews)
|
||||
|
||||
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 = '-'
|
||||
}
|
||||
|
||||
refreshTagsList()
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
let brk = document.createElement('br')
|
||||
brk.style.clear = 'both'
|
||||
modifiersEl.appendChild(brk)
|
||||
|
||||
let e = document.createElement('div')
|
||||
e.appendChild(titleEl)
|
||||
e.appendChild(modifiersEl)
|
||||
|
||||
editorModifierEntries.appendChild(e)
|
||||
})
|
||||
|
||||
createCollapsibles(editorModifierEntries)
|
||||
}
|
||||
} catch (e) {
|
||||
console.log('error fetching modifiers', e)
|
||||
}
|
||||
}
|
||||
|
||||
var DEFAULT_THEME = {};
|
||||
var THEMES = []; // initialized in initTheme from data in css
|
||||
|
||||
function getThemeName(theme) {
|
||||
theme = theme.replace("theme-", "");
|
||||
theme = theme.split("-").map(word => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
||||
return theme;
|
||||
}
|
||||
// init themefield
|
||||
function initTheme() {
|
||||
Array.from(document.styleSheets)
|
||||
.filter(sheet => sheet.href?.startsWith(window.location.origin))
|
||||
.flatMap(sheet => Array.from(sheet.cssRules))
|
||||
.forEach(rule => {
|
||||
var selector = rule.selectorText; // TODO: also do selector == ":root", re-run un-set props
|
||||
if (selector && selector.startsWith(".theme-")) {
|
||||
var theme_key = selector.substring(1);
|
||||
THEMES.push({
|
||||
key: theme_key,
|
||||
name: getThemeName(theme_key),
|
||||
rule: rule
|
||||
})
|
||||
}
|
||||
if (selector && selector == ":root") {
|
||||
DEFAULT_THEME = {
|
||||
key: "theme-default",
|
||||
name: "Default",
|
||||
rule: rule
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
THEMES.forEach(theme => {
|
||||
var new_option = document.createElement("option");
|
||||
new_option.setAttribute("value", theme.key);
|
||||
new_option.innerText = theme.name;
|
||||
themeField.appendChild(new_option);
|
||||
});
|
||||
}
|
||||
initTheme();
|
||||
|
||||
function themeFieldChanged() {
|
||||
var theme_key = themeField.value;
|
||||
|
||||
var body = document.querySelector("body");
|
||||
body.classList.remove(...THEMES.map(theme => theme.key));
|
||||
body.classList.add(theme_key);
|
||||
|
||||
body.style = "";
|
||||
var theme = THEMES.find(t => t.key == theme_key);
|
||||
if (theme) {
|
||||
// refresh variables incase they are back referencing
|
||||
Array.from(DEFAULT_THEME.rule.style)
|
||||
.filter(cssVariable => !Array.from(theme.rule.style).includes(cssVariable))
|
||||
.forEach(cssVariable => {
|
||||
body.style.setProperty(cssVariable, DEFAULT_THEME.rule.style.getPropertyValue(cssVariable));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
themeField.addEventListener('change', themeFieldChanged);
|
||||
createCollapsibles()
|
61
ui/media/js/themes.js
Normal file
61
ui/media/js/themes.js
Normal file
@ -0,0 +1,61 @@
|
||||
var DEFAULT_THEME = {};
|
||||
var THEMES = []; // initialized in initTheme from data in css
|
||||
|
||||
function getThemeName(theme) {
|
||||
theme = theme.replace("theme-", "");
|
||||
theme = theme.split("-").map(word => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
||||
return theme;
|
||||
}
|
||||
// init themefield
|
||||
function initTheme() {
|
||||
Array.from(document.styleSheets)
|
||||
.filter(sheet => sheet.href?.startsWith(window.location.origin))
|
||||
.flatMap(sheet => Array.from(sheet.cssRules))
|
||||
.forEach(rule => {
|
||||
var selector = rule.selectorText; // TODO: also do selector == ":root", re-run un-set props
|
||||
if (selector && selector.startsWith(".theme-")) {
|
||||
var theme_key = selector.substring(1);
|
||||
THEMES.push({
|
||||
key: theme_key,
|
||||
name: getThemeName(theme_key),
|
||||
rule: rule
|
||||
})
|
||||
}
|
||||
if (selector && selector == ":root") {
|
||||
DEFAULT_THEME = {
|
||||
key: "theme-default",
|
||||
name: "Default",
|
||||
rule: rule
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
THEMES.forEach(theme => {
|
||||
var new_option = document.createElement("option");
|
||||
new_option.setAttribute("value", theme.key);
|
||||
new_option.innerText = theme.name;
|
||||
themeField.appendChild(new_option);
|
||||
});
|
||||
}
|
||||
initTheme();
|
||||
|
||||
function themeFieldChanged() {
|
||||
var theme_key = themeField.value;
|
||||
|
||||
var body = document.querySelector("body");
|
||||
body.classList.remove(...THEMES.map(theme => theme.key));
|
||||
body.classList.add(theme_key);
|
||||
|
||||
body.style = "";
|
||||
var theme = THEMES.find(t => t.key == theme_key);
|
||||
if (theme) {
|
||||
// refresh variables incase they are back referencing
|
||||
Array.from(DEFAULT_THEME.rule.style)
|
||||
.filter(cssVariable => !Array.from(theme.rule.style).includes(cssVariable))
|
||||
.forEach(cssVariable => {
|
||||
body.style.setProperty(cssVariable, DEFAULT_THEME.rule.style.getPropertyValue(cssVariable));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
themeField.addEventListener('change', themeFieldChanged);
|
103
ui/media/js/utils.js
Normal file
103
ui/media/js/utils.js
Normal file
@ -0,0 +1,103 @@
|
||||
// https://gomakethings.com/finding-the-next-and-previous-sibling-elements-that-match-a-selector-with-vanilla-js/
|
||||
function getNextSibling(elem, selector) {
|
||||
// Get the next sibling element
|
||||
var sibling = elem.nextElementSibling
|
||||
|
||||
// If there's no selector, return the first sibling
|
||||
if (!selector) return sibling
|
||||
|
||||
// If the sibling matches our selector, use it
|
||||
// If not, jump to the next sibling and continue the loop
|
||||
while (sibling) {
|
||||
if (sibling.matches(selector)) return sibling
|
||||
sibling = sibling.nextElementSibling
|
||||
}
|
||||
}
|
||||
|
||||
function createCollapsibles(node) {
|
||||
if (!node) {
|
||||
node = document
|
||||
}
|
||||
|
||||
let collapsibles = node.querySelectorAll(".collapsible")
|
||||
collapsibles.forEach(function(c) {
|
||||
let handle = document.createElement('span')
|
||||
handle.className = 'collapsible-handle'
|
||||
|
||||
if (c.className.indexOf('active') !== -1) {
|
||||
handle.innerHTML = '➖' // minus
|
||||
} else {
|
||||
handle.innerHTML = '➕' // plus
|
||||
}
|
||||
c.insertBefore(handle, c.firstChild)
|
||||
|
||||
c.addEventListener('click', function() {
|
||||
this.classList.toggle("active")
|
||||
let content = getNextSibling(this, '.collapsible-content')
|
||||
if (content.style.display === "block") {
|
||||
content.style.display = "none"
|
||||
handle.innerHTML = '➕' // plus
|
||||
} else {
|
||||
content.style.display = "block"
|
||||
handle.innerHTML = '➖' // minus
|
||||
}
|
||||
|
||||
if (this == advancedPanelHandle) {
|
||||
let state = (content.style.display === 'block' ? 'true' : 'false')
|
||||
localStorage.setItem(ADVANCED_PANEL_OPEN_KEY, state)
|
||||
} else if (this == modifiersPanelHandle) {
|
||||
let state = (content.style.display === 'block' ? 'true' : 'false')
|
||||
localStorage.setItem(MODIFIERS_PANEL_OPEN_KEY, state)
|
||||
} else if (this == negativePromptPanelHandle) {
|
||||
let state = (content.style.display === 'block' ? 'true' : 'false')
|
||||
localStorage.setItem(NEGATIVE_PROMPT_PANEL_OPEN_KEY, state)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function permute(arr) {
|
||||
let permutations = []
|
||||
let n = arr.length
|
||||
let n_permutations = Math.pow(2, n)
|
||||
for (let i = 0; i < n_permutations; i++) {
|
||||
let perm = []
|
||||
let mask = Number(i).toString(2).padStart(n, '0')
|
||||
|
||||
for (let idx = 0; idx < mask.length; idx++) {
|
||||
if (mask[idx] === '1' && arr[idx].trim() !== '') {
|
||||
perm.push(arr[idx])
|
||||
}
|
||||
}
|
||||
|
||||
if (perm.length > 0) {
|
||||
permutations.push(perm)
|
||||
}
|
||||
}
|
||||
|
||||
return permutations
|
||||
}
|
||||
|
||||
// https://stackoverflow.com/a/8212878
|
||||
function millisecondsToStr(milliseconds) {
|
||||
function numberEnding (number) {
|
||||
return (number > 1) ? 's' : ''
|
||||
}
|
||||
|
||||
var temp = Math.floor(milliseconds / 1000)
|
||||
var hours = Math.floor((temp %= 86400) / 3600)
|
||||
var s = ''
|
||||
if (hours) {
|
||||
s += hours + ' hour' + numberEnding(hours) + ' '
|
||||
}
|
||||
var minutes = Math.floor((temp %= 3600) / 60)
|
||||
if (minutes) {
|
||||
s += minutes + ' minute' + numberEnding(minutes) + ' '
|
||||
}
|
||||
var seconds = temp % 60
|
||||
if (!hours && minutes < 4 && seconds) {
|
||||
s += seconds + ' second' + numberEnding(seconds)
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
@ -478,14 +478,18 @@ def do_mk_img(req: Request):
|
||||
thread_data.modelFS.to(thread_data.device)
|
||||
|
||||
partial_x_samples = None
|
||||
last_callback_time = -1
|
||||
def img_callback(x_samples, i):
|
||||
nonlocal partial_x_samples
|
||||
nonlocal partial_x_samples, last_callback_time
|
||||
|
||||
partial_x_samples = x_samples
|
||||
|
||||
if req.stream_progress_updates:
|
||||
n_steps = req.num_inference_steps if req.init_image is None else t_enc
|
||||
progress = {"step": i, "total_steps": n_steps}
|
||||
step_time = time.time() - last_callback_time if last_callback_time != -1 else -1
|
||||
last_callback_time = time.time()
|
||||
|
||||
progress = {"step": i, "total_steps": n_steps, "step_time": step_time}
|
||||
|
||||
if req.stream_image_progress and i % 5 == 0:
|
||||
partial_images = []
|
||||
|
Loading…
Reference in New Issue
Block a user