mirror of
https://github.com/easydiffusion/easydiffusion.git
synced 2025-06-24 03:41:24 +02:00
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');"
|
@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
|
@>nul grep -c "sd_git_cloned" scripts\install_status.txt
|
||||||
@if "%ERRORLEVEL%" EQU "0" (
|
@if "%ERRORLEVEL%" EQU "0" (
|
||||||
@echo "Stable Diffusion's git repository was already installed. Updating.."
|
@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
|
@REM prevent conda from using packages from the user's home directory, to avoid conflicts
|
||||||
@set PYTHONNOUSERSITE=1
|
@set PYTHONNOUSERSITE=1
|
||||||
|
|
||||||
|
set USERPROFILE=%cd%\profile
|
||||||
set TMP=%cd%\tmp
|
set TMP=%cd%\tmp
|
||||||
set TEMP=%cd%\tmp
|
set TEMP=%cd%\tmp
|
||||||
|
|
||||||
@ -95,6 +100,7 @@ set PATH=C:\Windows\System32;%PATH%
|
|||||||
|
|
||||||
@set PYTHONNOUSERSITE=1
|
@set PYTHONNOUSERSITE=1
|
||||||
|
|
||||||
|
set USERPROFILE=%cd%\profile
|
||||||
set TMP=%cd%\tmp
|
set TMP=%cd%\tmp
|
||||||
set TEMP=%cd%\tmp
|
set TEMP=%cd%\tmp
|
||||||
|
|
||||||
@ -127,6 +133,7 @@ set PATH=C:\Windows\System32;%PATH%
|
|||||||
|
|
||||||
@set PYTHONNOUSERSITE=1
|
@set PYTHONNOUSERSITE=1
|
||||||
|
|
||||||
|
set USERPROFILE=%cd%\profile
|
||||||
set TMP=%cd%\tmp
|
set TMP=%cd%\tmp
|
||||||
set TEMP=%cd%\tmp
|
set TEMP=%cd%\tmp
|
||||||
|
|
||||||
@ -153,6 +160,7 @@ set PATH=C:\Windows\System32;%PATH%
|
|||||||
|
|
||||||
@set PYTHONNOUSERSITE=1
|
@set PYTHONNOUSERSITE=1
|
||||||
|
|
||||||
|
set USERPROFILE=%cd%\profile
|
||||||
set TMP=%cd%\tmp
|
set TMP=%cd%\tmp
|
||||||
set TEMP=%cd%\tmp
|
set TEMP=%cd%\tmp
|
||||||
|
|
||||||
|
@ -2,21 +2,22 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<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/images/favicon-16x16.png" sizes="16x16">
|
||||||
<link rel="icon" type="image/png" href="/media/favicon-32x32.png" sizes="32x32">
|
<link rel="icon" type="image/png" href="/media/images/favicon-32x32.png" sizes="32x32">
|
||||||
<link rel="stylesheet" href="/media/main.css?v=25">
|
<link rel="stylesheet" href="/media/css/fonts.css?v=1">
|
||||||
<link rel="stylesheet" href="/media/modifier-thumbnails.css?v=1">
|
<link rel="stylesheet" href="/media/css/themes.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/css/main.css?v=1">
|
||||||
<link rel="stylesheet" href="/media/drawingboard.min.css">
|
<link rel="stylesheet" href="/media/css/modifier-thumbnails.css?v=1">
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Work+Sans:wght@400;600;700;800&display=swap" rel="stylesheet">
|
<link rel="stylesheet" href="/media/css/fontawesome-all.min.css?v=1">
|
||||||
<script src="/media/jquery-3.6.1.min.js"></script>
|
<link rel="stylesheet" href="/media/css/drawingboard.min.css">
|
||||||
<script src="/media/drawingboard.min.js"></script>
|
<script src="/media/js/jquery-3.6.1.min.js"></script>
|
||||||
|
<script src="/media/js/drawingboard.min.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="container">
|
<div id="container">
|
||||||
<div id="top-nav">
|
<div id="top-nav">
|
||||||
<div id="logo">
|
<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>
|
</div>
|
||||||
<ul id="top-nav-items">
|
<ul id="top-nav-items">
|
||||||
<li class="dropdown">
|
<li class="dropdown">
|
||||||
@ -239,7 +240,7 @@
|
|||||||
<div class="line-separator"> </div>
|
<div class="line-separator"> </div>
|
||||||
|
|
||||||
<div id="footer" class="panel-box">
|
<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>
|
<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">
|
<div id="footer-legal">
|
||||||
<p><b>Disclaimer:</b> The authors of this project are not responsible for any content generated using this interface.</p>
|
<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>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
<script src="media/auto-save.js?v=2"></script>
|
<script src="media/js/utils.js?v=1"></script>
|
||||||
<script src="media/main.js?v=37"></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>
|
<script>
|
||||||
async function init() {
|
async function init() {
|
||||||
await loadModifiers()
|
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;
|
font-family: Work Sans, Verdana, Geneva, sans-serif;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
@ -164,7 +16,7 @@ a:visited {
|
|||||||
color: rgb(0, 102, 204);
|
color: rgb(0, 102, 204);
|
||||||
}
|
}
|
||||||
label {
|
label {
|
||||||
font-size: 9pt;
|
font-size: 10pt;
|
||||||
}
|
}
|
||||||
#prompt {
|
#prompt {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -252,7 +104,7 @@ label {
|
|||||||
margin-bottom: 7px;
|
margin-bottom: 7px;
|
||||||
}
|
}
|
||||||
#container {
|
#container {
|
||||||
width: 90%;
|
width: 95%;
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
}
|
}
|
||||||
@ -681,24 +533,6 @@ input::file-selector-button {
|
|||||||
height: 19px;
|
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) {
|
@media screen and (max-width: 700px) {
|
||||||
body {
|
body {
|
||||||
margin: 0px;
|
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 {
|
#promptsFromFileBtn {
|
||||||
font-size: 9pt;
|
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 AUTO_SAVE_SETTINGS_KEY = "autoSaveSettings"
|
||||||
const HEALTH_PING_INTERVAL = 5 // seconds
|
const HEALTH_PING_INTERVAL = 5 // seconds
|
||||||
const MAX_INIT_IMAGE_DIMENSION = 768
|
const MAX_INIT_IMAGE_DIMENSION = 768
|
||||||
const INPAINTING_EDITOR_SIZE = 450
|
|
||||||
|
|
||||||
const IMAGE_REGEX = new RegExp('data:image/[A-Za-z]+;base64')
|
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 maskSetting = document.querySelector('#enable_mask')
|
||||||
let negativePromptPanelHandle = document.querySelector('#negative_prompt_handle')
|
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 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')
|
// 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 advancedPanelHandle = document.querySelector("#editor-settings .collapsible")
|
||||||
let modifiersPanelHandle = document.querySelector("#editor-modifiers .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-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>'
|
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'
|
maskResetButton.style.fontSize = '10pt'
|
||||||
|
|
||||||
let serverState = {'status': 'Offline', 'time': Date.now()}
|
let serverState = {'status': 'Offline', 'time': Date.now()}
|
||||||
let activeTags = []
|
|
||||||
let modifiers = []
|
|
||||||
let lastPromptUsed = ''
|
let lastPromptUsed = ''
|
||||||
let bellPending = false
|
let bellPending = false
|
||||||
|
|
||||||
let taskQueue = []
|
let taskQueue = []
|
||||||
let currentTask = null
|
let currentTask = null
|
||||||
|
|
||||||
const modifierThumbnailPath = 'media/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) {
|
||||||
@ -336,40 +312,6 @@ async function healthCheck() {
|
|||||||
setServerStatus('error', 'offline')
|
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) {
|
function showImages(reqBody, res, outputContainer, livePreview) {
|
||||||
let imageItemElements = outputContainer.querySelectorAll('.imgItem')
|
let imageItemElements = outputContainer.querySelectorAll('.imgItem')
|
||||||
@ -464,9 +406,9 @@ function getUseAsInputHandler(imageItemElem) {
|
|||||||
|
|
||||||
// maskSetting.style.display = 'block'
|
// maskSetting.style.display = 'block'
|
||||||
|
|
||||||
randomSeedField.checked = false
|
// randomSeedField.checked = false
|
||||||
seedField.value = imageSeed
|
// seedField.value = imageSeed
|
||||||
seedField.disabled = false
|
// seedField.disabled = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -609,7 +551,6 @@ async function doMakeImage(task) {
|
|||||||
let reader = res.body.getReader()
|
let reader = res.body.getReader()
|
||||||
let textDecoder = new TextDecoder()
|
let textDecoder = new TextDecoder()
|
||||||
let finalJSON = ''
|
let finalJSON = ''
|
||||||
let prevTime = -1
|
|
||||||
let readComplete = false
|
let readComplete = false
|
||||||
while (!readComplete || finalJSON.length > 0) {
|
while (!readComplete || finalJSON.length > 0) {
|
||||||
let t = Date.now()
|
let t = Date.now()
|
||||||
@ -664,11 +605,11 @@ async function doMakeImage(task) {
|
|||||||
let percent = 100 * (overallStepCount / totalSteps)
|
let percent = 100 * (overallStepCount / totalSteps)
|
||||||
percent = (percent > 100 ? 100 : percent)
|
percent = (percent > 100 ? 100 : percent)
|
||||||
percent = percent.toFixed(0)
|
percent = percent.toFixed(0)
|
||||||
let timeTaken = (prevTime === -1 ? -1 : t - prevTime)
|
let timeTaken = stepUpdate.step_time // sec
|
||||||
|
|
||||||
let stepsRemaining = totalSteps - overallStepCount
|
let stepsRemaining = totalSteps - overallStepCount
|
||||||
stepsRemaining = (stepsRemaining < 0 ? 0 : stepsRemaining)
|
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 = `Batch ${task.batchesDone+1} of ${batchCount}`
|
||||||
outputMsg.innerHTML += `. Generating image(s): ${percent}%`
|
outputMsg.innerHTML += `. Generating image(s): ${percent}%`
|
||||||
@ -698,7 +639,6 @@ async function doMakeImage(task) {
|
|||||||
console.log('Stream stopped: ', res)
|
console.log('Stream stopped: ', res)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
prevTime = t
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof stepUpdate === 'object' && stepUpdate.status !== 'succeeded') {
|
if (typeof stepUpdate === 'object' && stepUpdate.status !== 'succeeded') {
|
||||||
@ -986,12 +926,19 @@ function createTask(task) {
|
|||||||
imagePreview.insertBefore(taskEntry, previewTools.nextSibling)
|
imagePreview.insertBefore(taskEntry, previewTools.nextSibling)
|
||||||
|
|
||||||
task.previewPrompt.innerText = task.reqBody.prompt
|
task.previewPrompt.innerText = task.reqBody.prompt
|
||||||
|
if (task.previewPrompt.innerText.trim() === '') {
|
||||||
|
task.previewPrompt.innerHTML = ' ' // allows the results to be collapsed
|
||||||
|
}
|
||||||
|
|
||||||
taskQueue.unshift(task)
|
taskQueue.unshift(task)
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPrompts() {
|
function getPrompts() {
|
||||||
let prompts = promptField.value
|
let prompts = promptField.value
|
||||||
|
if (prompts.trim() === '') {
|
||||||
|
return ['']
|
||||||
|
}
|
||||||
|
|
||||||
prompts = prompts.split('\n')
|
prompts = prompts.split('\n')
|
||||||
|
|
||||||
let promptsToMake = []
|
let promptsToMake = []
|
||||||
@ -1041,28 +988,6 @@ function permutePrompts(promptBase, promptMatrix) {
|
|||||||
return prompts
|
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
|
// create a file name with embedded prompt and metadata
|
||||||
// for easier cateloging and comparison
|
// for easier cateloging and comparison
|
||||||
function createFileName(prompt, seed, steps, guidance, outputFormat) {
|
function createFileName(prompt, seed, steps, guidance, outputFormat) {
|
||||||
@ -1165,8 +1090,18 @@ outputFormatField.addEventListener('change', handleStringSettingChange(OUTPUT_FO
|
|||||||
outputFormatField.value = getOutputFormat()
|
outputFormatField.value = getOutputFormat()
|
||||||
|
|
||||||
diskPathField.addEventListener('change', handleStringSettingChange(DISK_PATH_KEY))
|
diskPathField.addEventListener('change', handleStringSettingChange(DISK_PATH_KEY))
|
||||||
widthField.addEventListener('change', resizeInpaintingEditor)
|
widthField.addEventListener('change', onDimensionChange)
|
||||||
heightField.addEventListener('change', resizeInpaintingEditor)
|
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) {
|
saveToDiskField.addEventListener('click', function(e) {
|
||||||
diskPathField.disabled = !this.checked
|
diskPathField.disabled = !this.checked
|
||||||
@ -1375,7 +1310,7 @@ initImageClearBtn.addEventListener('click', function() {
|
|||||||
|
|
||||||
maskSetting.addEventListener('click', function() {
|
maskSetting.addEventListener('click', function() {
|
||||||
inpaintingEditorContainer.style.display = (this.checked ? 'block' : 'none')
|
inpaintingEditorContainer.style.display = (this.checked ? 'block' : 'none')
|
||||||
resizeInpaintingEditor()
|
onDimensionChange()
|
||||||
})
|
})
|
||||||
|
|
||||||
promptsFromFileBtn.addEventListener('click', function() {
|
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() {
|
async function getDiskPath() {
|
||||||
try {
|
try {
|
||||||
let diskPath = getSavedDiskPath()
|
let diskPath = getSavedDiskPath()
|
||||||
@ -1564,246 +1355,4 @@ async function getDiskPath() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function createModifierCard(name, previews) {
|
createCollapsibles()
|
||||||
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);
|
|
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)
|
thread_data.modelFS.to(thread_data.device)
|
||||||
|
|
||||||
partial_x_samples = None
|
partial_x_samples = None
|
||||||
|
last_callback_time = -1
|
||||||
def img_callback(x_samples, i):
|
def img_callback(x_samples, i):
|
||||||
nonlocal partial_x_samples
|
nonlocal partial_x_samples, last_callback_time
|
||||||
|
|
||||||
partial_x_samples = x_samples
|
partial_x_samples = x_samples
|
||||||
|
|
||||||
if req.stream_progress_updates:
|
if req.stream_progress_updates:
|
||||||
n_steps = req.num_inference_steps if req.init_image is None else t_enc
|
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:
|
if req.stream_image_progress and i % 5 == 0:
|
||||||
partial_images = []
|
partial_images = []
|
||||||
|
Loading…
x
Reference in New Issue
Block a user