mirror of
https://github.com/easydiffusion/easydiffusion.git
synced 2025-06-21 18:31:28 +02:00
commit
6799b3d7da
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
## v2.4
|
## v2.4
|
||||||
### Major Changes
|
### Major Changes
|
||||||
|
- **Automatic scanning for malicious model files** - using `picklescan`. Thanks @JeLuf
|
||||||
- **Support for custom VAE models**. You can place your VAE files in the `models/vae` folder, and refresh the browser page to use them. More info: https://github.com/cmdr2/stable-diffusion-ui/wiki/VAE-Variational-Auto-Encoder
|
- **Support for custom VAE models**. You can place your VAE files in the `models/vae` folder, and refresh the browser page to use them. More info: https://github.com/cmdr2/stable-diffusion-ui/wiki/VAE-Variational-Auto-Encoder
|
||||||
- **Experimental support for multiple GPUs!** It should work automatically. Just open one browser tab per GPU, and spread your tasks across your GPUs. For e.g. open our UI in two browser tabs if you have two GPUs. You can customize which GPUs it should use in the "Settings" tab, otherwise let it automatically pick the best GPUs. Thanks @madrang . More info: https://github.com/cmdr2/stable-diffusion-ui/wiki/Run-on-Multiple-GPUs
|
- **Experimental support for multiple GPUs!** It should work automatically. Just open one browser tab per GPU, and spread your tasks across your GPUs. For e.g. open our UI in two browser tabs if you have two GPUs. You can customize which GPUs it should use in the "Settings" tab, otherwise let it automatically pick the best GPUs. Thanks @madrang . More info: https://github.com/cmdr2/stable-diffusion-ui/wiki/Run-on-Multiple-GPUs
|
||||||
- **Cleaner UI design** - Show settings and help in new tabs, instead of dropdown popups (which were buggy). Thanks @mdiller
|
- **Cleaner UI design** - Show settings and help in new tabs, instead of dropdown popups (which were buggy). Thanks @mdiller
|
||||||
@ -20,6 +21,12 @@
|
|||||||
- A `What's New?` tab in the UI
|
- A `What's New?` tab in the UI
|
||||||
|
|
||||||
### Detailed changelog
|
### Detailed changelog
|
||||||
|
* 2.4.11 - 19 Nov 2022 - Address a regression in how long images take to generate. Use the previous code for moving a model to CPU. This improves things by a second or two per image, but we still have a regression (investigating).
|
||||||
|
* 2.4.10 - 18 Nov 2022 - Textarea for negative prompts. Thanks @JeLuf
|
||||||
|
* 2.4.10 - 18 Nov 2022 - Improved design for Settings, and rounded toggle buttons instead of checkboxes for a more modern look. Thanks @mdiller
|
||||||
|
* 2.4.9 - 18 Nov 2022 - Add Picklescan - a scanner for malicious model files. If it finds a malicious file, it will halt the web application and alert the user. Thanks @JeLuf
|
||||||
|
* 2.4.8 - 18 Nov 2022 - A `Use these settings` button to use the settings from a previously generated image task. Thanks @patriceac
|
||||||
|
* 2.4.7 - 18 Nov 2022 - Don't crash if a VAE file fails to load
|
||||||
* 2.4.7 - 17 Nov 2022 - Fix a bug where Face Correction (GFPGAN) would fail on cuda:N (i.e. GPUs other than cuda:0), as well as fail on CPU if the system had an incompatible GPU.
|
* 2.4.7 - 17 Nov 2022 - Fix a bug where Face Correction (GFPGAN) would fail on cuda:N (i.e. GPUs other than cuda:0), as well as fail on CPU if the system had an incompatible GPU.
|
||||||
* 2.4.6 - 16 Nov 2022 - Fix a regression in VRAM usage during startup, which caused 'Out of Memory' errors when starting on GPUs with 4gb (or less) VRAM
|
* 2.4.6 - 16 Nov 2022 - Fix a regression in VRAM usage during startup, which caused 'Out of Memory' errors when starting on GPUs with 4gb (or less) VRAM
|
||||||
* 2.4.5 - 16 Nov 2022 - Add checkbox for "Open browser on startup".
|
* 2.4.5 - 16 Nov 2022 - Add checkbox for "Open browser on startup".
|
||||||
|
@ -191,6 +191,16 @@ call WHERE uvicorn > .tmp
|
|||||||
exit /b
|
exit /b
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@>nul 2>nul call python -m picklescan --help
|
||||||
|
@if "%ERRORLEVEL%" NEQ "0" (
|
||||||
|
@echo. & echo Picklescan not found. Installing
|
||||||
|
@call pip install picklescan || (
|
||||||
|
echo "Error installing the picklescan package necessary for Stable Diffusion UI. Sorry about that, please try to:" & echo " 1. Run this installer again." & echo " 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/wiki/Troubleshooting" & echo " 3. If those steps don't help, please copy *all* the error messages in this window, and ask the community at https://discord.com/invite/u9yhsFmEkB" & echo " 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues" & echo "Thanks!"
|
||||||
|
pause
|
||||||
|
exit /b
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
@>nul findstr /m "conda_sd_ui_deps_installed" ..\scripts\install_status.txt
|
@>nul findstr /m "conda_sd_ui_deps_installed" ..\scripts\install_status.txt
|
||||||
@if "%ERRORLEVEL%" NEQ "0" (
|
@if "%ERRORLEVEL%" NEQ "0" (
|
||||||
@echo conda_sd_ui_deps_installed >> ..\scripts\install_status.txt
|
@echo conda_sd_ui_deps_installed >> ..\scripts\install_status.txt
|
||||||
@ -275,7 +285,7 @@ echo. > "..\models\vae\Put your VAE files here.txt"
|
|||||||
for %%I in ("RealESRGAN_x4plus.pth") do if "%%~zI" EQU "67040989" (
|
for %%I in ("RealESRGAN_x4plus.pth") do if "%%~zI" EQU "67040989" (
|
||||||
echo "Data files (weights) necessary for ESRGAN (Resolution Upscaling) x4plus were already downloaded"
|
echo "Data files (weights) necessary for ESRGAN (Resolution Upscaling) x4plus were already downloaded"
|
||||||
) else (
|
) else (
|
||||||
echo. & echo "The GFPGAN model file present at %cd%\RealESRGAN_x4plus.pth is invalid. It is only %%~zI bytes in size. Re-downloading.." & echo.
|
echo. & echo "The RealESRGAN model file present at %cd%\RealESRGAN_x4plus.pth is invalid. It is only %%~zI bytes in size. Re-downloading.." & echo.
|
||||||
del "RealESRGAN_x4plus.pth"
|
del "RealESRGAN_x4plus.pth"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -305,7 +315,7 @@ echo. > "..\models\vae\Put your VAE files here.txt"
|
|||||||
for %%I in ("RealESRGAN_x4plus_anime_6B.pth") do if "%%~zI" EQU "17938799" (
|
for %%I in ("RealESRGAN_x4plus_anime_6B.pth") do if "%%~zI" EQU "17938799" (
|
||||||
echo "Data files (weights) necessary for ESRGAN (Resolution Upscaling) x4plus_anime were already downloaded"
|
echo "Data files (weights) necessary for ESRGAN (Resolution Upscaling) x4plus_anime were already downloaded"
|
||||||
) else (
|
) else (
|
||||||
echo. & echo "The GFPGAN model file present at %cd%\RealESRGAN_x4plus_anime_6B.pth is invalid. It is only %%~zI bytes in size. Re-downloading.." & echo.
|
echo. & echo "The RealESRGAN model file present at %cd%\RealESRGAN_x4plus_anime_6B.pth is invalid. It is only %%~zI bytes in size. Re-downloading.." & echo.
|
||||||
del "RealESRGAN_x4plus_anime_6B.pth"
|
del "RealESRGAN_x4plus_anime_6B.pth"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -156,6 +156,13 @@ else
|
|||||||
echo conda_sd_ui_deps_installed >> ../scripts/install_status.txt
|
echo conda_sd_ui_deps_installed >> ../scripts/install_status.txt
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if python -m picklescan --help >/dev/null 2>&1; then
|
||||||
|
echo "Picklescan is already installed."
|
||||||
|
else
|
||||||
|
echo "Picklescan not found, installing."
|
||||||
|
pip install picklescan || fail "Picklescan installation failed."
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
mkdir -p "../models/stable-diffusion"
|
mkdir -p "../models/stable-diffusion"
|
||||||
|
@ -5,12 +5,12 @@
|
|||||||
<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/images/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/images/favicon-32x32.png" sizes="32x32">
|
<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/fonts.css">
|
||||||
<link rel="stylesheet" href="/media/css/themes.css?v=3">
|
<link rel="stylesheet" href="/media/css/themes.css">
|
||||||
<link rel="stylesheet" href="/media/css/main.css?v=19">
|
<link rel="stylesheet" href="/media/css/main.css">
|
||||||
<link rel="stylesheet" href="/media/css/auto-save.css?v=5">
|
<link rel="stylesheet" href="/media/css/auto-save.css">
|
||||||
<link rel="stylesheet" href="/media/css/modifier-thumbnails.css?v=4">
|
<link rel="stylesheet" href="/media/css/modifier-thumbnails.css">
|
||||||
<link rel="stylesheet" href="/media/css/fontawesome-all.min.css?v=1">
|
<link rel="stylesheet" href="/media/css/fontawesome-all.min.css">
|
||||||
<link rel="stylesheet" href="/media/css/drawingboard.min.css">
|
<link rel="stylesheet" href="/media/css/drawingboard.min.css">
|
||||||
<script src="/media/js/jquery-3.6.1.min.js"></script>
|
<script src="/media/js/jquery-3.6.1.min.js"></script>
|
||||||
<script src="/media/js/drawingboard.min.js"></script>
|
<script src="/media/js/drawingboard.min.js"></script>
|
||||||
@ -20,7 +20,7 @@
|
|||||||
<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.4.7 <span id="updateBranchLabel"></span></small></h1>
|
<h1>Stable Diffusion UI <small>v2.4.11 <span id="updateBranchLabel"></span></small></h1>
|
||||||
</div>
|
</div>
|
||||||
<div id="server-status">
|
<div id="server-status">
|
||||||
<div id="server-status-color">●</div>
|
<div id="server-status-color">●</div>
|
||||||
@ -47,14 +47,13 @@
|
|||||||
<label for="prompt"><b>Enter Prompt</b></label> <small>or</small> <button id="promptsFromFileBtn">Load from a file</button>
|
<label for="prompt"><b>Enter Prompt</b></label> <small>or</small> <button id="promptsFromFileBtn">Load from a file</button>
|
||||||
<textarea id="prompt" class="col-free">a photograph of an astronaut riding a horse</textarea>
|
<textarea id="prompt" class="col-free">a photograph of an astronaut riding a horse</textarea>
|
||||||
<input id="prompt_from_file" name="prompt_from_file" type="file" /> <!-- hidden -->
|
<input id="prompt_from_file" name="prompt_from_file" type="file" /> <!-- hidden -->
|
||||||
|
|
||||||
<label for="negative_prompt" class="collapsible" id="negative_prompt_handle">
|
<label for="negative_prompt" class="collapsible" id="negative_prompt_handle">
|
||||||
Negative Prompt
|
Negative Prompt
|
||||||
<a href="https://github.com/cmdr2/stable-diffusion-ui/wiki/Writing-prompts#negative-prompts" target="_blank"><i class="fa-solid fa-circle-question help-btn"><span class="simple-tooltip right">Click to learn more about Negative Prompts</span></i></a>
|
<a href="https://github.com/cmdr2/stable-diffusion-ui/wiki/Writing-prompts#negative-prompts" target="_blank"><i class="fa-solid fa-circle-question help-btn"><span class="simple-tooltip right">Click to learn more about Negative Prompts</span></i></a>
|
||||||
<small>(optional)</small>
|
<small>(optional)</small>
|
||||||
</label>
|
</label>
|
||||||
<div class="collapsible-content">
|
<div class="collapsible-content">
|
||||||
<input id="negative_prompt" name="negative_prompt" placeholder="list the things to remove from the image (e.g. fog, green)">
|
<textarea id="negative_prompt" name="negative_prompt" placeholder="list the things to remove from the image (e.g. fog, green)"></textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -84,7 +83,7 @@
|
|||||||
<div id="editor-inputs-tags-list"></div>
|
<div id="editor-inputs-tags-list"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button id="makeImage">Make Image</button>
|
<button id="makeImage" class="primaryButton">Make Image</button>
|
||||||
<button id="stopImage" class="secondaryButton">Stop All</button>
|
<button id="stopImage" class="secondaryButton">Stop All</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -94,7 +93,7 @@
|
|||||||
<h4 class="collapsible">
|
<h4 class="collapsible">
|
||||||
Image Settings
|
Image Settings
|
||||||
<i id="reset-image-settings" class="fa-solid fa-arrow-rotate-left section-button">
|
<i id="reset-image-settings" class="fa-solid fa-arrow-rotate-left section-button">
|
||||||
<span class="simple-tooltip left">
|
<span class="simple-tooltip right">
|
||||||
Reset Image Settings
|
Reset Image Settings
|
||||||
</span>
|
</span>
|
||||||
</i>
|
</i>
|
||||||
@ -242,7 +241,7 @@
|
|||||||
<div id="tab-content-settings" class="tab-content">
|
<div id="tab-content-settings" class="tab-content">
|
||||||
<div id="system-settings" class="tab-content-inner">
|
<div id="system-settings" class="tab-content-inner">
|
||||||
<h1>System Settings</h1>
|
<h1>System Settings</h1>
|
||||||
<table class="form-table"></table>
|
<div class="parameters-table"></div>
|
||||||
<br/>
|
<br/>
|
||||||
<button id="save-system-settings-btn" class="primaryButton">Save</button>
|
<button id="save-system-settings-btn" class="primaryButton">Save</button>
|
||||||
<br/><br/>
|
<br/><br/>
|
||||||
@ -329,15 +328,15 @@
|
|||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
<script src="media/js/utils.js?v=6"></script>
|
<script src="media/js/utils.js"></script>
|
||||||
<script src="media/js/parameters.js?v=10"></script>
|
<script src="media/js/parameters.js"></script>
|
||||||
<script src="media/js/plugins.js?v=1"></script>
|
<script src="media/js/plugins.js"></script>
|
||||||
<script src="media/js/inpainting-editor.js?v=1"></script>
|
<script src="media/js/inpainting-editor.js"></script>
|
||||||
<script src="media/js/image-modifiers.js?v=6"></script>
|
<script src="media/js/image-modifiers.js"></script>
|
||||||
<script src="media/js/auto-save.js?v=8"></script>
|
<script src="media/js/auto-save.js"></script>
|
||||||
<script src="media/js/main.js?v=23"></script>
|
<script src="media/js/main.js"></script>
|
||||||
<script src="media/js/themes.js?v=4"></script>
|
<script src="media/js/themes.js"></script>
|
||||||
<script src="media/js/dnd.js?v=10"></script>
|
<script src="media/js/dnd.js"></script>
|
||||||
<script>
|
<script>
|
||||||
async function init() {
|
async function init() {
|
||||||
await initSettings()
|
await initSettings()
|
||||||
|
@ -26,23 +26,56 @@
|
|||||||
float: left;
|
float: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-table small {
|
|
||||||
|
.parameters-table {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.parameters-table > div {
|
||||||
|
background: var(--background-color2);
|
||||||
|
display: flex;
|
||||||
|
padding: 0px 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.parameters-table > div > div {
|
||||||
|
padding: 10px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.parameters-table small {
|
||||||
color: rgb(153, 153, 153);
|
color: rgb(153, 153, 153);
|
||||||
}
|
}
|
||||||
|
|
||||||
#system-settings .form-table td {
|
.parameters-table > div > div:nth-child(1) {
|
||||||
height: 24px;
|
font-size: 20px;
|
||||||
|
width: 45px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#system-settings .form-table td:last-child div {
|
.parameters-table > div > div:nth-child(2) {
|
||||||
display: flex;
|
flex: 1;
|
||||||
align-items: center;
|
flex-direction: column;
|
||||||
}
|
|
||||||
#system-settings .form-table td:last-child div > :not([type="checkbox"]):first-child {
|
|
||||||
margin-left: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#system-settings .form-table td:last-child div small {
|
|
||||||
padding-left: 5px;
|
|
||||||
text-align: left;
|
text-align: left;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: start;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.parameters-table > div > div:nth-child(3) {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.parameters-table > div:first-child {
|
||||||
|
border-radius: 12px 12px 0px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.parameters-table > div:last-child {
|
||||||
|
border-radius: 0px 0px 12px 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.parameters-table .fa-fire {
|
||||||
|
color: #F7630C;
|
||||||
}
|
}
|
@ -30,10 +30,19 @@ code {
|
|||||||
#prompt {
|
#prompt {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 65pt;
|
height: 65pt;
|
||||||
font-size: 13px;
|
font-size: 14px;
|
||||||
margin-bottom: 6px;
|
margin-bottom: 6px;
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
display: block;
|
display: block;
|
||||||
|
border: 2px solid var(--background-color2);
|
||||||
|
}
|
||||||
|
#negative_prompt {
|
||||||
|
width: 100%;
|
||||||
|
height: 50pt;
|
||||||
|
font-size: 13px;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
margin-top: 5px;
|
||||||
|
display: block;
|
||||||
}
|
}
|
||||||
.image_preview_container {
|
.image_preview_container {
|
||||||
margin-top: 10pt;
|
margin-top: 10pt;
|
||||||
@ -216,7 +225,6 @@ code {
|
|||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
#editor-modifiers {
|
#editor-modifiers {
|
||||||
max-width: 600px;
|
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
@ -442,6 +450,17 @@ img {
|
|||||||
.secondaryButton:hover {
|
.secondaryButton:hover {
|
||||||
background: rgb(177, 27, 0);
|
background: rgb(177, 27, 0);
|
||||||
}
|
}
|
||||||
|
.useSettings {
|
||||||
|
background: var(--accent-color);
|
||||||
|
border: 1px solid var(--accent-color);
|
||||||
|
color: rgb(255, 221, 255);
|
||||||
|
padding: 3pt 6pt;
|
||||||
|
margin-right: 6pt;
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
.useSettings:hover {
|
||||||
|
background: hsl(var(--accent-hue), 100%, calc(var(--accent-lightness) + 6%));
|
||||||
|
}
|
||||||
.stopTask {
|
.stopTask {
|
||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
@ -495,6 +514,10 @@ img {
|
|||||||
border-radius: 6px 0px;
|
border-radius: 6px 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#editor-settings {
|
||||||
|
min-width: 500px;
|
||||||
|
}
|
||||||
|
|
||||||
#editor-settings-entries {
|
#editor-settings-entries {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@ -584,6 +607,57 @@ input::file-selector-button {
|
|||||||
height: 19px;
|
height: 19px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.input-toggle {
|
||||||
|
display: inline-block;
|
||||||
|
position: relative;
|
||||||
|
vertical-align: middle;
|
||||||
|
width: calc(var(--input-height) * 2);
|
||||||
|
user-select: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
.input-toggle > input {
|
||||||
|
position: absolute;
|
||||||
|
opacity: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
.input-toggle > label {
|
||||||
|
display: block;
|
||||||
|
overflow: hidden;
|
||||||
|
cursor: pointer;
|
||||||
|
height: var(--input-height);
|
||||||
|
padding: 0;
|
||||||
|
line-height: var(--input-height);
|
||||||
|
border: var(--input-border-size) solid var(--input-border-color);
|
||||||
|
border-radius: var(--input-height);
|
||||||
|
background: var(--input-background-color);
|
||||||
|
transition: background 0.2s ease-in;
|
||||||
|
}
|
||||||
|
.input-toggle > label:before {
|
||||||
|
content: "";
|
||||||
|
display: block;
|
||||||
|
width: calc(var(--input-height) - ((var(--input-border-size) + var(--input-switch-padding)) * 2));
|
||||||
|
margin: 0px;
|
||||||
|
background: var(--input-text-color);
|
||||||
|
position: absolute;
|
||||||
|
top: calc(var(--input-border-size) + var(--input-switch-padding));
|
||||||
|
bottom: calc(var(--input-border-size) + var(--input-switch-padding));
|
||||||
|
right: calc(var(--input-border-size) + var(--input-switch-padding) + var(--input-height));
|
||||||
|
border-radius: calc(var(--input-height) - ((var(--input-border-size) + var(--input-switch-padding)) * 2));
|
||||||
|
transition: all 0.2s ease-in 0s;
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
.input-toggle > input:checked + label {
|
||||||
|
background: var(--accent-color);
|
||||||
|
}
|
||||||
|
.input-toggle > input:checked + label:before {
|
||||||
|
right: calc(var(--input-border-size) + var(--input-switch-padding));
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* MOBILE SUPPORT */
|
/* MOBILE SUPPORT */
|
||||||
@media screen and (max-width: 700px) {
|
@media screen and (max-width: 700px) {
|
||||||
#top-nav {
|
#top-nav {
|
||||||
@ -625,6 +699,9 @@ input::file-selector-button {
|
|||||||
#editor {
|
#editor {
|
||||||
padding: 16px 8px;
|
padding: 16px 8px;
|
||||||
}
|
}
|
||||||
|
#editor-settings {
|
||||||
|
min-width: 0px;
|
||||||
|
}
|
||||||
.tab-content-inner {
|
.tab-content-inner {
|
||||||
margin: 0px;
|
margin: 0px;
|
||||||
}
|
}
|
||||||
@ -648,21 +725,15 @@ input::file-selector-button {
|
|||||||
padding: 0px !important;
|
padding: 0px !important;
|
||||||
margin: 24px !important;
|
margin: 24px !important;
|
||||||
}
|
}
|
||||||
.simple-tooltip.right {
|
.simple-tooltip {
|
||||||
right: initial;
|
display: none;
|
||||||
left: 0px;
|
|
||||||
top: 50%;
|
|
||||||
transform: translate(calc(-100% + 15%), -50%);
|
|
||||||
}
|
|
||||||
:hover > .simple-tooltip.right {
|
|
||||||
transform: translate(100%, -50%);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 700px) {
|
@media (min-width: 700px) {
|
||||||
/* #editor {
|
/* #editor {
|
||||||
max-width: 480px;
|
max-width: 480px;
|
||||||
} */
|
}*/
|
||||||
.float-container {
|
.float-container {
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
}
|
}
|
||||||
@ -918,6 +989,16 @@ i.active {
|
|||||||
float: right;
|
float: right;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
#save-system-settings-btn {
|
button:hover {
|
||||||
|
transition-duration: 0.1s;
|
||||||
|
background: hsl(var(--accent-hue), 100%, calc(var(--accent-lightness) + 6%));
|
||||||
|
}
|
||||||
|
|
||||||
|
button:active {
|
||||||
|
transition-duration: 0.1s;
|
||||||
|
background-color: hsl(var(--accent-hue), 100%, calc(var(--accent-lightness) + 24%));
|
||||||
|
}
|
||||||
|
|
||||||
|
button#save-system-settings-btn {
|
||||||
padding: 4pt 8pt;
|
padding: 4pt 8pt;
|
||||||
}
|
}
|
||||||
|
@ -1,22 +1,26 @@
|
|||||||
:root {
|
:root {
|
||||||
--background-color1: rgb(32, 33, 36); /* main parts of the page */
|
--main-hue: 222;
|
||||||
--background-color2: rgb(44, 45, 48); /* main panels */
|
--main-saturation: 4%;
|
||||||
--background-color3: rgb(47, 49, 53);
|
--value-base: 13%;
|
||||||
--background-color4: rgb(18, 18, 19); /* settings dropdowns */
|
--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) - (0.5 * var(--value-step))));
|
||||||
|
--background-color4: hsl(var(--main-hue), var(--main-saturation), calc(var(--value-base) - (1.5 * var(--value-step))));
|
||||||
|
|
||||||
--accent-hue: 266;
|
--accent-hue: 267;
|
||||||
--accent-lightness: 36%;
|
--accent-lightness: 36%;
|
||||||
--accent-lightness-hover: 40%;
|
--accent-lightness-hover: 40%;
|
||||||
|
|
||||||
--text-color: #eee;
|
--text-color: #eee;
|
||||||
|
|
||||||
--input-text-color: black;
|
--input-text-color: #eee;
|
||||||
--input-background-color: #e9e9ed;
|
--input-background-color: hsl(var(--main-hue), var(--main-saturation), calc(var(--value-base) - (0.7 * var(--value-step))));
|
||||||
--input-border-color: #8f8f9d;
|
--input-border-color: var(--background-color4);
|
||||||
|
|
||||||
--button-text-color: var(--input-text-color);
|
--button-text-color: var(--input-text-color);
|
||||||
--button-color: #e9e9ed;
|
--button-color: var(--accent-color);
|
||||||
--button-border: 1px solid #8f8f9d;
|
--button-border: none;
|
||||||
|
|
||||||
/* other */
|
/* other */
|
||||||
--input-border-radius: 4px;
|
--input-border-radius: 4px;
|
||||||
@ -24,6 +28,8 @@
|
|||||||
--accent-color: hsl(var(--accent-hue), 100%, var(--accent-lightness));
|
--accent-color: hsl(var(--accent-hue), 100%, var(--accent-lightness));
|
||||||
--accent-color-hover: hsl(var(--accent-hue), 100%, var(--accent-lightness-hover));
|
--accent-color-hover: hsl(var(--accent-hue), 100%, var(--accent-lightness-hover));
|
||||||
--primary-button-border: none;
|
--primary-button-border: none;
|
||||||
|
--input-switch-padding: 1px;
|
||||||
|
--input-height: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.theme-light {
|
.theme-light {
|
||||||
@ -33,6 +39,7 @@
|
|||||||
--background-color4: #cccccc;
|
--background-color4: #cccccc;
|
||||||
|
|
||||||
--text-color: black;
|
--text-color: black;
|
||||||
|
--button-text-color: white;
|
||||||
|
|
||||||
--input-text-color: black;
|
--input-text-color: black;
|
||||||
--input-background-color: #f8f9fa;
|
--input-background-color: #f8f9fa;
|
||||||
@ -47,12 +54,7 @@
|
|||||||
|
|
||||||
--accent-hue: 235;
|
--accent-hue: 235;
|
||||||
--accent-lightness: 65%;
|
--accent-lightness: 65%;
|
||||||
--primary-button-border: none;
|
|
||||||
|
|
||||||
--button-color: var(--accent-color);
|
|
||||||
--button-border: none;
|
|
||||||
|
|
||||||
--input-text-color: #ccc;
|
|
||||||
--input-border-size: 2px;
|
--input-border-size: 2px;
|
||||||
--input-background-color: #202225;
|
--input-background-color: #202225;
|
||||||
--input-border-color: var(--input-background-color);
|
--input-border-color: var(--input-background-color);
|
||||||
@ -67,17 +69,10 @@
|
|||||||
--background-color2: hsl(var(--main-hue), var(--main-saturation), calc(var(--value-base) - (1 * var(--value-step))));
|
--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-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))));
|
--background-color4: hsl(var(--main-hue), var(--main-saturation), calc(var(--value-base) - (3 * var(--value-step))));
|
||||||
|
|
||||||
|
--input-background-color: var(--background-color3);
|
||||||
|
|
||||||
--accent-hue: 212;
|
--accent-hue: 212;
|
||||||
--primary-button-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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -90,16 +85,8 @@
|
|||||||
--background-color2: hsl(var(--main-hue), var(--main-saturation), calc(var(--value-base) - (1 * var(--value-step))));
|
--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-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))));
|
--background-color4: hsl(var(--main-hue), var(--main-saturation), calc(var(--value-base) - (3 * var(--value-step))));
|
||||||
|
|
||||||
--primary-button-border: none;
|
|
||||||
|
|
||||||
--button-color: var(--accent-color);
|
|
||||||
--button-border: none;
|
|
||||||
|
|
||||||
--input-border-size: 1px;
|
|
||||||
--input-background-color: var(--background-color3);
|
--input-background-color: var(--background-color3);
|
||||||
--input-text-color: #ccc;
|
|
||||||
--input-border-color: var(--background-color4);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.theme-super-dark {
|
.theme-super-dark {
|
||||||
@ -111,16 +98,9 @@
|
|||||||
--background-color2: hsl(var(--main-hue), var(--main-saturation), calc(var(--value-base) + (1 * var(--value-step))));
|
--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-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) + (1.4 * var(--value-step))));
|
--background-color4: hsl(var(--main-hue), var(--main-saturation), calc(var(--value-base) + (1.4 * var(--value-step))));
|
||||||
|
|
||||||
--primary-button-border: none;
|
|
||||||
|
|
||||||
--button-color: var(--accent-color);
|
|
||||||
--button-border: none;
|
|
||||||
|
|
||||||
--input-border-size: 0px;
|
|
||||||
--input-background-color: var(--background-color3);
|
--input-background-color: var(--background-color3);
|
||||||
--input-text-color: #ccc;
|
--input-border-size: 0px;
|
||||||
--input-border-color: var(--background-color4);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.theme-wild {
|
.theme-wild {
|
||||||
@ -134,13 +114,33 @@
|
|||||||
--background-color4: hsl(var(--main-hue), var(--main-saturation), calc(var(--value-base) - (3 * var(--value-step))));
|
--background-color4: hsl(var(--main-hue), var(--main-saturation), calc(var(--value-base) - (3 * var(--value-step))));
|
||||||
|
|
||||||
--accent-hue: 212;
|
--accent-hue: 212;
|
||||||
--primary-button-border: none;
|
|
||||||
|
|
||||||
--button-color: var(--accent-color);
|
|
||||||
--button-border: none;
|
|
||||||
|
|
||||||
--input-border-size: 1px;
|
--input-border-size: 1px;
|
||||||
--input-background-color: hsl(222, var(--main-saturation), calc(var(--value-base) - (2 * var(--value-step))));
|
--input-background-color: hsl(222, var(--main-saturation), calc(var(--value-base) - (2 * var(--value-step))));
|
||||||
--input-text-color: red;
|
--input-text-color: red;
|
||||||
--input-border-color: green;
|
--input-border-color: green;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.theme-gnomie {
|
||||||
|
--background-color1: #242424;
|
||||||
|
--background-color2: #353535;
|
||||||
|
--background-color3: #494949;
|
||||||
|
--background-color4: #000000;
|
||||||
|
|
||||||
|
--accent-hue: 213;
|
||||||
|
--accent-lightness: 55%;
|
||||||
|
--accent-color: #2168bf;
|
||||||
|
|
||||||
|
--input-border-radius: 6px;
|
||||||
|
--input-text-color: #ffffff;
|
||||||
|
--input-background-color: #2a2a2a;
|
||||||
|
--input-border-size: 0px;
|
||||||
|
--input-border-color: var(--input-background-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-gnomie .panel-box {
|
||||||
|
border: none;
|
||||||
|
box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.25);
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -213,6 +213,7 @@ function fillSaveSettingsConfigTable() {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
prettifyInputs(saveSettingsConfigTable)
|
||||||
}
|
}
|
||||||
|
|
||||||
// configureSettingsSaveBtn
|
// configureSettingsSaveBtn
|
||||||
@ -224,7 +225,7 @@ var autoSaveSettings = document.getElementById("auto_save_settings")
|
|||||||
var configSettingsButton = document.createElement("button")
|
var configSettingsButton = document.createElement("button")
|
||||||
configSettingsButton.textContent = "Configure"
|
configSettingsButton.textContent = "Configure"
|
||||||
configSettingsButton.style.margin = "0px 5px"
|
configSettingsButton.style.margin = "0px 5px"
|
||||||
autoSaveSettings.insertAdjacentElement("afterend", configSettingsButton)
|
autoSaveSettings.insertAdjacentElement("beforebegin", configSettingsButton)
|
||||||
autoSaveSettings.addEventListener("change", () => {
|
autoSaveSettings.addEventListener("change", () => {
|
||||||
configSettingsButton.style.display = autoSaveSettings.checked ? "block" : "none"
|
configSettingsButton.style.display = autoSaveSettings.checked ? "block" : "none"
|
||||||
})
|
})
|
||||||
|
@ -243,7 +243,9 @@ const TASK_MAPPING = {
|
|||||||
parse: (val) => val
|
parse: (val) => val
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function restoreTaskToUI(task) {
|
function restoreTaskToUI(task, fieldsToSkip) {
|
||||||
|
fieldsToSkip = fieldsToSkip || []
|
||||||
|
|
||||||
if ('numOutputsTotal' in task) {
|
if ('numOutputsTotal' in task) {
|
||||||
numOutputsTotalField.value = task.numOutputsTotal
|
numOutputsTotalField.value = task.numOutputsTotal
|
||||||
}
|
}
|
||||||
@ -255,10 +257,47 @@ function restoreTaskToUI(task) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
for (const key in TASK_MAPPING) {
|
for (const key in TASK_MAPPING) {
|
||||||
if (key in task.reqBody) {
|
if (key in task.reqBody && !fieldsToSkip.includes(key)) {
|
||||||
TASK_MAPPING[key].setUI(task.reqBody[key])
|
TASK_MAPPING[key].setUI(task.reqBody[key])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// restore the original tag
|
||||||
|
promptField.value = task.reqBody.original_prompt || task.reqBody.prompt
|
||||||
|
|
||||||
|
// Restore modifiers
|
||||||
|
if (task.reqBody.active_tags) {
|
||||||
|
refreshModifiersState(task.reqBody.active_tags)
|
||||||
|
}
|
||||||
|
|
||||||
|
// properly reset checkboxes
|
||||||
|
if (!('use_face_correction' in task.reqBody)) {
|
||||||
|
useFaceCorrectionField.checked = false
|
||||||
|
}
|
||||||
|
if (!('use_upscale' in task.reqBody)) {
|
||||||
|
useUpscalingField.checked = false
|
||||||
|
}
|
||||||
|
if (!('mask' in task.reqBody)) {
|
||||||
|
maskSetting.checked = false
|
||||||
|
}
|
||||||
|
upscaleModelField.disabled = !useUpscalingField.checked
|
||||||
|
|
||||||
|
// Show the source picture if present
|
||||||
|
initImagePreview.src = (task.reqBody.init_image == undefined ? '' : task.reqBody.init_image)
|
||||||
|
if (IMAGE_REGEX.test(initImagePreview.src)) {
|
||||||
|
Boolean(task.reqBody.mask) ? inpaintingEditor.setImg(task.reqBody.mask) : inpaintingEditor.resetBackground()
|
||||||
|
initImagePreviewContainer.style.display = 'block'
|
||||||
|
inpaintingEditorContainer.style.display = 'none'
|
||||||
|
promptStrengthContainer.style.display = 'table-row'
|
||||||
|
//samplerSelectionContainer.style.display = 'none'
|
||||||
|
// maskSetting.checked = false
|
||||||
|
inpaintingEditorContainer.style.display = maskSetting.checked ? 'block' : 'none'
|
||||||
|
} else {
|
||||||
|
initImagePreviewContainer.style.display = 'none'
|
||||||
|
// inpaintingEditorContainer.style.display = 'none'
|
||||||
|
promptStrengthContainer.style.display = 'none'
|
||||||
|
// maskSetting.style.display = 'none'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
function readUI() {
|
function readUI() {
|
||||||
const reqBody = {}
|
const reqBody = {}
|
||||||
|
@ -148,6 +148,58 @@ async function loadModifiers() {
|
|||||||
loadCustomModifiers()
|
loadCustomModifiers()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function refreshModifiersState(newTags) {
|
||||||
|
// clear existing modifiers
|
||||||
|
document.querySelector('#editor-modifiers').querySelectorAll('.modifier-card').forEach(modifierCard => {
|
||||||
|
const modifierName = modifierCard.querySelector('.modifier-card-label').innerText
|
||||||
|
if (activeTags.map(x => x.name).includes(modifierName)) {
|
||||||
|
modifierCard.classList.remove(activeCardClass)
|
||||||
|
modifierCard.querySelector('.modifier-card-image-overlay').innerText = '+'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
activeTags = []
|
||||||
|
|
||||||
|
// set new modifiers
|
||||||
|
newTags.forEach(tag => {
|
||||||
|
let found = false
|
||||||
|
document.querySelector('#editor-modifiers').querySelectorAll('.modifier-card').forEach(modifierCard => {
|
||||||
|
const modifierName = modifierCard.querySelector('.modifier-card-label').innerText
|
||||||
|
if (tag == modifierName) {
|
||||||
|
// add modifier to active array
|
||||||
|
activeTags.push({
|
||||||
|
'name': modifierName,
|
||||||
|
'element': modifierCard.cloneNode(true),
|
||||||
|
'originElement': modifierCard
|
||||||
|
})
|
||||||
|
modifierCard.classList.add(activeCardClass)
|
||||||
|
modifierCard.querySelector('.modifier-card-image-overlay').innerText = '-'
|
||||||
|
found = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (found == false) { // custom tag went missing, create one here
|
||||||
|
let modifierCard = createModifierCard(tag, undefined) // create a modifier card for the missing tag, no image
|
||||||
|
|
||||||
|
modifierCard.addEventListener('click', () => {
|
||||||
|
if (activeTags.map(x => x.name).includes(tag)) {
|
||||||
|
// remove modifier from active array
|
||||||
|
activeTags = activeTags.filter(x => x.name != tag)
|
||||||
|
modifierCard.classList.remove(activeCardClass)
|
||||||
|
|
||||||
|
modifierCard.querySelector('.modifier-card-image-overlay').innerText = '+'
|
||||||
|
}
|
||||||
|
refreshTagsList()
|
||||||
|
})
|
||||||
|
|
||||||
|
activeTags.push({
|
||||||
|
'name': tag,
|
||||||
|
'element': modifierCard,
|
||||||
|
'originElement': undefined // no origin element for missing tags
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
refreshTagsList()
|
||||||
|
}
|
||||||
|
|
||||||
function refreshTagsList() {
|
function refreshTagsList() {
|
||||||
editorModifierTagsList.innerHTML = ''
|
editorModifierTagsList.innerHTML = ''
|
||||||
|
|
||||||
@ -167,7 +219,7 @@ function refreshTagsList() {
|
|||||||
tag.element.addEventListener('click', () => {
|
tag.element.addEventListener('click', () => {
|
||||||
let idx = activeTags.indexOf(tag)
|
let idx = activeTags.indexOf(tag)
|
||||||
|
|
||||||
if (idx !== -1) {
|
if (idx !== -1 && activeTags[idx].originElement !== undefined) {
|
||||||
activeTags[idx].originElement.classList.remove(activeCardClass)
|
activeTags[idx].originElement.classList.remove(activeCardClass)
|
||||||
activeTags[idx].originElement.querySelector('.modifier-card-image-overlay').innerText = '+'
|
activeTags[idx].originElement.querySelector('.modifier-card-image-overlay').innerText = '+'
|
||||||
|
|
||||||
|
@ -789,7 +789,9 @@ function getCurrentUserRequest() {
|
|||||||
stream_progress_updates: true,
|
stream_progress_updates: true,
|
||||||
stream_image_progress: (numOutputsTotal > 50 ? false : streamImageProgressField.checked),
|
stream_image_progress: (numOutputsTotal > 50 ? false : streamImageProgressField.checked),
|
||||||
show_only_filtered_image: showOnlyFilteredImageField.checked,
|
show_only_filtered_image: showOnlyFilteredImageField.checked,
|
||||||
output_format: outputFormatField.value
|
output_format: outputFormatField.value,
|
||||||
|
original_prompt: promptField.value,
|
||||||
|
active_tags: (activeTags.map(x => x.name))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (IMAGE_REGEX.test(initImagePreview.src)) {
|
if (IMAGE_REGEX.test(initImagePreview.src)) {
|
||||||
@ -856,6 +858,7 @@ function createTask(task) {
|
|||||||
taskEntry.innerHTML = ` <div class="header-content panel collapsible active">
|
taskEntry.innerHTML = ` <div class="header-content panel collapsible active">
|
||||||
<div class="taskStatusLabel">Enqueued</div>
|
<div class="taskStatusLabel">Enqueued</div>
|
||||||
<button class="secondaryButton stopTask"><i class="fa-solid fa-trash-can"></i> Remove</button>
|
<button class="secondaryButton stopTask"><i class="fa-solid fa-trash-can"></i> Remove</button>
|
||||||
|
<button class="secondaryButton useSettings"><i class="fa-solid fa-redo"></i> Use these settings</button>
|
||||||
<div class="preview-prompt collapsible active"></div>
|
<div class="preview-prompt collapsible active"></div>
|
||||||
<div class="taskConfig">${taskConfig}</div>
|
<div class="taskConfig">${taskConfig}</div>
|
||||||
<div class="outputMsg"></div>
|
<div class="outputMsg"></div>
|
||||||
@ -894,6 +897,12 @@ function createTask(task) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
task['useSettings'] = taskEntry.querySelector('.useSettings')
|
||||||
|
task['useSettings'].addEventListener('click', function(e) {
|
||||||
|
e.stopPropagation()
|
||||||
|
restoreTaskToUI(task, TASK_REQ_NO_EXPORT)
|
||||||
|
})
|
||||||
|
|
||||||
imagePreview.insertBefore(taskEntry, previewTools.nextSibling)
|
imagePreview.insertBefore(taskEntry, previewTools.nextSibling)
|
||||||
|
|
||||||
task.previewPrompt.innerText = task.reqBody.prompt
|
task.previewPrompt.innerText = task.reqBody.prompt
|
||||||
@ -1079,10 +1088,6 @@ useUpscalingField.addEventListener('change', function(e) {
|
|||||||
upscaleModelField.disabled = !this.checked
|
upscaleModelField.disabled = !this.checked
|
||||||
})
|
})
|
||||||
|
|
||||||
if (useBetaChannelField.checked) {
|
|
||||||
updateBranchLabel.innerText = "(beta)"
|
|
||||||
}
|
|
||||||
|
|
||||||
makeImageBtn.addEventListener('click', makeImage)
|
makeImageBtn.addEventListener('click', makeImage)
|
||||||
|
|
||||||
document.onkeydown = function(e) {
|
document.onkeydown = function(e) {
|
||||||
@ -1141,8 +1146,16 @@ async function getModels() {
|
|||||||
let res = await fetch('/get/models')
|
let res = await fetch('/get/models')
|
||||||
const models = await res.json()
|
const models = await res.json()
|
||||||
|
|
||||||
console.log('get models response', models)
|
console.log('got models response', models)
|
||||||
|
|
||||||
|
if ( "scan-error" in models ) {
|
||||||
|
// let previewPane = document.getElementById('tab-content-wrapper')
|
||||||
|
let previewPane = document.getElementById('preview')
|
||||||
|
previewPane.style.background="red"
|
||||||
|
previewPane.style.textAlign="center"
|
||||||
|
previewPane.innerHTML = '<H1>🔥Malware alert!🔥</H1><h2>The file <i>' + models['scan-error'] + '</i> in your <tt>models/stable-diffusion</tt> folder is probably malware infected.</h2><h2>Please delete this file from the folder before proceeding!</h2>After deleting the file, reload this page.<br><br><button onClick="window.location.reload();">Reload Page</button>'
|
||||||
|
makeImageBtn.disabled = true
|
||||||
|
}
|
||||||
let modelOptions = models['options']
|
let modelOptions = models['options']
|
||||||
let stableDiffusionOptions = modelOptions['stable-diffusion']
|
let stableDiffusionOptions = modelOptions['stable-diffusion']
|
||||||
let vaeOptions = modelOptions['vae']
|
let vaeOptions = modelOptions['vae']
|
||||||
@ -1323,3 +1336,4 @@ window.addEventListener("beforeunload", function(e) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
createCollapsibles()
|
createCollapsibles()
|
||||||
|
prettifyInputs(document);
|
@ -28,18 +28,21 @@ var PARAMETERS = [
|
|||||||
type: ParameterType.select,
|
type: ParameterType.select,
|
||||||
label: "Theme",
|
label: "Theme",
|
||||||
default: "theme-default",
|
default: "theme-default",
|
||||||
|
note: "customize the look and feel of the ui",
|
||||||
options: [ // Note: options expanded dynamically
|
options: [ // Note: options expanded dynamically
|
||||||
{
|
{
|
||||||
value: "theme-default",
|
value: "theme-default",
|
||||||
label: "Default"
|
label: "Default"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
icon: "fa-palette"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "save_to_disk",
|
id: "save_to_disk",
|
||||||
type: ParameterType.checkbox,
|
type: ParameterType.checkbox,
|
||||||
label: "Auto-Save Images",
|
label: "Auto-Save Images",
|
||||||
note: "automatically saves images to the specified location",
|
note: "automatically saves images to the specified location",
|
||||||
|
icon: "fa-download",
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -55,6 +58,7 @@ var PARAMETERS = [
|
|||||||
type: ParameterType.checkbox,
|
type: ParameterType.checkbox,
|
||||||
label: "Enable Sound",
|
label: "Enable Sound",
|
||||||
note: "plays a sound on task completion",
|
note: "plays a sound on task completion",
|
||||||
|
icon: "fa-volume-low",
|
||||||
default: true,
|
default: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -62,20 +66,23 @@ var PARAMETERS = [
|
|||||||
type: ParameterType.checkbox,
|
type: ParameterType.checkbox,
|
||||||
label: "Open browser on startup",
|
label: "Open browser on startup",
|
||||||
note: "starts the default browser on startup",
|
note: "starts the default browser on startup",
|
||||||
|
icon: "fa-window-restore",
|
||||||
default: true,
|
default: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "turbo",
|
id: "turbo",
|
||||||
type: ParameterType.checkbox,
|
type: ParameterType.checkbox,
|
||||||
label: "Turbo Mode",
|
label: "Turbo Mode",
|
||||||
default: true,
|
|
||||||
note: "generates images faster, but uses an additional 1 GB of GPU memory",
|
note: "generates images faster, but uses an additional 1 GB of GPU memory",
|
||||||
|
icon: "fa-forward",
|
||||||
|
default: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "use_cpu",
|
id: "use_cpu",
|
||||||
type: ParameterType.checkbox,
|
type: ParameterType.checkbox,
|
||||||
label: "Use CPU (not GPU)",
|
label: "Use CPU (not GPU)",
|
||||||
note: "warning: this will be *very* slow",
|
note: "warning: this will be *very* slow",
|
||||||
|
icon: "fa-microchip",
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -96,6 +103,7 @@ var PARAMETERS = [
|
|||||||
type: ParameterType.checkbox,
|
type: ParameterType.checkbox,
|
||||||
label: "Use Full Precision",
|
label: "Use Full Precision",
|
||||||
note: "for GPU-only. warning: this will consume more VRAM",
|
note: "for GPU-only. warning: this will consume more VRAM",
|
||||||
|
icon: "fa-crosshairs",
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -103,13 +111,15 @@ var PARAMETERS = [
|
|||||||
type: ParameterType.checkbox,
|
type: ParameterType.checkbox,
|
||||||
label: "Auto-Save Settings",
|
label: "Auto-Save Settings",
|
||||||
note: "restores settings on browser load",
|
note: "restores settings on browser load",
|
||||||
|
icon: "fa-gear",
|
||||||
default: true,
|
default: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "use_beta_channel",
|
id: "use_beta_channel",
|
||||||
type: ParameterType.checkbox,
|
type: ParameterType.checkbox,
|
||||||
label: "🔥Beta channel",
|
label: "Beta channel",
|
||||||
note: "Get the latest features immediately (but could be less stable). Please restart the program after changing this.",
|
note: "Get the latest features immediately (but could be less stable). Please restart the program after changing this.",
|
||||||
|
icon: "fa-fire",
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
@ -140,16 +150,18 @@ function getParameterElement(parameter) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let parametersTable = document.querySelector("#system-settings table")
|
let parametersTable = document.querySelector("#system-settings .parameters-table")
|
||||||
/* fill in the system settings popup table */
|
/* fill in the system settings popup table */
|
||||||
function initParameters() {
|
function initParameters() {
|
||||||
PARAMETERS.forEach(parameter => {
|
PARAMETERS.forEach(parameter => {
|
||||||
var element = getParameterElement(parameter)
|
var element = getParameterElement(parameter)
|
||||||
var note = parameter.note ? `<small>${parameter.note}</small>` : "";
|
var note = parameter.note ? `<small>${parameter.note}</small>` : "";
|
||||||
var newrow = document.createElement('tr')
|
var icon = parameter.icon ? `<i class="fa ${parameter.icon}"></i>` : "";
|
||||||
|
var newrow = document.createElement('div')
|
||||||
newrow.innerHTML = `
|
newrow.innerHTML = `
|
||||||
<td><label for="${parameter.id}">${parameter.label}</label></td>
|
<div>${icon}</div>
|
||||||
<td><div>${element}${note}<div></td>`
|
<div><label for="${parameter.id}">${parameter.label}</label>${note}</div>
|
||||||
|
<div>${element}</div>`
|
||||||
parametersTable.appendChild(newrow)
|
parametersTable.appendChild(newrow)
|
||||||
parameter.settingsEntry = newrow
|
parameter.settingsEntry = newrow
|
||||||
})
|
})
|
||||||
@ -193,6 +205,7 @@ async function getAppConfig() {
|
|||||||
|
|
||||||
if (config.update_branch === 'beta') {
|
if (config.update_branch === 'beta') {
|
||||||
useBetaChannelField.checked = true
|
useBetaChannelField.checked = true
|
||||||
|
document.querySelector("#updateBranchLabel").innerText = "(beta)"
|
||||||
}
|
}
|
||||||
if (config.ui && config.ui.open_browser_on_start === false) {
|
if (config.ui && config.ui.open_browser_on_start === false) {
|
||||||
uiOpenBrowserOnStartField.checked = false
|
uiOpenBrowserOnStartField.checked = false
|
||||||
@ -224,6 +237,7 @@ function getCurrentRenderDeviceSelection() {
|
|||||||
useCPUField.addEventListener('click', function() {
|
useCPUField.addEventListener('click', function() {
|
||||||
let gpuSettingEntry = getParameterSettingsEntry('use_gpus')
|
let gpuSettingEntry = getParameterSettingsEntry('use_gpus')
|
||||||
let autoPickGPUSettingEntry = getParameterSettingsEntry('auto_pick_gpus')
|
let autoPickGPUSettingEntry = getParameterSettingsEntry('auto_pick_gpus')
|
||||||
|
console.log("hello", this.checked);
|
||||||
if (this.checked) {
|
if (this.checked) {
|
||||||
gpuSettingEntry.style.display = 'none'
|
gpuSettingEntry.style.display = 'none'
|
||||||
autoPickGPUSettingEntry.style.display = 'none'
|
autoPickGPUSettingEntry.style.display = 'none'
|
||||||
|
@ -14,7 +14,7 @@ function initTheme() {
|
|||||||
.flatMap(sheet => Array.from(sheet.cssRules))
|
.flatMap(sheet => Array.from(sheet.cssRules))
|
||||||
.forEach(rule => {
|
.forEach(rule => {
|
||||||
var selector = rule.selectorText; // TODO: also do selector == ":root", re-run un-set props
|
var selector = rule.selectorText; // TODO: also do selector == ":root", re-run un-set props
|
||||||
if (selector && selector.startsWith(".theme-")) {
|
if (selector && selector.startsWith(".theme-") && !selector.includes(" ")) {
|
||||||
var theme_key = selector.substring(1);
|
var theme_key = selector.substring(1);
|
||||||
THEMES.push({
|
THEMES.push({
|
||||||
key: theme_key,
|
key: theme_key,
|
||||||
|
@ -358,3 +358,19 @@ function preventNonNumericalInput(e) {
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* inserts custom html to allow prettifying of inputs */
|
||||||
|
function prettifyInputs(root_element) {
|
||||||
|
root_element.querySelectorAll(`input[type="checkbox"]`).forEach(element => {
|
||||||
|
var parent = element.parentNode;
|
||||||
|
if (!parent.classList.contains("input-toggle")) {
|
||||||
|
var wrapper = document.createElement("div");
|
||||||
|
wrapper.classList.add("input-toggle");
|
||||||
|
parent.replaceChild(wrapper, element);
|
||||||
|
wrapper.appendChild(element);
|
||||||
|
var label = document.createElement("label");
|
||||||
|
label.htmlFor = element.id;
|
||||||
|
wrapper.appendChild(label);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
@ -140,15 +140,24 @@ def load_model_ckpt():
|
|||||||
_, _ = modelFS.load_state_dict(sd, strict=False)
|
_, _ = modelFS.load_state_dict(sd, strict=False)
|
||||||
|
|
||||||
if thread_data.vae_file is not None:
|
if thread_data.vae_file is not None:
|
||||||
for model_extension in ['.ckpt', '.vae.pt']:
|
try:
|
||||||
if os.path.exists(thread_data.vae_file + model_extension):
|
loaded = False
|
||||||
print(f"Loading VAE weights from: {thread_data.vae_file}{model_extension}")
|
for model_extension in ['.ckpt', '.vae.pt']:
|
||||||
vae_ckpt = torch.load(thread_data.vae_file + model_extension, map_location="cpu")
|
if os.path.exists(thread_data.vae_file + model_extension):
|
||||||
vae_dict = {k: v for k, v in vae_ckpt["state_dict"].items() if k[0:4] != "loss"}
|
print(f"Loading VAE weights from: {thread_data.vae_file}{model_extension}")
|
||||||
modelFS.first_stage_model.load_state_dict(vae_dict, strict=False)
|
vae_ckpt = torch.load(thread_data.vae_file + model_extension, map_location="cpu")
|
||||||
break
|
vae_dict = {k: v for k, v in vae_ckpt["state_dict"].items() if k[0:4] != "loss"}
|
||||||
else:
|
modelFS.first_stage_model.load_state_dict(vae_dict, strict=False)
|
||||||
print(f'Cannot find VAE file: {thread_data.vae_file}{model_extension}')
|
loaded = True
|
||||||
|
break
|
||||||
|
|
||||||
|
if not loaded:
|
||||||
|
print(f'Cannot find VAE: {thread_data.vae_file}')
|
||||||
|
thread_data.vae_file = None
|
||||||
|
except:
|
||||||
|
print(traceback.format_exc())
|
||||||
|
print(f'Could not load VAE: {thread_data.vae_file}')
|
||||||
|
thread_data.vae_file = None
|
||||||
|
|
||||||
modelFS.eval()
|
modelFS.eval()
|
||||||
# if thread_data.device != 'cpu':
|
# if thread_data.device != 'cpu':
|
||||||
@ -210,29 +219,36 @@ def unload_models():
|
|||||||
|
|
||||||
gc()
|
gc()
|
||||||
|
|
||||||
def wait_model_move_to(model, target_device): # Send to target_device and wait until complete.
|
# def wait_model_move_to(model, target_device): # Send to target_device and wait until complete.
|
||||||
if thread_data.device == target_device: return
|
# if thread_data.device == target_device: return
|
||||||
start_mem = torch.cuda.memory_allocated(thread_data.device) / 1e6
|
# start_mem = torch.cuda.memory_allocated(thread_data.device) / 1e6
|
||||||
if start_mem <= 0: return
|
# if start_mem <= 0: return
|
||||||
model_name = model.__class__.__name__
|
# model_name = model.__class__.__name__
|
||||||
print(f'Device {thread_data.device} - Sending model {model_name} to {target_device} | Memory transfer starting. Memory Used: {round(start_mem)}Mb')
|
# print(f'Device {thread_data.device} - Sending model {model_name} to {target_device} | Memory transfer starting. Memory Used: {round(start_mem)}Mb')
|
||||||
start_time = time.time()
|
# start_time = time.time()
|
||||||
model.to(target_device)
|
# model.to(target_device)
|
||||||
time_step = start_time
|
# time_step = start_time
|
||||||
WARNING_TIMEOUT = 1.5 # seconds - Show activity in console after timeout.
|
# WARNING_TIMEOUT = 1.5 # seconds - Show activity in console after timeout.
|
||||||
last_mem = start_mem
|
# last_mem = start_mem
|
||||||
is_transfering = True
|
# is_transfering = True
|
||||||
while is_transfering:
|
# while is_transfering:
|
||||||
time.sleep(0.5) # 500ms
|
# time.sleep(0.5) # 500ms
|
||||||
mem = torch.cuda.memory_allocated(thread_data.device) / 1e6
|
# mem = torch.cuda.memory_allocated(thread_data.device) / 1e6
|
||||||
is_transfering = bool(mem > 0 and mem < last_mem) # still stuff loaded, but less than last time.
|
# is_transfering = bool(mem > 0 and mem < last_mem) # still stuff loaded, but less than last time.
|
||||||
last_mem = mem
|
# last_mem = mem
|
||||||
if not is_transfering:
|
# if not is_transfering:
|
||||||
break;
|
# break;
|
||||||
if time.time() - time_step > WARNING_TIMEOUT: # Long delay, print to console to show activity.
|
# if time.time() - time_step > WARNING_TIMEOUT: # Long delay, print to console to show activity.
|
||||||
print(f'Device {thread_data.device} - Waiting for Memory transfer. Memory Used: {round(mem)}Mb, Transfered: {round(start_mem - mem)}Mb')
|
# print(f'Device {thread_data.device} - Waiting for Memory transfer. Memory Used: {round(mem)}Mb, Transfered: {round(start_mem - mem)}Mb')
|
||||||
time_step = time.time()
|
# time_step = time.time()
|
||||||
print(f'Device {thread_data.device} - {model_name} Moved: {round(start_mem - last_mem)}Mb in {round(time.time() - start_time, 3)} seconds to {target_device}')
|
# print(f'Device {thread_data.device} - {model_name} Moved: {round(start_mem - last_mem)}Mb in {round(time.time() - start_time, 3)} seconds to {target_device}')
|
||||||
|
|
||||||
|
def move_to_cpu(model):
|
||||||
|
if thread_data.device != "cpu":
|
||||||
|
mem = torch.cuda.memory_allocated() / 1e6
|
||||||
|
model.to("cpu")
|
||||||
|
while torch.cuda.memory_allocated() / 1e6 >= mem:
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
def load_model_gfpgan():
|
def load_model_gfpgan():
|
||||||
if thread_data.gfpgan_file is None: raise ValueError(f'Thread gfpgan_file is undefined.')
|
if thread_data.gfpgan_file is None: raise ValueError(f'Thread gfpgan_file is undefined.')
|
||||||
@ -475,7 +491,8 @@ def do_mk_img(req: Request):
|
|||||||
mask = mask.half()
|
mask = mask.half()
|
||||||
|
|
||||||
# Send to CPU and wait until complete.
|
# Send to CPU and wait until complete.
|
||||||
wait_model_move_to(thread_data.modelFS, 'cpu')
|
# wait_model_move_to(thread_data.modelFS, 'cpu')
|
||||||
|
move_to_cpu(thread_data.modelFS)
|
||||||
|
|
||||||
assert 0. <= req.prompt_strength <= 1., 'can only work with strength in [0.0, 1.0]'
|
assert 0. <= req.prompt_strength <= 1., 'can only work with strength in [0.0, 1.0]'
|
||||||
t_enc = int(req.prompt_strength * req.num_inference_steps)
|
t_enc = int(req.prompt_strength * req.num_inference_steps)
|
||||||
@ -551,10 +568,6 @@ def do_mk_img(req: Request):
|
|||||||
img_data[i] = x_sample
|
img_data[i] = x_sample
|
||||||
del x_samples, x_samples_ddim, x_sample
|
del x_samples, x_samples_ddim, x_sample
|
||||||
|
|
||||||
if thread_data.reduced_memory:
|
|
||||||
# Send to CPU and wait until complete.
|
|
||||||
wait_model_move_to(thread_data.modelFS, 'cpu')
|
|
||||||
|
|
||||||
print("saving images")
|
print("saving images")
|
||||||
for i in range(batch_size):
|
for i in range(batch_size):
|
||||||
img = Image.fromarray(img_data[i])
|
img = Image.fromarray(img_data[i])
|
||||||
@ -608,6 +621,7 @@ def do_mk_img(req: Request):
|
|||||||
|
|
||||||
# if thread_data.reduced_memory:
|
# if thread_data.reduced_memory:
|
||||||
# unload_filters()
|
# unload_filters()
|
||||||
|
move_to_cpu(thread_data.modelFS)
|
||||||
del img_data
|
del img_data
|
||||||
gc()
|
gc()
|
||||||
if thread_data.device != 'cpu':
|
if thread_data.device != 'cpu':
|
||||||
@ -647,7 +661,9 @@ def _txt2img(opt_W, opt_H, opt_n_samples, opt_ddim_steps, opt_scale, start_code,
|
|||||||
shape = [opt_n_samples, opt_C, opt_H // opt_f, opt_W // opt_f]
|
shape = [opt_n_samples, opt_C, opt_H // opt_f, opt_W // opt_f]
|
||||||
|
|
||||||
# Send to CPU and wait until complete.
|
# Send to CPU and wait until complete.
|
||||||
wait_model_move_to(thread_data.modelCS, 'cpu')
|
# wait_model_move_to(thread_data.modelCS, 'cpu')
|
||||||
|
|
||||||
|
move_to_cpu(thread_data.modelCS)
|
||||||
|
|
||||||
if sampler_name == 'ddim':
|
if sampler_name == 'ddim':
|
||||||
thread_data.model.make_schedule(ddim_num_steps=opt_ddim_steps, ddim_eta=opt_ddim_eta, verbose=False)
|
thread_data.model.make_schedule(ddim_num_steps=opt_ddim_steps, ddim_eta=opt_ddim_eta, verbose=False)
|
||||||
|
@ -436,7 +436,7 @@ def stop_render_thread(device):
|
|||||||
try:
|
try:
|
||||||
device_manager.validate_device_id(device, log_prefix='stop_render_thread')
|
device_manager.validate_device_id(device, log_prefix='stop_render_thread')
|
||||||
except:
|
except:
|
||||||
print(traceback.format_exec())
|
print(traceback.format_exc())
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if not manager_lock.acquire(blocking=True, timeout=LOCK_TIMEOUT): raise Exception('stop_render_thread' + ERR_LOCK_FAILED)
|
if not manager_lock.acquire(blocking=True, timeout=LOCK_TIMEOUT): raise Exception('stop_render_thread' + ERR_LOCK_FAILED)
|
||||||
|
51
ui/server.py
51
ui/server.py
@ -7,6 +7,8 @@ import traceback
|
|||||||
|
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
|
import picklescan.scanner
|
||||||
|
import rich
|
||||||
|
|
||||||
SD_DIR = os.getcwd()
|
SD_DIR = os.getcwd()
|
||||||
print('started in ', SD_DIR)
|
print('started in ', SD_DIR)
|
||||||
@ -21,6 +23,9 @@ USER_UI_PLUGINS_DIR = os.path.abspath(os.path.join(SD_DIR, '..', 'plugins', 'ui'
|
|||||||
CORE_UI_PLUGINS_DIR = os.path.abspath(os.path.join(SD_UI_DIR, 'plugins', 'ui'))
|
CORE_UI_PLUGINS_DIR = os.path.abspath(os.path.join(SD_UI_DIR, 'plugins', 'ui'))
|
||||||
UI_PLUGINS_SOURCES = ((CORE_UI_PLUGINS_DIR, 'core'), (USER_UI_PLUGINS_DIR, 'user'))
|
UI_PLUGINS_SOURCES = ((CORE_UI_PLUGINS_DIR, 'core'), (USER_UI_PLUGINS_DIR, 'user'))
|
||||||
|
|
||||||
|
STABLE_DIFFUSION_MODEL_EXTENSIONS = ['.ckpt']
|
||||||
|
VAE_MODEL_EXTENSIONS = ['.vae.pt', '.ckpt']
|
||||||
|
|
||||||
OUTPUT_DIRNAME = "Stable Diffusion UI" # in the user's home folder
|
OUTPUT_DIRNAME = "Stable Diffusion UI" # in the user's home folder
|
||||||
TASK_TTL = 15 * 60 # Discard last session's task timeout
|
TASK_TTL = 15 * 60 # Discard last session's task timeout
|
||||||
APP_CONFIG_DEFAULTS = {
|
APP_CONFIG_DEFAULTS = {
|
||||||
@ -59,10 +64,18 @@ ACCESS_LOG_SUPPRESS_PATH_PREFIXES = ['/ping', '/image', '/modifier-thumbnails']
|
|||||||
|
|
||||||
NOCACHE_HEADERS={"Cache-Control": "no-cache, no-store, must-revalidate", "Pragma": "no-cache", "Expires": "0"}
|
NOCACHE_HEADERS={"Cache-Control": "no-cache, no-store, must-revalidate", "Pragma": "no-cache", "Expires": "0"}
|
||||||
|
|
||||||
app.mount('/media', StaticFiles(directory=os.path.join(SD_UI_DIR, 'media')), name="media")
|
class NoCacheStaticFiles(StaticFiles):
|
||||||
|
def is_not_modified(self, response_headers, request_headers) -> bool:
|
||||||
|
if 'content-type' in response_headers and ('javascript' in response_headers['content-type'] or 'css' in response_headers['content-type']):
|
||||||
|
response_headers.update(NOCACHE_HEADERS)
|
||||||
|
return False
|
||||||
|
|
||||||
|
return super().is_not_modified(response_headers, request_headers)
|
||||||
|
|
||||||
|
app.mount('/media', NoCacheStaticFiles(directory=os.path.join(SD_UI_DIR, 'media')), name="media")
|
||||||
|
|
||||||
for plugins_dir, dir_prefix in UI_PLUGINS_SOURCES:
|
for plugins_dir, dir_prefix in UI_PLUGINS_SOURCES:
|
||||||
app.mount(f'/plugins/{dir_prefix}', StaticFiles(directory=plugins_dir), name=f"plugins-{dir_prefix}")
|
app.mount(f'/plugins/{dir_prefix}', NoCacheStaticFiles(directory=plugins_dir), name=f"plugins-{dir_prefix}")
|
||||||
|
|
||||||
def getConfig(default_val=APP_CONFIG_DEFAULTS):
|
def getConfig(default_val=APP_CONFIG_DEFAULTS):
|
||||||
try:
|
try:
|
||||||
@ -152,11 +165,11 @@ def resolve_model_to_use(model_name:str, model_type:str, model_dir:str, model_ex
|
|||||||
raise Exception('No valid models found.')
|
raise Exception('No valid models found.')
|
||||||
|
|
||||||
def resolve_ckpt_to_use(model_name:str=None):
|
def resolve_ckpt_to_use(model_name:str=None):
|
||||||
return resolve_model_to_use(model_name, model_type='stable-diffusion', model_dir='stable-diffusion', model_extensions=['.ckpt'], default_models=APP_CONFIG_DEFAULT_MODELS)
|
return resolve_model_to_use(model_name, model_type='stable-diffusion', model_dir='stable-diffusion', model_extensions=STABLE_DIFFUSION_MODEL_EXTENSIONS, default_models=APP_CONFIG_DEFAULT_MODELS)
|
||||||
|
|
||||||
def resolve_vae_to_use(model_name:str=None):
|
def resolve_vae_to_use(model_name:str=None):
|
||||||
try:
|
try:
|
||||||
return resolve_model_to_use(model_name, model_type='vae', model_dir='vae', model_extensions=['.vae.pt', '.ckpt'], default_models=[])
|
return resolve_model_to_use(model_name, model_type='vae', model_dir='vae', model_extensions=VAE_MODEL_EXTENSIONS, default_models=[])
|
||||||
except:
|
except:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@ -188,6 +201,20 @@ async def setAppConfig(req : SetAppConfigRequest):
|
|||||||
print(traceback.format_exc())
|
print(traceback.format_exc())
|
||||||
raise HTTPException(status_code=500, detail=str(e))
|
raise HTTPException(status_code=500, detail=str(e))
|
||||||
|
|
||||||
|
def is_malicious_model(file_path):
|
||||||
|
try:
|
||||||
|
scan_result = picklescan.scanner.scan_file_path(file_path)
|
||||||
|
if scan_result.issues_count > 0 or scan_result.infected_files > 0:
|
||||||
|
rich.print(":warning: [bold red]Scan %s: %d scanned, %d issue, %d infected.[/bold red]" % (file_path, scan_result.scanned_files, scan_result.issues_count, scan_result.infected_files))
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
rich.print("Scan %s: [green]%d scanned, %d issue, %d infected.[/green]" % (file_path, scan_result.scanned_files, scan_result.issues_count, scan_result.infected_files))
|
||||||
|
return False
|
||||||
|
except Exception as e:
|
||||||
|
print('error while scanning', file_path, 'error:', e)
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
def getModels():
|
def getModels():
|
||||||
models = {
|
models = {
|
||||||
'active': {
|
'active': {
|
||||||
@ -207,16 +234,22 @@ def getModels():
|
|||||||
|
|
||||||
for file in os.listdir(models_dir):
|
for file in os.listdir(models_dir):
|
||||||
for model_extension in model_extensions:
|
for model_extension in model_extensions:
|
||||||
if file.endswith(model_extension):
|
if not file.endswith(model_extension):
|
||||||
model_name = file[:-len(model_extension)]
|
continue
|
||||||
models['options'][model_type].append(model_name)
|
|
||||||
|
if is_malicious_model(os.path.join(models_dir, file)):
|
||||||
|
models['scan-error'] = file
|
||||||
|
return
|
||||||
|
|
||||||
|
model_name = file[:-len(model_extension)]
|
||||||
|
models['options'][model_type].append(model_name)
|
||||||
|
|
||||||
models['options'][model_type] = [*set(models['options'][model_type])] # remove duplicates
|
models['options'][model_type] = [*set(models['options'][model_type])] # remove duplicates
|
||||||
models['options'][model_type].sort()
|
models['options'][model_type].sort()
|
||||||
|
|
||||||
# custom models
|
# custom models
|
||||||
listModels(models_dirname='stable-diffusion', model_type='stable-diffusion', model_extensions=['.ckpt'])
|
listModels(models_dirname='stable-diffusion', model_type='stable-diffusion', model_extensions=STABLE_DIFFUSION_MODEL_EXTENSIONS)
|
||||||
listModels(models_dirname='vae', model_type='vae', model_extensions=['.vae.pt', '.ckpt'])
|
listModels(models_dirname='vae', model_type='vae', model_extensions=VAE_MODEL_EXTENSIONS)
|
||||||
|
|
||||||
# legacy
|
# legacy
|
||||||
custom_weight_path = os.path.join(SD_DIR, 'custom-model.ckpt')
|
custom_weight_path = os.path.join(SD_DIR, 'custom-model.ckpt')
|
||||||
|
Loading…
x
Reference in New Issue
Block a user