Compare commits
42 Commits
react
...
installer_
Author | SHA1 | Date | |
---|---|---|---|
7219c55dcd | |||
9aa46f92dc | |||
199fa4a0f5 | |||
c91348dae7 | |||
b47ff071da | |||
0d921eacb6 | |||
e1718c45e1 | |||
1c5352203d | |||
e521b350ca | |||
e9ddef6992 | |||
1d4a835e4a | |||
3cf7a984fd | |||
a6913dfe29 | |||
1f7c7909c2 | |||
0e15c48d04 | |||
a3e5931fd6 | |||
0e3766838f | |||
f17a00092a | |||
724e101edc | |||
0b1968c017 | |||
be3a52d703 | |||
7468aa5a4f | |||
889fd98577 | |||
9de91d3021 | |||
f20014660d | |||
add533d0da | |||
a5f5113e9a | |||
c72e1f0943 | |||
e282b2864f | |||
abcab9bce5 | |||
2174788514 | |||
ecda0d5b05 | |||
55bd8a34d7 | |||
65c667cc37 | |||
582b594789 | |||
19a868b2df | |||
9e07228a90 | |||
85f8141968 | |||
b9646a8a94 | |||
3a7e4390eb | |||
d07279c266 | |||
c10411c506 |
1
.gitattributes
vendored
@ -1 +0,0 @@
|
||||
* text=auto eol=lf
|
8
.gitignore
vendored
@ -1,11 +1,3 @@
|
||||
__pycache__
|
||||
installer
|
||||
installer.tar
|
||||
dist
|
||||
|
||||
# built code for the front end
|
||||
!/ui/frontend/dist
|
||||
ui/frontend/.idea/*
|
||||
ui/frontend/build_src/.idea/*
|
||||
|
||||
.idea/*
|
||||
|
15
Developer Console.cmd
Normal file
@ -0,0 +1,15 @@
|
||||
@echo off
|
||||
|
||||
echo "Opening Stable Diffusion UI - Developer Console.." & echo.
|
||||
|
||||
set SD_BASE_DIR=%cd%
|
||||
set MAMBA_ROOT_PREFIX=%SD_BASE_DIR%\env\mamba
|
||||
set INSTALL_ENV_DIR=%SD_BASE_DIR%\env\installer_env
|
||||
set PROJECT_ENV_DIR=%SD_BASE_DIR%\env\project_env
|
||||
|
||||
call "%MAMBA_ROOT_PREFIX%\condabin\mamba_hook.bat"
|
||||
|
||||
call micromamba activate "%INSTALL_ENV_DIR%"
|
||||
call micromamba activate "%PROJECT_ENV_DIR%"
|
||||
|
||||
cmd /k
|
@ -1,24 +0,0 @@
|
||||
Congrats on downloading Stable Diffusion UI, version 2!
|
||||
|
||||
If you haven't downloaded Stable Diffusion UI yet, please download from https://github.com/cmdr2/stable-diffusion-ui#installation
|
||||
|
||||
After downloading, to install please follow these instructions:
|
||||
|
||||
For Windows:
|
||||
- Please double-click the "Start Stable Diffusion UI.cmd" file inside the "stable-diffusion-ui" folder.
|
||||
|
||||
For Linux:
|
||||
- Please open a terminal, and go to the "stable-diffusion-ui" directory. Then run ./start.sh
|
||||
|
||||
That file will automatically install everything. After that it will start the Stable Diffusion interface in a web browser.
|
||||
|
||||
To start the UI in the future, please run the same command mentioned above.
|
||||
|
||||
|
||||
If you have any problems, please:
|
||||
1. Try the troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/wiki/Troubleshooting
|
||||
2. Or, seek help from the community at https://discord.com/invite/u9yhsFmEkB
|
||||
3. Or, file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues
|
||||
|
||||
Thanks
|
||||
cmdr2 (and contributors to the project)
|
@ -1,8 +0,0 @@
|
||||
Hi there,
|
||||
|
||||
What you have downloaded is meant for the developers of this project, not for users.
|
||||
|
||||
If you only want to use the Stable Diffusion UI, you've downloaded the wrong file.
|
||||
Please download and follow the instructions at https://github.com/cmdr2/stable-diffusion-ui#installation
|
||||
|
||||
Thanks
|
@ -8,7 +8,7 @@
|
||||
|
||||
[](https://discord.com/invite/u9yhsFmEkB) (for support, and development discussion) | [Troubleshooting guide for common problems](Troubleshooting.md)
|
||||
|
||||
️🔥🎉 **New!** Task Queue, Negative Prompt, Live Preview, More Samplers, In-Painting, Face Correction (GFPGAN) and Upscaling (RealESRGAN) have been added!
|
||||
️🔥🎉 **New!** Use Custom Weights, Task Queue, Negative Prompt, Live Preview, More Samplers, In-Painting, Face Correction (GFPGAN) and Upscaling (RealESRGAN) have been added!
|
||||
|
||||
This distribution currently uses Stable Diffusion 1.4. Once the model for 1.5 becomes publicly available, the model in this distribution will be updated.
|
||||
|
||||
@ -18,6 +18,7 @@ This distribution currently uses Stable Diffusion 1.4. Once the model for 1.5 be
|
||||
- **In-Painting**
|
||||
- **Live Preview**: See the image as the AI is drawing it
|
||||
- **Task Queue**: Queue up all your ideas, without waiting for the current task to finish
|
||||
- **Custom Weights**: Use your own `.ckpt` file, by placing it inside the `stable-diffusion` folder (rename it to `custom-model.ckpt`)
|
||||
- **Negative Prompt**: Specify aspects of the image to *remove*.
|
||||
- **Lots of Samplers:** ddim, plms, heun, euler, euler_a, dpm2, dpm2_a, lms
|
||||
- **Image Modifiers**: A library of *modifier tags* like *"Realistic"*, *"Pencil Sketch"*, *"ArtStation"* etc. Experiment with various styles quickly.
|
||||
|
25
Start Stable Diffusion UI.cmd
Normal file
@ -0,0 +1,25 @@
|
||||
@echo off
|
||||
|
||||
echo. & echo "Stable Diffusion UI - v2.5" & echo.
|
||||
|
||||
set PATH=C:\Windows\System32;%PATH%
|
||||
|
||||
set SD_BASE_DIR=%cd%
|
||||
|
||||
@rem Confirm or change the installation dir
|
||||
call installer\bootstrap\check-install-dir.bat
|
||||
|
||||
@rem set the vars again, if the installer dir has changed
|
||||
set SD_BASE_DIR=%cd%
|
||||
|
||||
echo Working in %SD_BASE_DIR%
|
||||
|
||||
@rem Setup the packages required for the installer
|
||||
call installer\bootstrap\bootstrap.bat
|
||||
|
||||
@rem Test the bootstrap
|
||||
call git --version
|
||||
call python --version
|
||||
|
||||
@rem Download the rest of the installer and UI
|
||||
call installer\installer\start.bat
|
@ -64,7 +64,7 @@ Users don't need to have the Anaconda Prompt installed to do this anymore, since
|
||||
5. Type `conda activate .\env` and press enter
|
||||
6. Type `python --version` and press enter. You should see 3.8.5.
|
||||
|
||||
**Windows:**
|
||||
**Linux:**
|
||||
1. Open the terminal
|
||||
2. Type `cd /path/to/stable-diffusion-ui` and press enter
|
||||
3. Type `installer/bin/activate` and press enter
|
||||
|
47
build.bat
@ -1,47 +0,0 @@
|
||||
@echo off
|
||||
|
||||
@echo "Hi there, what you are running is meant for the developers of this project, not for users." & echo.
|
||||
@echo "If you only want to use the Stable Diffusion UI, you've downloaded the wrong file."
|
||||
@echo "Please download and follow the instructions at https://github.com/cmdr2/stable-diffusion-ui#installation" & echo.
|
||||
@echo "If you are actually a developer of this project, please type Y and press enter" & echo.
|
||||
|
||||
set /p answer=Are you a developer of this project (Y/N)?
|
||||
if /i "%answer:~,1%" NEQ "Y" exit /b
|
||||
|
||||
@set PYTHONNOUSERSITE=1
|
||||
|
||||
@mkdir dist\stable-diffusion-ui
|
||||
|
||||
@echo "Downloading components for the installer.."
|
||||
|
||||
@call conda env create --prefix installer -f environment.yaml
|
||||
@call conda activate .\installer
|
||||
|
||||
@echo "Creating a distributable package.."
|
||||
|
||||
@call conda install -c conda-forge -y conda-pack
|
||||
@call conda pack --n-threads -1 --prefix installer --format tar
|
||||
|
||||
@cd dist\stable-diffusion-ui
|
||||
@mkdir installer
|
||||
|
||||
@call tar -xf ..\..\installer.tar -C installer
|
||||
|
||||
@mkdir scripts
|
||||
|
||||
@copy ..\..\scripts\on_env_start.bat scripts\
|
||||
@copy "..\..\scripts\Start Stable Diffusion UI.cmd" .
|
||||
@copy ..\..\LICENSE .
|
||||
@copy "..\..\CreativeML Open RAIL-M License" .
|
||||
@copy "..\..\How to install and run.txt" .
|
||||
@echo. > scripts\install_status.txt
|
||||
|
||||
@echo "Build ready. Zip the 'dist\stable-diffusion-ui' folder."
|
||||
|
||||
@echo "Cleaning up.."
|
||||
|
||||
@cd ..\..
|
||||
|
||||
@rmdir /s /q installer
|
||||
|
||||
@del installer.tar
|
55
build.sh
@ -1,55 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
printf "Hi there, what you are running is meant for the developers of this project, not for users.\n\n"
|
||||
printf "If you only want to use the Stable Diffusion UI, you've downloaded the wrong file.\n"
|
||||
printf "Please download and follow the instructions at https://github.com/cmdr2/stable-diffusion-ui#installation\n\n"
|
||||
printf "If you are actually a developer of this project, please type Y and press enter\n\n"
|
||||
|
||||
read -p "Are you a developer of this project (Y/N) " yn
|
||||
case $yn in
|
||||
[Yy]* ) ;;
|
||||
* ) exit;;
|
||||
esac
|
||||
|
||||
export PYTHONNOUSERSITE=1
|
||||
|
||||
mkdir -p dist/stable-diffusion-ui
|
||||
|
||||
echo "Downloading components for the installer.."
|
||||
|
||||
source ~/miniconda3/etc/profile.d/conda.sh
|
||||
|
||||
conda install -c conda-forge -y conda-pack
|
||||
|
||||
conda env create --prefix installer -f environment.yaml
|
||||
conda activate ./installer
|
||||
|
||||
echo "Creating a distributable package.."
|
||||
|
||||
conda pack --n-threads -1 --prefix installer --format tar
|
||||
|
||||
cd dist/stable-diffusion-ui
|
||||
mkdir installer
|
||||
|
||||
tar -xf ../../installer.tar -C installer
|
||||
|
||||
mkdir scripts
|
||||
|
||||
cp ../../scripts/on_env_start.sh scripts/
|
||||
cp ../../scripts/start.sh .
|
||||
cp ../../LICENSE .
|
||||
cp "../../CreativeML Open RAIL-M License" .
|
||||
cp "../../How to install and run.txt" .
|
||||
echo "" > scripts/install_status.txt
|
||||
|
||||
chmod u+x start.sh
|
||||
|
||||
echo "Build ready. Zip the 'dist/stable-diffusion-ui' folder."
|
||||
|
||||
echo "Cleaning up.."
|
||||
|
||||
cd ../..
|
||||
|
||||
rm -rf installer
|
||||
|
||||
rm installer.tar
|
18
developer_console.sh
Normal file
@ -0,0 +1,18 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ "$0" == "bash" ]; then
|
||||
echo "Opening Stable Diffusion UI - Developer Console.."
|
||||
echo ""
|
||||
|
||||
export SD_BASE_DIR=`pwd`
|
||||
export MAMBA_ROOT_PREFIX="$SD_BASE_DIR/env/mamba"
|
||||
export INSTALL_ENV_DIR="$SD_BASE_DIR/env/installer_env"
|
||||
export PROJECT_ENV_DIR="$SD_BASE_DIR/env/project_env"
|
||||
|
||||
eval "$($MAMBA_ROOT_PREFIX/micromamba shell hook -s posix)"
|
||||
|
||||
micromamba activate "$INSTALL_ENV_DIR"
|
||||
micromamba activate "$PROJECT_ENV_DIR"
|
||||
else
|
||||
bash --init-file developer_console.sh
|
||||
fi
|
@ -370,13 +370,7 @@ def do_mk_img(req: Request):
|
||||
|
||||
if req.stream_progress_updates:
|
||||
n_steps = opt_ddim_steps if req.init_image is None else t_enc
|
||||
progress = {
|
||||
"status": "progress",
|
||||
#"progress": (i + 1) / n_steps,
|
||||
"progress": {
|
||||
"step": i, "total_steps": n_steps
|
||||
}
|
||||
}
|
||||
progress = {"step": i, "total_steps": n_steps}
|
||||
|
||||
if req.stream_image_progress and i % 5 == 0:
|
||||
partial_images = []
|
237
engine/server.py
Normal file
@ -0,0 +1,237 @@
|
||||
import json
|
||||
import traceback
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
||||
SCRIPT_DIR = os.getcwd()
|
||||
print('started in ', SCRIPT_DIR)
|
||||
|
||||
SD_UI_DIR = os.getenv('SD_UI_PATH', None)
|
||||
sys.path.append(os.path.dirname(SD_UI_DIR))
|
||||
|
||||
CONFIG_DIR = os.path.join(SD_UI_DIR, '..', 'scripts')
|
||||
|
||||
OUTPUT_DIRNAME = "Stable Diffusion UI" # in the user's home folder
|
||||
|
||||
from fastapi import FastAPI, HTTPException
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
from starlette.responses import FileResponse, StreamingResponse
|
||||
from pydantic import BaseModel
|
||||
import logging
|
||||
|
||||
from sd_internal import Request, Response
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
model_loaded = False
|
||||
model_is_loading = False
|
||||
|
||||
modifiers_cache = None
|
||||
outpath = os.path.join(os.path.expanduser("~"), OUTPUT_DIRNAME)
|
||||
|
||||
# don't show access log entries for URLs that start with the given prefix
|
||||
ACCESS_LOG_SUPPRESS_PATH_PREFIXES = ['/ping', '/modifier-thumbnails']
|
||||
|
||||
app.mount('/media', StaticFiles(directory=os.path.join(SD_UI_DIR, 'media/')), name="media")
|
||||
|
||||
# defaults from https://huggingface.co/blog/stable_diffusion
|
||||
class ImageRequest(BaseModel):
|
||||
session_id: str = "session"
|
||||
prompt: str = ""
|
||||
negative_prompt: str = ""
|
||||
init_image: str = None # base64
|
||||
mask: str = None # base64
|
||||
num_outputs: int = 1
|
||||
num_inference_steps: int = 50
|
||||
guidance_scale: float = 7.5
|
||||
width: int = 512
|
||||
height: int = 512
|
||||
seed: int = 42
|
||||
prompt_strength: float = 0.8
|
||||
sampler: str = None # "ddim", "plms", "heun", "euler", "euler_a", "dpm2", "dpm2_a", "lms"
|
||||
# allow_nsfw: bool = False
|
||||
save_to_disk_path: str = None
|
||||
turbo: bool = True
|
||||
use_cpu: bool = False
|
||||
use_full_precision: bool = False
|
||||
use_face_correction: str = None # or "GFPGANv1.3"
|
||||
use_upscale: str = None # or "RealESRGAN_x4plus" or "RealESRGAN_x4plus_anime_6B"
|
||||
show_only_filtered_image: bool = False
|
||||
|
||||
stream_progress_updates: bool = False
|
||||
stream_image_progress: bool = False
|
||||
|
||||
class SetAppConfigRequest(BaseModel):
|
||||
update_branch: str = "main"
|
||||
|
||||
@app.get('/')
|
||||
def read_root():
|
||||
headers = {"Cache-Control": "no-cache, no-store, must-revalidate", "Pragma": "no-cache", "Expires": "0"}
|
||||
return FileResponse(os.path.join(SD_UI_DIR, 'index.html'), headers=headers)
|
||||
|
||||
@app.get('/ping')
|
||||
async def ping():
|
||||
global model_loaded, model_is_loading
|
||||
|
||||
try:
|
||||
if model_loaded:
|
||||
return {'OK'}
|
||||
|
||||
if model_is_loading:
|
||||
return {'ERROR'}
|
||||
|
||||
model_is_loading = True
|
||||
|
||||
from sd_internal import runtime
|
||||
|
||||
custom_weight_path = os.path.join(SCRIPT_DIR, 'custom-model.ckpt')
|
||||
ckpt_to_use = "sd-v1-4" if not os.path.exists(custom_weight_path) else "custom-model"
|
||||
runtime.load_model_ckpt(ckpt_to_use=ckpt_to_use)
|
||||
|
||||
model_loaded = True
|
||||
model_is_loading = False
|
||||
|
||||
return {'OK'}
|
||||
except Exception as e:
|
||||
print(traceback.format_exc())
|
||||
return HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
@app.post('/image')
|
||||
def image(req : ImageRequest):
|
||||
from sd_internal import runtime
|
||||
|
||||
r = Request()
|
||||
r.session_id = req.session_id
|
||||
r.prompt = req.prompt
|
||||
r.negative_prompt = req.negative_prompt
|
||||
r.init_image = req.init_image
|
||||
r.mask = req.mask
|
||||
r.num_outputs = req.num_outputs
|
||||
r.num_inference_steps = req.num_inference_steps
|
||||
r.guidance_scale = req.guidance_scale
|
||||
r.width = req.width
|
||||
r.height = req.height
|
||||
r.seed = req.seed
|
||||
r.prompt_strength = req.prompt_strength
|
||||
r.sampler = req.sampler
|
||||
# r.allow_nsfw = req.allow_nsfw
|
||||
r.turbo = req.turbo
|
||||
r.use_cpu = req.use_cpu
|
||||
r.use_full_precision = req.use_full_precision
|
||||
r.save_to_disk_path = req.save_to_disk_path
|
||||
r.use_upscale: str = req.use_upscale
|
||||
r.use_face_correction = req.use_face_correction
|
||||
r.show_only_filtered_image = req.show_only_filtered_image
|
||||
|
||||
r.stream_progress_updates = True # the underlying implementation only supports streaming
|
||||
r.stream_image_progress = req.stream_image_progress
|
||||
|
||||
try:
|
||||
if not req.stream_progress_updates:
|
||||
r.stream_image_progress = False
|
||||
|
||||
res = runtime.mk_img(r)
|
||||
|
||||
if req.stream_progress_updates:
|
||||
return StreamingResponse(res, media_type='application/json')
|
||||
else: # compatibility mode: buffer the streaming responses, and return the last one
|
||||
last_result = None
|
||||
|
||||
for result in res:
|
||||
last_result = result
|
||||
|
||||
return json.loads(last_result)
|
||||
except Exception as e:
|
||||
print(traceback.format_exc())
|
||||
return HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
@app.get('/image/stop')
|
||||
def stop():
|
||||
try:
|
||||
if model_is_loading:
|
||||
return {'ERROR'}
|
||||
|
||||
from sd_internal import runtime
|
||||
runtime.stop_processing = True
|
||||
|
||||
return {'OK'}
|
||||
except Exception as e:
|
||||
print(traceback.format_exc())
|
||||
return HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
@app.get('/image/tmp/{session_id}/{img_id}')
|
||||
def get_image(session_id, img_id):
|
||||
from sd_internal import runtime
|
||||
buf = runtime.temp_images[session_id + '/' + img_id]
|
||||
buf.seek(0)
|
||||
return StreamingResponse(buf, media_type='image/jpeg')
|
||||
|
||||
@app.post('/app_config')
|
||||
async def setAppConfig(req : SetAppConfigRequest):
|
||||
try:
|
||||
config = {
|
||||
'update_branch': req.update_branch
|
||||
}
|
||||
|
||||
config_json_str = json.dumps(config)
|
||||
config_bat_str = f'@set update_branch={req.update_branch}'
|
||||
config_sh_str = f'export update_branch={req.update_branch}'
|
||||
|
||||
config_json_path = os.path.join(CONFIG_DIR, 'config.json')
|
||||
config_bat_path = os.path.join(CONFIG_DIR, 'config.bat')
|
||||
config_sh_path = os.path.join(CONFIG_DIR, 'config.sh')
|
||||
|
||||
with open(config_json_path, 'w') as f:
|
||||
f.write(config_json_str)
|
||||
|
||||
with open(config_bat_path, 'w') as f:
|
||||
f.write(config_bat_str)
|
||||
|
||||
with open(config_sh_path, 'w') as f:
|
||||
f.write(config_sh_str)
|
||||
|
||||
return {'OK'}
|
||||
except Exception as e:
|
||||
print(traceback.format_exc())
|
||||
return HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
@app.get('/app_config')
|
||||
def getAppConfig():
|
||||
try:
|
||||
config_json_path = os.path.join(CONFIG_DIR, 'config.json')
|
||||
|
||||
if not os.path.exists(config_json_path):
|
||||
return HTTPException(status_code=500, detail="No config file")
|
||||
|
||||
with open(config_json_path, 'r') as f:
|
||||
config_json_str = f.read()
|
||||
config = json.loads(config_json_str)
|
||||
return config
|
||||
except Exception as e:
|
||||
print(traceback.format_exc())
|
||||
return HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
@app.get('/modifiers.json')
|
||||
def read_modifiers():
|
||||
headers = {"Cache-Control": "no-cache, no-store, must-revalidate", "Pragma": "no-cache", "Expires": "0"}
|
||||
return FileResponse(os.path.join(SD_UI_DIR, 'modifiers.json'), headers=headers)
|
||||
|
||||
@app.get('/output_dir')
|
||||
def read_home_dir():
|
||||
return {outpath}
|
||||
|
||||
# don't log certain requests
|
||||
class LogSuppressFilter(logging.Filter):
|
||||
def filter(self, record: logging.LogRecord) -> bool:
|
||||
path = record.getMessage()
|
||||
for prefix in ACCESS_LOG_SUPPRESS_PATH_PREFIXES:
|
||||
if path.find(prefix) != -1:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
logging.getLogger('uvicorn.access').addFilter(LogSuppressFilter())
|
||||
|
||||
# start the browser ui
|
||||
import webbrowser; webbrowser.open('http://localhost:9000')
|
BIN
installer/bin/micromamba_linux_arm64
Executable file
BIN
installer/bin/micromamba_linux_x64
Executable file
BIN
installer/bin/micromamba_mac_arm64
Executable file
BIN
installer/bin/micromamba_mac_x64
Executable file
BIN
installer/bin/micromamba_win_x64.exe
Normal file
34
installer/bootstrap/bootstrap.bat
Normal file
@ -0,0 +1,34 @@
|
||||
@echo off
|
||||
|
||||
@rem This file initializes micromamba and activates the env.
|
||||
@rem A similar bootstrap file needs to exist for each platform (win, linux, macOS)
|
||||
@rem Ready to hand-over to the platform-independent installer after this (written in python).
|
||||
|
||||
set MAMBA_ROOT_PREFIX=%SD_BASE_DIR%\env\mamba
|
||||
set INSTALL_ENV_DIR=%SD_BASE_DIR%\env\installer_env
|
||||
set INSTALLER_YAML_FILE=%SD_BASE_DIR%\installer\yaml\installer-environment.yaml
|
||||
set MICROMAMBA_BINARY_FILE=%SD_BASE_DIR%\installer\bin\micromamba_win_x64.exe
|
||||
|
||||
@rem initialize the mamba dir
|
||||
if not exist "%MAMBA_ROOT_PREFIX%" mkdir "%MAMBA_ROOT_PREFIX%"
|
||||
|
||||
copy "%MICROMAMBA_BINARY_FILE%" "%MAMBA_ROOT_PREFIX%\micromamba.exe"
|
||||
|
||||
@rem test the mamba binary
|
||||
echo Micromamba version:
|
||||
call "%MAMBA_ROOT_PREFIX%\micromamba.exe" --version
|
||||
|
||||
@rem run the shell hook
|
||||
if not exist "%MAMBA_ROOT_PREFIX%\Scripts" (
|
||||
call "%MAMBA_ROOT_PREFIX%\micromamba.exe" shell hook --log-level 4 -s cmd.exe
|
||||
)
|
||||
|
||||
call "%MAMBA_ROOT_PREFIX%\condabin\mamba_hook.bat"
|
||||
|
||||
@rem create the installer env
|
||||
if not exist "%INSTALL_ENV_DIR%" (
|
||||
call micromamba create -y --prefix "%INSTALL_ENV_DIR%" -f "%INSTALLER_YAML_FILE%"
|
||||
)
|
||||
|
||||
@rem activate
|
||||
call micromamba activate "%INSTALL_ENV_DIR%"
|
44
installer/bootstrap/bootstrap.sh
Executable file
@ -0,0 +1,44 @@
|
||||
#!/bin/bash
|
||||
|
||||
# This file initializes micromamba and activates the env.
|
||||
# A similar bootstrap file needs to exist for each platform (win, linux, macOS)
|
||||
# Ready to hand-over to the platform-independent installer after this (written in python).
|
||||
|
||||
OS_NAME=$(uname -s)
|
||||
case "${OS_NAME}" in
|
||||
Linux*) OS_NAME="linux";;
|
||||
Darwin*) OS_NAME="mac";;
|
||||
*) echo "Unknown OS: $OS_NAME! This only runs on Linux or Mac" && exit
|
||||
esac
|
||||
|
||||
OS_ARCH=$(uname -m)
|
||||
case "${OS_ARCH}" in
|
||||
x86_64*) OS_ARCH="x64";;
|
||||
arm64*) OS_ARCH="arm64";;
|
||||
*) echo "Unknown system architecture: $OS_ARCH! This only runs on x86_64 or arm64" && exit
|
||||
esac
|
||||
|
||||
export MAMBA_ROOT_PREFIX=$SD_BASE_DIR/env/mamba
|
||||
INSTALL_ENV_DIR=$SD_BASE_DIR/env/installer_env
|
||||
INSTALLER_YAML_FILE=$SD_BASE_DIR/installer/yaml/installer-environment.yaml
|
||||
MICROMAMBA_BINARY_FILE=$SD_BASE_DIR/installer/bin/micromamba_${OS_NAME}_${OS_ARCH}
|
||||
|
||||
# initialize the mamba dir
|
||||
mkdir -p "$MAMBA_ROOT_PREFIX"
|
||||
|
||||
cp "$MICROMAMBA_BINARY_FILE" "$MAMBA_ROOT_PREFIX/micromamba"
|
||||
|
||||
# test the mamba binary
|
||||
echo "Micromamba version:"
|
||||
"$MAMBA_ROOT_PREFIX/micromamba" --version
|
||||
|
||||
# run the shell hook
|
||||
eval "$($MAMBA_ROOT_PREFIX/micromamba shell hook -s posix)"
|
||||
|
||||
# create the installer env
|
||||
if [ ! -e "$INSTALL_ENV_DIR" ]; then
|
||||
micromamba create -y --prefix "$INSTALL_ENV_DIR" -f "$INSTALLER_YAML_FILE"
|
||||
fi
|
||||
|
||||
# activate
|
||||
micromamba activate "$INSTALL_ENV_DIR"
|
21
installer/bootstrap/check-install-dir.bat
Normal file
@ -0,0 +1,21 @@
|
||||
@echo off
|
||||
|
||||
if exist "%SD_BASE_DIR%\env" exit /b
|
||||
|
||||
set suggested_dir=%~d0\stable-diffusion-ui
|
||||
|
||||
echo "Please install Stable Diffusion UI at the root of your drive. This avoids problems with path length limits in Windows." & echo.
|
||||
set /p answer="Press Enter to install at %suggested_dir%, or type 'c' (without quotes) to install at the current location (press enter or type 'c'): "
|
||||
|
||||
if /i "%answer:~,1%" NEQ "c" (
|
||||
if exist "%suggested_dir%" (
|
||||
echo. & echo "Sorry, %suggested_dir% already exists! Cannot overwrite that folder!" & echo.
|
||||
pause
|
||||
exit
|
||||
)
|
||||
|
||||
xcopy "%SD_BASE_DIR%" "%suggested_dir%" /s /i /Y /Q
|
||||
echo Please run the %START_CMD_FILENAME% file inside %suggested_dir% . Do not use this folder anymore > "%SD_BASE_DIR%/READ_ME - DO_NOT_USE_THIS_FOLDER.txt"
|
||||
|
||||
cd %suggested_dir%
|
||||
)
|
78
installer/developer/enable_dev_mode.py
Normal file
@ -0,0 +1,78 @@
|
||||
import argparse
|
||||
import subprocess
|
||||
import sys
|
||||
import json
|
||||
import os
|
||||
import platform
|
||||
import shutil
|
||||
|
||||
config_path = os.path.join('config.json')
|
||||
|
||||
if not os.path.exists('LICENSE'):
|
||||
print('Error: This script needs to be run from the root of the stable-diffusion-ui folder! Please cd to the correct folder, and run this again.')
|
||||
exit(1)
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
|
||||
parser.add_argument(
|
||||
"--symlink_dir", type=str, default=None, help="the absolute path to the project git repository (to link to)"
|
||||
)
|
||||
opt = parser.parse_args()
|
||||
|
||||
def run(cmd):
|
||||
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True)
|
||||
|
||||
for c in iter(lambda: p.stdout.read(1), b""):
|
||||
sys.stdout.buffer.write(c)
|
||||
sys.stdout.flush()
|
||||
|
||||
p.wait()
|
||||
|
||||
return p.returncode == 0
|
||||
|
||||
def get_config():
|
||||
if not os.path.exists(config_path):
|
||||
return {}
|
||||
|
||||
with open(config_path, "r") as f:
|
||||
return json.load(f)
|
||||
|
||||
def save_config(config):
|
||||
with open(config_path, "w") as f:
|
||||
json.dump(config, f)
|
||||
|
||||
# set the `is_developer_mode` flag to `true` in the config
|
||||
config = get_config()
|
||||
config['is_developer_mode'] = True
|
||||
save_config(config)
|
||||
|
||||
print('set is_developer_mode=true in config.json')
|
||||
|
||||
# make the symlink, if requested
|
||||
if opt.symlink_dir is not None:
|
||||
if not os.path.exists(opt.symlink_dir):
|
||||
print(f'Symlink directory "{opt.symlink_dir}" was not found! Are you sure it has been escaped correctly?')
|
||||
exit(1)
|
||||
|
||||
installer_target_path = os.path.join(opt.symlink_dir, 'installer')
|
||||
ui_target_path = os.path.join(opt.symlink_dir, 'ui')
|
||||
engine_target_path = os.path.join(opt.symlink_dir, 'engine')
|
||||
|
||||
shutil.rmtree('installer', ignore_errors=True)
|
||||
shutil.rmtree('ui', ignore_errors=True)
|
||||
shutil.rmtree('engine', ignore_errors=True)
|
||||
|
||||
if not os.path.exists(ui_target_path) or not os.path.exists(installer_target_path) or not os.path.exists(engine_target_path):
|
||||
print('The target symlink directory does not contain the required {ui, installer, engine} folders. Are you sure it is the correct git repo for the project?')
|
||||
exit(1)
|
||||
|
||||
if platform.system() == 'Windows':
|
||||
run(f'mklink /J "installer" "{installer_target_path}"')
|
||||
run(f'mklink /J "ui" "{ui_target_path}"')
|
||||
run(f'mklink /J "engine" "{engine_target_path}"')
|
||||
elif platform.system() in ('Linux', 'Darwin'):
|
||||
run(f'ln -s "{installer_target_path}" "installer"')
|
||||
run(f'ln -s "{ui_target_path}" "ui"')
|
||||
run(f'ln -s "{engine_target_path}" "engine"')
|
||||
|
||||
print(f'Created symlinks! Your installation will now automatically use the files present in the repository at {opt.symlink_dir}')
|
0
installer/installer/__init__.py
Normal file
70
installer/installer/app.py
Normal file
@ -0,0 +1,70 @@
|
||||
import os
|
||||
import json
|
||||
import platform
|
||||
|
||||
# config
|
||||
PROJECT_REPO_URL = 'https://github.com/cmdr2/stable-diffusion-ui.git'
|
||||
DEFAULT_PROJECT_BRANCH = 'installer_new'
|
||||
PROJECT_REPO_DIR_NAME = 'project_repo'
|
||||
|
||||
STABLE_DIFFUSION_REPO_URL = 'https://github.com/basujindal/stable-diffusion.git'
|
||||
DEFAULT_STABLE_DIFFUSION_COMMIT = 'f6cfebffa752ee11a7b07497b8529d5971de916c'
|
||||
STABLE_DIFFUSION_REPO_DIR_NAME = 'stable-diffusion'
|
||||
|
||||
PROJECT_ENV_DIR_NAME = 'project_env'
|
||||
|
||||
START_CMD_FILE_NAME = "Start Stable Diffusion UI.cmd" if platform.system() == "Windows" else "start.sh"
|
||||
DEV_CONSOLE_CMD_FILE_NAME = "Developer Console.cmd" if platform.system() == "Windows" else "developer_console.sh"
|
||||
CONFIG_FILE_NAME = 'config.json'
|
||||
|
||||
# top-level folders
|
||||
ENV_DIR_NAME = 'env'
|
||||
MODELS_DIR_NAME = 'models'
|
||||
|
||||
INSTALLER_DIR_NAME = 'installer'
|
||||
UI_DIR_NAME = 'ui'
|
||||
ENGINE_DIR_NAME = 'engine'
|
||||
|
||||
|
||||
# env
|
||||
SD_BASE_DIR = os.environ['SD_BASE_DIR']
|
||||
|
||||
|
||||
# model folders
|
||||
STABLE_DIFFUSION_MODELS_DIR_NAME = "stable-diffusion"
|
||||
GFPGAN_MODELS_DIR_NAME = "gfpgan"
|
||||
RealESRGAN_MODELS_DIR_NAME = "realesrgan"
|
||||
|
||||
# create references to dirs
|
||||
env_dir_path = os.path.join(SD_BASE_DIR, ENV_DIR_NAME)
|
||||
|
||||
installer_dir_path = os.path.join(SD_BASE_DIR, INSTALLER_DIR_NAME)
|
||||
ui_dir_path = os.path.join(SD_BASE_DIR, UI_DIR_NAME)
|
||||
engine_dir_path = os.path.join(SD_BASE_DIR, ENGINE_DIR_NAME)
|
||||
|
||||
project_repo_dir_path = os.path.join(env_dir_path, PROJECT_REPO_DIR_NAME)
|
||||
stable_diffusion_repo_dir_path = os.path.join(env_dir_path, STABLE_DIFFUSION_REPO_DIR_NAME)
|
||||
|
||||
project_env_dir_path = os.path.join(env_dir_path, PROJECT_ENV_DIR_NAME)
|
||||
|
||||
patches_dir_path = os.path.join(installer_dir_path, 'patches')
|
||||
|
||||
models_dir_path = os.path.join(SD_BASE_DIR, MODELS_DIR_NAME)
|
||||
stable_diffusion_models_dir_path = os.path.join(models_dir_path, STABLE_DIFFUSION_MODELS_DIR_NAME)
|
||||
gfpgan_models_dir_path = os.path.join(models_dir_path, GFPGAN_MODELS_DIR_NAME)
|
||||
realesrgan_models_dir_path = os.path.join(models_dir_path, RealESRGAN_MODELS_DIR_NAME)
|
||||
|
||||
|
||||
# useful functions
|
||||
def get_config():
|
||||
config_path = os.path.join(SD_BASE_DIR, CONFIG_FILE_NAME)
|
||||
if not os.path.exists(config_path):
|
||||
return {}
|
||||
|
||||
with open(config_path, "r") as f:
|
||||
return json.load(f)
|
||||
|
||||
|
||||
# app context
|
||||
config = get_config()
|
||||
activated_env_dir_path = None
|
18
installer/installer/check_modules.py
Normal file
@ -0,0 +1,18 @@
|
||||
'''
|
||||
This script is run by the `installer.helpers.modules_exist_in_env()` function
|
||||
'''
|
||||
|
||||
import sys
|
||||
import pkgutil
|
||||
|
||||
modules = sys.argv[1:]
|
||||
missing_modules = []
|
||||
for m in modules:
|
||||
if pkgutil.find_loader(m) is None:
|
||||
missing_modules.append(m)
|
||||
|
||||
if len(missing_modules) == 0:
|
||||
print('42')
|
||||
exit()
|
||||
|
||||
print('Missing modules', missing_modules)
|
80
installer/installer/helpers.py
Normal file
@ -0,0 +1,80 @@
|
||||
import os
|
||||
from os import path
|
||||
import subprocess
|
||||
import traceback
|
||||
|
||||
from installer import app
|
||||
|
||||
def run(cmd, run_in_folder=None, env=None, get_output=False, log_the_cmd=False):
|
||||
if app.activated_env_dir_path is not None and 'micromamba activate' not in cmd:
|
||||
cmd = f'micromamba activate "{app.activated_env_dir_path}" && {cmd}'
|
||||
|
||||
if run_in_folder is not None:
|
||||
cmd = f'cd "{run_in_folder}" && {cmd}'
|
||||
|
||||
if log_the_cmd:
|
||||
log('running: ' + cmd)
|
||||
|
||||
if get_output:
|
||||
p = subprocess.Popen(cmd, shell=True, env=env, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||
else:
|
||||
p = subprocess.Popen(cmd, shell=True, env=env)
|
||||
|
||||
out, err = p.communicate()
|
||||
|
||||
out = out.decode('utf-8') if isinstance(out, bytes) else out
|
||||
err = err.decode('utf-8') if isinstance(out, bytes) else err
|
||||
|
||||
if get_output:
|
||||
return out, err
|
||||
|
||||
def log(msg):
|
||||
print(msg)
|
||||
|
||||
def modules_exist_in_env(modules, env_dir_path=app.project_env_dir_path):
|
||||
if not path.exists(env_dir_path):
|
||||
return False
|
||||
|
||||
check_modules_script_path = path.join(app.installer_dir_path, 'installer', 'check_modules.py')
|
||||
module_args = ' '.join(modules)
|
||||
check_modules_cmd = f'python "{check_modules_script_path}" {module_args}'
|
||||
|
||||
env = os.environ.copy()
|
||||
env['PYTHONPATH'] = app.stable_diffusion_repo_dir_path + ';' + os.path.join(app.project_env_dir_path, 'lib', 'site-packages')
|
||||
|
||||
if app.activated_env_dir_path != env_dir_path:
|
||||
activate_cmd = f'micromamba activate "{env_dir_path}"'
|
||||
check_modules_cmd = f'{activate_cmd} && {check_modules_cmd}'
|
||||
|
||||
# activate and run the modules checker
|
||||
output, _ = run(check_modules_cmd, get_output=True, env=env)
|
||||
if 'Missing' in output:
|
||||
log(output)
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def fail_with_install_error(error_msg):
|
||||
try:
|
||||
log(traceback.format_stack())
|
||||
log(f'''
|
||||
|
||||
Error: {error_msg}. Sorry about that, please try to:
|
||||
1. Run this installer again.
|
||||
2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/blob/main/Troubleshooting.md
|
||||
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
|
||||
4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues
|
||||
Thanks!''')
|
||||
except:
|
||||
pass
|
||||
|
||||
exit(1)
|
||||
|
||||
def apply_git_patches(repo_dir_path, patch_file_names):
|
||||
is_developer_mode = app.config.get('is_developer_mode', False)
|
||||
if is_developer_mode:
|
||||
return
|
||||
|
||||
for patch_file_name in patch_file_names:
|
||||
patch_file_path = path.join(app.patches_dir_path, patch_file_name)
|
||||
run(f"git apply {patch_file_path}", run_in_folder=repo_dir_path)
|
34
installer/installer/main.py
Normal file
@ -0,0 +1,34 @@
|
||||
import os
|
||||
import sys
|
||||
from datetime import datetime
|
||||
|
||||
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
|
||||
|
||||
from installer import helpers
|
||||
from installer.tasks import (
|
||||
fetch_project_repo,
|
||||
apply_project_update,
|
||||
fetch_stable_diffusion_repo,
|
||||
install_stable_diffusion_packages,
|
||||
install_ui_packages,
|
||||
download_weights,
|
||||
start_ui_server,
|
||||
)
|
||||
|
||||
tasks = [
|
||||
fetch_project_repo,
|
||||
apply_project_update,
|
||||
fetch_stable_diffusion_repo,
|
||||
install_stable_diffusion_packages,
|
||||
install_ui_packages,
|
||||
download_weights,
|
||||
start_ui_server,
|
||||
]
|
||||
|
||||
helpers.log(f'Starting Stable Diffusion UI at {datetime.now().strftime("%d/%m/%Y %H:%M:%S")}')
|
||||
|
||||
def run_tasks():
|
||||
for task in tasks:
|
||||
task.run()
|
||||
|
||||
run_tasks()
|
8
installer/installer/start.bat
Normal file
@ -0,0 +1,8 @@
|
||||
@echo off
|
||||
rem Never edit this file. If you really, really have to, beware that a script doesn't like
|
||||
rem being overwritten while it is running (the auto-updater will do that).
|
||||
rem The trick is to update this file while another script is running, and vice versa.
|
||||
|
||||
call python %SD_BASE_DIR%\installer\installer\main.py
|
||||
|
||||
pause
|
9
installer/installer/start.sh
Executable file
@ -0,0 +1,9 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Never edit this file. If you really, really have to, beware that a script doesn't like
|
||||
# being overwritten while it is running (the auto-updater will do that).
|
||||
# The trick is to update this file while another script is running, and vice versa.
|
||||
|
||||
python $SD_BASE_DIR/installer/installer/main.py
|
||||
|
||||
read -p "Press enter to continue"
|
0
installer/installer/tasks/__init__.py
Normal file
30
installer/installer/tasks/apply_project_update.py
Normal file
@ -0,0 +1,30 @@
|
||||
from os import path
|
||||
import shutil
|
||||
|
||||
from installer import app
|
||||
|
||||
def run():
|
||||
is_developer_mode = app.config.get('is_developer_mode', False)
|
||||
if is_developer_mode:
|
||||
return
|
||||
|
||||
installer_src_path = path.join(app.project_repo_dir_path, 'installer')
|
||||
ui_src_path = path.join(app.project_repo_dir_path, 'ui')
|
||||
engine_src_path = path.join(app.project_repo_dir_path, 'engine')
|
||||
|
||||
start_cmd_src_path = path.join(app.project_repo_dir_path, app.START_CMD_FILE_NAME)
|
||||
start_cmd_dst_path = path.join(app.SD_BASE_DIR, app.START_CMD_FILE_NAME)
|
||||
|
||||
dev_console_cmd_src_path = path.join(app.project_repo_dir_path, app.DEV_CONSOLE_CMD_FILE_NAME)
|
||||
dev_console_cmd_dst_path = path.join(app.SD_BASE_DIR, app.DEV_CONSOLE_CMD_FILE_NAME)
|
||||
|
||||
shutil.rmtree(app.installer_dir_path, ignore_errors=True)
|
||||
shutil.rmtree(app.ui_dir_path, ignore_errors=True)
|
||||
shutil.rmtree(app.engine_dir_path, ignore_errors=True)
|
||||
|
||||
shutil.copytree(installer_src_path, app.installer_dir_path, dirs_exist_ok=True)
|
||||
shutil.copytree(ui_src_path, app.ui_dir_path, dirs_exist_ok=True)
|
||||
shutil.copytree(engine_src_path, app.engine_dir_path, dirs_exist_ok=True)
|
||||
|
||||
shutil.copy(start_cmd_src_path, start_cmd_dst_path)
|
||||
shutil.copy(dev_console_cmd_src_path, dev_console_cmd_dst_path)
|
46
installer/installer/tasks/download_weights.py
Normal file
@ -0,0 +1,46 @@
|
||||
import os
|
||||
|
||||
from installer import app, helpers
|
||||
|
||||
def run():
|
||||
fetch_model('Stable Diffusion', 'sd-v1-4.ckpt', model_dir_path=app.stable_diffusion_models_dir_path, download_url='https://me.cmdr2.org/stable-diffusion-ui/sd-v1-4.ckpt', expected_file_sizes=[4265380512, 7703807346, 7703810927])
|
||||
fetch_model('Face Correction (GFPGAN)', 'GFPGANv1.4.pth', model_dir_path=app.gfpgan_models_dir_path, download_url='https://github.com/TencentARC/GFPGAN/releases/download/v1.3.4/GFPGANv1.4.pth', expected_file_sizes=[348632874])
|
||||
fetch_model('Resolution Upscale (RealESRGAN x4)', 'RealESRGAN_x4plus.pth', model_dir_path=app.realesrgan_models_dir_path, download_url='https://github.com/xinntao/Real-ESRGAN/releases/download/v0.1.0/RealESRGAN_x4plus.pth', expected_file_sizes=[67040989])
|
||||
fetch_model('Resolution Upscale (RealESRGAN x4_anime)', 'RealESRGAN_x4plus_anime_6B.pth', model_dir_path=app.realesrgan_models_dir_path, download_url='https://github.com/xinntao/Real-ESRGAN/releases/download/v0.2.2.4/RealESRGAN_x4plus_anime_6B.pth', expected_file_sizes=[17938799])
|
||||
|
||||
def fetch_model(model_type, file_name, model_dir_path, download_url, expected_file_sizes):
|
||||
os.makedirs(model_dir_path, exist_ok=True)
|
||||
|
||||
file_path = os.path.join(model_dir_path, file_name)
|
||||
|
||||
if model_exists(file_name, file_path, expected_file_sizes):
|
||||
helpers.log(f'Data files (weights) necessary for {model_type} were already downloaded')
|
||||
return
|
||||
|
||||
helpers.log(f'Downloading data files (weights) for {model_type}..')
|
||||
|
||||
helpers.run(f'curl -L -k "{download_url}" > "{file_path}"', log_the_cmd=True)
|
||||
|
||||
def model_exists(file_name, file_path, expected_file_sizes):
|
||||
legacy_file_path = os.path.join(app.stable_diffusion_repo_dir_path, file_name)
|
||||
|
||||
file_exists = os.path.exists(file_path)
|
||||
legacy_file_exists = os.path.exists(legacy_file_path)
|
||||
|
||||
if legacy_file_exists:
|
||||
file_size = os.path.getsize(legacy_file_path)
|
||||
if file_size in expected_file_sizes:
|
||||
return True
|
||||
|
||||
helpers.log(f'{file_name} is invalid. Was only {file_size} bytes in size. Downloading again..')
|
||||
os.remove(legacy_file_path)
|
||||
|
||||
if file_exists:
|
||||
file_size = os.path.getsize(file_path)
|
||||
if file_size in expected_file_sizes:
|
||||
return True
|
||||
|
||||
helpers.log(f'{file_name} is invalid. Was only {file_size} bytes in size. Downloading again..')
|
||||
os.remove(file_path)
|
||||
|
||||
return False
|
27
installer/installer/tasks/fetch_project_repo.py
Normal file
@ -0,0 +1,27 @@
|
||||
from os import path
|
||||
|
||||
from installer import app, helpers
|
||||
|
||||
project_repo_git_path = path.join(app.project_repo_dir_path, '.git')
|
||||
|
||||
def run():
|
||||
branch_name = app.config.get('update_branch', app.DEFAULT_PROJECT_BRANCH)
|
||||
|
||||
if path.exists(project_repo_git_path):
|
||||
helpers.log(f"Stable Diffusion UI's git repository was already installed. Updating from {branch_name}..")
|
||||
|
||||
helpers.run("git reset --hard", run_in_folder=app.project_repo_dir_path)
|
||||
helpers.run(f'git -c advice.detachedHead=false checkout "{branch_name}"', run_in_folder=app.project_repo_dir_path)
|
||||
helpers.run("git pull", run_in_folder=app.project_repo_dir_path)
|
||||
else:
|
||||
helpers.log("\nDownloading Stable Diffusion UI..\n")
|
||||
helpers.log(f"Using the {branch_name} channel\n")
|
||||
|
||||
helpers.run(f'git clone {app.PROJECT_REPO_URL} "{app.project_repo_dir_path}"')
|
||||
|
||||
if path.exists(project_repo_git_path):
|
||||
helpers.log("Downloaded Stable Diffusion UI")
|
||||
else:
|
||||
helpers.fail_with_install_error(error_msg="Could not download Stable Diffusion UI")
|
||||
|
||||
helpers.run(f'git -c advice.detachedHead=false checkout "{branch_name}"', run_in_folder=app.project_repo_dir_path)
|
37
installer/installer/tasks/fetch_stable_diffusion_repo.py
Normal file
@ -0,0 +1,37 @@
|
||||
from os import path
|
||||
|
||||
from installer import app, helpers
|
||||
|
||||
stable_diffusion_repo_git_path = path.join(app.stable_diffusion_repo_dir_path, '.git')
|
||||
|
||||
is_developer_mode = app.config.get('is_developer_mode', False)
|
||||
|
||||
def run():
|
||||
fetch_repo()
|
||||
|
||||
helpers.apply_git_patches(app.stable_diffusion_repo_dir_path, patch_file_names=(
|
||||
"sd_custom.patch",
|
||||
))
|
||||
|
||||
def fetch_repo():
|
||||
commit_id = app.config.get('stable_diffusion_commit', app.DEFAULT_STABLE_DIFFUSION_COMMIT)
|
||||
|
||||
if path.exists(stable_diffusion_repo_git_path):
|
||||
helpers.log(f"Stable Diffusion's git repository was already installed. Using commit: {commit_id}..")
|
||||
|
||||
if not is_developer_mode:
|
||||
helpers.run("git reset --hard", run_in_folder=app.stable_diffusion_repo_dir_path)
|
||||
helpers.run("git fetch origin", run_in_folder=app.stable_diffusion_repo_dir_path)
|
||||
helpers.run(f'git -c advice.detachedHead=false checkout "{commit_id}"', run_in_folder=app.stable_diffusion_repo_dir_path)
|
||||
else:
|
||||
helpers.log("\nDownloading Stable Diffusion..\n")
|
||||
helpers.log(f"Using commit: {commit_id}\n")
|
||||
|
||||
helpers.run(f'git clone {app.STABLE_DIFFUSION_REPO_URL} "{app.stable_diffusion_repo_dir_path}"')
|
||||
|
||||
if path.exists(stable_diffusion_repo_git_path):
|
||||
helpers.log("Downloaded Stable Diffusion")
|
||||
else:
|
||||
helpers.fail_with_install_error(error_msg="Could not download Stable Diffusion")
|
||||
|
||||
helpers.run(f'git -c advice.detachedHead=false checkout "{commit_id}"', run_in_folder=app.stable_diffusion_repo_dir_path)
|
@ -0,0 +1,59 @@
|
||||
import os
|
||||
import platform
|
||||
import shutil
|
||||
|
||||
from installer import app, helpers
|
||||
|
||||
def run():
|
||||
environment_file_path = get_environment_file_path()
|
||||
local_env_file_path = os.path.join(app.stable_diffusion_repo_dir_path, 'environment.yaml')
|
||||
|
||||
shutil.copy(environment_file_path, local_env_file_path)
|
||||
|
||||
if is_valid_env():
|
||||
helpers.log("Packages necessary for Stable Diffusion were already installed")
|
||||
return
|
||||
|
||||
log_installing_header()
|
||||
|
||||
env = os.environ.copy()
|
||||
env['PYTHONNOUSERSITE'] = '1'
|
||||
|
||||
if not os.path.exists(app.project_env_dir_path):
|
||||
helpers.run(f'micromamba create --prefix {app.project_env_dir_path}', log_the_cmd=True)
|
||||
|
||||
helpers.run(f'micromamba install -y --prefix {app.project_env_dir_path} -f {local_env_file_path}', env=env, log_the_cmd=True, run_in_folder=app.stable_diffusion_repo_dir_path)
|
||||
|
||||
if is_valid_env():
|
||||
helpers.log("Installed the packages necessary for Stable Diffusion")
|
||||
|
||||
app.activated_env_dir_path = app.project_env_dir_path # so that future `run()` invocations will run in the activated env
|
||||
else:
|
||||
helpers.fail_with_install_error(error_msg="Could not install the packages necessary for Stable Diffusion")
|
||||
|
||||
apply_patches()
|
||||
|
||||
def apply_patches():
|
||||
gfpgan_repo_dir_path = os.path.join(app.stable_diffusion_repo_dir_path, 'src', 'gfpgan')
|
||||
helpers.apply_git_patches(gfpgan_repo_dir_path, patch_file_names=(
|
||||
"gfpgan_custom.patch",
|
||||
))
|
||||
|
||||
def get_environment_file_path():
|
||||
environment_file_name = 'sd-environment-win-linux-nvidia.yaml'
|
||||
if platform.system() == 'Darwin':
|
||||
environment_file_name = 'sd-environment-mac-nvidia.yaml'
|
||||
|
||||
return os.path.join(app.installer_dir_path, 'yaml', environment_file_name)
|
||||
|
||||
def log_installing_header():
|
||||
helpers.log('''
|
||||
|
||||
Downloading packages necessary for Stable Diffusion..
|
||||
|
||||
***** !! This will take some time (depending on the speed of the Internet connection) and may appear to be stuck, but please be patient *****
|
||||
|
||||
''')
|
||||
|
||||
def is_valid_env():
|
||||
return helpers.modules_exist_in_env(('torch', 'antlr4', 'transformers', 'numpy', 'gfpgan', 'realesrgan', 'basicsr'))
|
39
installer/installer/tasks/install_ui_packages.py
Normal file
@ -0,0 +1,39 @@
|
||||
import os
|
||||
import shutil
|
||||
import platform
|
||||
|
||||
from installer import app, helpers
|
||||
|
||||
def run():
|
||||
if is_valid_env():
|
||||
helpers.log("Packages necessary for Stable Diffusion UI were already installed")
|
||||
return
|
||||
|
||||
log_installing_header()
|
||||
|
||||
env = os.environ.copy()
|
||||
env['PYTHONNOUSERSITE'] = '1'
|
||||
|
||||
helpers.run(f'micromamba install -y --prefix {app.project_env_dir_path} -c conda-forge uvicorn fastapi', env=env, log_the_cmd=True)
|
||||
|
||||
if is_valid_env():
|
||||
helpers.log("Installed the packages necessary for Stable Diffusion UI")
|
||||
else:
|
||||
helpers.fail_with_install_error(error_msg="Could not install the packages necessary for Stable Diffusion UI")
|
||||
|
||||
def log_installing_header():
|
||||
helpers.log('''
|
||||
|
||||
Downloading packages necessary for Stable Diffusion UI..
|
||||
|
||||
''')
|
||||
|
||||
def is_valid_env():
|
||||
path = os.environ['PATH']
|
||||
path += ';' + os.path.join(app.project_env_dir_path, 'Scripts' if platform.system() == 'Windows' else 'bin')
|
||||
|
||||
if shutil.which("uvicorn", path=path) is None:
|
||||
helpers.log("uvicorn not found!")
|
||||
return False
|
||||
|
||||
return helpers.modules_exist_in_env(('uvicorn', 'fastapi'))
|
23
installer/installer/tasks/start_ui_server.py
Normal file
@ -0,0 +1,23 @@
|
||||
import os
|
||||
import platform
|
||||
|
||||
from installer import app, helpers
|
||||
|
||||
def run():
|
||||
helpers.log("\nStable Diffusion is ready!\n")
|
||||
|
||||
env = os.environ.copy()
|
||||
env['SD_DIR'] = app.stable_diffusion_repo_dir_path
|
||||
env['PYTHONPATH'] = app.stable_diffusion_repo_dir_path + ';' + os.path.join(app.project_env_dir_path, 'lib', 'site-packages')
|
||||
env['SD_UI_PATH'] = app.ui_dir_path
|
||||
env['PATH'] += ';' + os.path.join(app.project_env_dir_path, 'Scripts' if platform.system() == 'Windows' else 'bin')
|
||||
|
||||
helpers.log(f'PYTHONPATH={env["PYTHONPATH"]}')
|
||||
helpers.run('python --version', log_the_cmd=True)
|
||||
|
||||
host = app.config.get('host', 'localhost')
|
||||
port = app.config.get('port', '9000')
|
||||
|
||||
ui_server_cmd = f'uvicorn server:app --app-dir "{app.ui_dir_path}" --port {port} --host {host}'
|
||||
|
||||
helpers.run(ui_server_cmd, run_in_folder=app.stable_diffusion_repo_dir_path, log_the_cmd=True, env=env)
|
22
installer/patches/gfpgan_custom.patch
Normal file
@ -0,0 +1,22 @@
|
||||
diff --git a/gfpgan/utils.py b/gfpgan/utils.py
|
||||
index 74ee5a8..1357f48 100644
|
||||
--- a/gfpgan/utils.py
|
||||
+++ b/gfpgan/utils.py
|
||||
@@ -117,14 +117,14 @@ class GFPGANer():
|
||||
# face restoration
|
||||
for cropped_face in self.face_helper.cropped_faces:
|
||||
# prepare data
|
||||
- cropped_face_t = img2tensor(cropped_face / 255., bgr2rgb=True, float32=True)
|
||||
+ cropped_face_t = img2tensor(cropped_face / 255., bgr2rgb=False, float32=True)
|
||||
normalize(cropped_face_t, (0.5, 0.5, 0.5), (0.5, 0.5, 0.5), inplace=True)
|
||||
cropped_face_t = cropped_face_t.unsqueeze(0).to(self.device)
|
||||
|
||||
try:
|
||||
- output = self.gfpgan(cropped_face_t, return_rgb=False, weight=weight)[0]
|
||||
+ output = self.gfpgan(cropped_face_t, return_rgb=True, weight=weight)[0]
|
||||
# convert to image
|
||||
- restored_face = tensor2img(output.squeeze(0), rgb2bgr=True, min_max=(-1, 1))
|
||||
+ restored_face = tensor2img(output.squeeze(0), rgb2bgr=False, min_max=(-1, 1))
|
||||
except RuntimeError as error:
|
||||
print(f'\tFailed inference for GFPGAN: {error}.')
|
||||
restored_face = cropped_face
|
@ -3,5 +3,5 @@ channels:
|
||||
- defaults
|
||||
- conda-forge
|
||||
dependencies:
|
||||
- conda
|
||||
- git
|
||||
- python=3.10.5
|
47
installer/yaml/sd-environment-mac-nvidia.yaml
Normal file
@ -0,0 +1,47 @@
|
||||
name: ldm
|
||||
channels:
|
||||
- pytorch
|
||||
- conda-forge
|
||||
dependencies:
|
||||
- python==3.10.5
|
||||
- pip==22.2.2
|
||||
|
||||
- pytorch
|
||||
- torchvision
|
||||
|
||||
- albumentations==1.2.1
|
||||
- coloredlogs==15.0.1
|
||||
- einops==0.4.1
|
||||
- grpcio==1.46.4
|
||||
- humanfriendly==10.0
|
||||
- imageio==2.21.2
|
||||
- imageio-ffmpeg==0.4.7
|
||||
- imgaug==0.4.0
|
||||
- kornia==0.6.7
|
||||
- mpmath==1.2.1
|
||||
- nomkl
|
||||
- numpy==1.23.2
|
||||
- omegaconf==2.1.1
|
||||
- onnx==1.12.0
|
||||
- onnxruntime==1.12.1
|
||||
- pudb==2022.1
|
||||
- pytorch-lightning==1.6.5
|
||||
- scipy==1.9.1
|
||||
- streamlit==1.12.2
|
||||
- sympy==1.10.1
|
||||
- tensorboard==2.9.0
|
||||
- torchmetrics==0.9.3
|
||||
- antlr4-python3-runtime=4.8
|
||||
- pip:
|
||||
- opencv-python==4.6.0.66
|
||||
- realesrgan==0.2.5.0
|
||||
- test-tube==0.7.5
|
||||
- transformers==4.21.2
|
||||
- torch-fidelity==0.3.0
|
||||
- -e git+https://github.com/CompVis/taming-transformers.git@master#egg=taming-transformers
|
||||
- -e git+https://github.com/openai/CLIP.git@main#egg=clip
|
||||
- -e git+https://github.com/TencentARC/GFPGAN#egg=GFPGAN
|
||||
- -e git+https://github.com/xinntao/Real-ESRGAN#egg=realesrgan
|
||||
- -e .
|
||||
variables:
|
||||
PYTORCH_ENABLE_MPS_FALLBACK: 1
|
33
installer/yaml/sd-environment-win-linux-nvidia.yaml
Normal file
@ -0,0 +1,33 @@
|
||||
name: ldm
|
||||
channels:
|
||||
- pytorch
|
||||
- defaults
|
||||
- conda-forge
|
||||
dependencies:
|
||||
- python=3.10.5
|
||||
- pip=20.3
|
||||
- cudatoolkit=11.3
|
||||
- pytorch=1.11.0
|
||||
- torchvision=0.12.0
|
||||
- numpy=1.23.2
|
||||
- antlr4-python3-runtime=4.8
|
||||
- pip:
|
||||
- albumentations==0.4.3
|
||||
- opencv-python==4.6.0.66
|
||||
- pudb==2019.2
|
||||
- imageio==2.9.0
|
||||
- imageio-ffmpeg==0.4.2
|
||||
- pytorch-lightning==1.4.2
|
||||
- omegaconf==2.1.1
|
||||
- test-tube>=0.7.5
|
||||
- streamlit>=0.73.1
|
||||
- einops==0.3.0
|
||||
- torch-fidelity==0.3.0
|
||||
- transformers==4.19.2
|
||||
- torchmetrics==0.6.0
|
||||
- kornia==0.6
|
||||
- -e git+https://github.com/CompVis/taming-transformers.git@master#egg=taming-transformers
|
||||
- -e git+https://github.com/openai/CLIP.git@main#egg=clip
|
||||
- -e git+https://github.com/TencentARC/GFPGAN#egg=GFPGAN
|
||||
- -e git+https://github.com/xinntao/Real-ESRGAN#egg=realesrgan
|
||||
- -e .
|
Before Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 55 KiB |
Before Width: | Height: | Size: 45 KiB |
Before Width: | Height: | Size: 122 KiB |
Before Width: | Height: | Size: 67 KiB |
Before Width: | Height: | Size: 244 KiB |
@ -1,19 +0,0 @@
|
||||
@echo off
|
||||
|
||||
@REM Delete the post-activate hook from the old installer
|
||||
if exist "installer\etc\conda\activate.d\post_activate.bat" (
|
||||
echo. > installer\etc\conda\activate.d\post_activate.bat
|
||||
)
|
||||
|
||||
@call installer\Scripts\activate.bat
|
||||
|
||||
@call conda-unpack
|
||||
|
||||
@call conda --version
|
||||
@call git --version
|
||||
|
||||
@cd installer
|
||||
|
||||
@call ..\scripts\on_env_start.bat
|
||||
|
||||
@pause
|
@ -1,61 +0,0 @@
|
||||
@echo off
|
||||
|
||||
@echo. & echo "Stable Diffusion UI - v2" & echo.
|
||||
|
||||
set PATH=C:\Windows\System32;%PATH%
|
||||
|
||||
@cd ..
|
||||
|
||||
if exist "scripts\config.bat" (
|
||||
@call scripts\config.bat
|
||||
)
|
||||
|
||||
if "%update_branch%"=="" (
|
||||
set update_branch=main
|
||||
)
|
||||
|
||||
@>nul grep -c "conda_sd_ui_deps_installed" scripts\install_status.txt
|
||||
@if "%ERRORLEVEL%" NEQ "0" (
|
||||
for /f "tokens=*" %%a in ('python -c "import os; parts = os.getcwd().split(os.path.sep); print(len(parts))"') do if "%%a" NEQ "2" (
|
||||
echo. & echo "!!!! WARNING !!!!" & echo.
|
||||
echo "Your 'stable-diffusion-ui' folder is at %cd%" & echo.
|
||||
echo "The 'stable-diffusion-ui' folder needs to be at the top of your drive, for e.g. 'C:\stable-diffusion-ui' or 'D:\stable-diffusion-ui' etc."
|
||||
echo "Not placing this folder at the top of a drive can cause errors on some computers."
|
||||
echo. & echo "Recommended: Please close this window and move the 'stable-diffusion-ui' folder to the top of a drive. For e.g. 'C:\stable-diffusion-ui'. Then run the installer again." & echo.
|
||||
echo "Not Recommended: If you're sure that you want to install at the current location, please press any key to continue." & echo.
|
||||
|
||||
pause
|
||||
)
|
||||
)
|
||||
|
||||
@>nul grep -c "sd_ui_git_cloned" scripts\install_status.txt
|
||||
@if "%ERRORLEVEL%" EQU "0" (
|
||||
@echo "Stable Diffusion UI's git repository was already installed. Updating from %update_branch%.."
|
||||
|
||||
@cd sd-ui-files
|
||||
|
||||
@call git reset --hard
|
||||
@call git checkout "%update_branch%"
|
||||
@call git pull
|
||||
|
||||
@cd ..
|
||||
) else (
|
||||
@echo. & echo "Downloading Stable Diffusion UI.." & echo.
|
||||
@echo "Using the %update_branch% channel" & echo.
|
||||
|
||||
@call git clone -b "%update_branch%" https://github.com/cmdr2/stable-diffusion-ui.git sd-ui-files && (
|
||||
@echo sd_ui_git_cloned >> scripts\install_status.txt
|
||||
) || (
|
||||
@echo "Error downloading 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/blob/main/Troubleshooting.md" & 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
|
||||
)
|
||||
)
|
||||
|
||||
@xcopy sd-ui-files\ui ui /s /i /Y
|
||||
@copy sd-ui-files\scripts\on_sd_start.bat scripts\ /Y
|
||||
@copy "sd-ui-files\scripts\Start Stable Diffusion UI.cmd" . /Y
|
||||
|
||||
@call scripts\on_sd_start.bat
|
||||
|
||||
@pause
|
@ -1,43 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
printf "\n\nStable Diffusion UI\n\n"
|
||||
|
||||
if [ -f "scripts/config.sh" ]; then
|
||||
source scripts/config.sh
|
||||
fi
|
||||
|
||||
if [ "$update_branch" == "" ]; then
|
||||
export update_branch="main"
|
||||
fi
|
||||
|
||||
if [ -f "scripts/install_status.txt" ] && [ `grep -c sd_ui_git_cloned scripts/install_status.txt` -gt "0" ]; then
|
||||
echo "Stable Diffusion UI's git repository was already installed. Updating from $update_branch.."
|
||||
|
||||
cd sd-ui-files
|
||||
|
||||
git reset --hard
|
||||
git checkout "$update_branch"
|
||||
git pull
|
||||
|
||||
cd ..
|
||||
else
|
||||
printf "\n\nDownloading Stable Diffusion UI..\n\n"
|
||||
printf "Using the $update_branch channel\n\n"
|
||||
|
||||
if git clone -b "$update_branch" https://github.com/cmdr2/stable-diffusion-ui.git sd-ui-files ; then
|
||||
echo sd_ui_git_cloned >> scripts/install_status.txt
|
||||
else
|
||||
printf "\n\nError downloading Stable Diffusion UI. Sorry about that, please try to:\n 1. Run this installer again.\n 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/blob/main/Troubleshooting.md\n 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\n 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues\nThanks!\n\n"
|
||||
read -p "Press any key to continue"
|
||||
exit
|
||||
fi
|
||||
fi
|
||||
|
||||
rm -rf ui
|
||||
cp -Rf sd-ui-files/ui .
|
||||
cp sd-ui-files/scripts/on_sd_start.sh scripts/
|
||||
cp sd-ui-files/scripts/start.sh .
|
||||
|
||||
./scripts/on_sd_start.sh
|
||||
|
||||
read -p "Press any key to continue"
|
@ -1,317 +0,0 @@
|
||||
@echo off
|
||||
|
||||
@copy sd-ui-files\scripts\on_env_start.bat scripts\ /Y
|
||||
|
||||
@REM Caution, this file will make your eyes and brain bleed. It's such an unholy mess.
|
||||
@REM Note to self: Please rewrite this in Python. For the sake of your own sanity.
|
||||
|
||||
@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');"
|
||||
|
||||
@>nul grep -c "sd_git_cloned" scripts\install_status.txt
|
||||
@if "%ERRORLEVEL%" EQU "0" (
|
||||
@echo "Stable Diffusion's git repository was already installed. Updating.."
|
||||
|
||||
@cd stable-diffusion
|
||||
|
||||
@call git reset --hard
|
||||
@call git pull
|
||||
@call git checkout f6cfebffa752ee11a7b07497b8529d5971de916c
|
||||
|
||||
@call git apply ..\ui\sd_internal\ddim_callback.patch
|
||||
@call git apply ..\ui\sd_internal\env_yaml.patch
|
||||
|
||||
@cd ..
|
||||
) else (
|
||||
@echo. & echo "Downloading Stable Diffusion.." & echo.
|
||||
|
||||
@call git clone https://github.com/basujindal/stable-diffusion.git && (
|
||||
@echo sd_git_cloned >> scripts\install_status.txt
|
||||
) || (
|
||||
@echo "Error downloading Stable Diffusion. 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/blob/main/Troubleshooting.md" & 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
|
||||
)
|
||||
|
||||
@cd stable-diffusion
|
||||
@call git checkout f6cfebffa752ee11a7b07497b8529d5971de916c
|
||||
|
||||
@call git apply ..\ui\sd_internal\ddim_callback.patch
|
||||
@call git apply ..\ui\sd_internal\env_yaml.patch
|
||||
|
||||
@cd ..
|
||||
)
|
||||
|
||||
@cd stable-diffusion
|
||||
|
||||
@>nul grep -c "conda_sd_env_created" ..\scripts\install_status.txt
|
||||
@if "%ERRORLEVEL%" EQU "0" (
|
||||
@echo "Packages necessary for Stable Diffusion were already installed"
|
||||
|
||||
@call conda activate .\env
|
||||
) else (
|
||||
@echo. & echo "Downloading packages necessary for Stable Diffusion.." & echo. & echo "***** This will take some time (depending on the speed of the Internet connection) and may appear to be stuck, but please be patient ***** .." & echo.
|
||||
|
||||
@rmdir /s /q .\env
|
||||
|
||||
@REM prevent conda from using packages from the user's home directory, to avoid conflicts
|
||||
@set PYTHONNOUSERSITE=1
|
||||
|
||||
@call conda env create --prefix env -f environment.yaml || (
|
||||
@echo. & echo "Error installing the packages necessary for Stable Diffusion. 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/blob/main/Troubleshooting.md" & 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!" & echo.
|
||||
pause
|
||||
exit /b
|
||||
)
|
||||
|
||||
@call conda activate .\env
|
||||
|
||||
@call conda install -c conda-forge -y --prefix env antlr4-python3-runtime=4.8 || (
|
||||
@echo. & echo "Error installing antlr4-python3-runtime for Stable Diffusion. 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/blob/main/Troubleshooting.md" & 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!" & echo.
|
||||
pause
|
||||
exit /b
|
||||
)
|
||||
|
||||
for /f "tokens=*" %%a in ('python -c "import torch; import ldm; import transformers; import numpy; import antlr4; print(42)"') do if "%%a" NEQ "42" (
|
||||
@echo. & echo "Dependency test failed! Error installing the packages necessary for Stable Diffusion. 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/blob/main/Troubleshooting.md" & 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!" & echo.
|
||||
pause
|
||||
exit /b
|
||||
)
|
||||
|
||||
@echo conda_sd_env_created >> ..\scripts\install_status.txt
|
||||
)
|
||||
|
||||
set PATH=C:\Windows\System32;%PATH%
|
||||
|
||||
@>nul grep -c "conda_sd_gfpgan_deps_installed" ..\scripts\install_status.txt
|
||||
@if "%ERRORLEVEL%" EQU "0" (
|
||||
@echo "Packages necessary for GFPGAN (Face Correction) were already installed"
|
||||
) else (
|
||||
@echo. & echo "Downloading packages necessary for GFPGAN (Face Correction).." & echo.
|
||||
|
||||
@set PYTHONNOUSERSITE=1
|
||||
|
||||
@call pip install -e git+https://github.com/TencentARC/GFPGAN#egg=GFPGAN || (
|
||||
@echo. & echo "Error installing the packages necessary for GFPGAN (Face Correction). 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/blob/main/Troubleshooting.md" & 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!" & echo.
|
||||
pause
|
||||
exit /b
|
||||
)
|
||||
|
||||
@call pip install basicsr==1.4.2 || (
|
||||
@echo. & echo "Error installing the basicsr package necessary for GFPGAN (Face Correction). 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/blob/main/Troubleshooting.md" & 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!" & echo.
|
||||
pause
|
||||
exit /b
|
||||
)
|
||||
|
||||
for /f "tokens=*" %%a in ('python -c "from gfpgan import GFPGANer; print(42)"') do if "%%a" NEQ "42" (
|
||||
@echo. & echo "Dependency test failed! Error installing the packages necessary for GFPGAN (Face Correction). 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/blob/main/Troubleshooting.md" & 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!" & echo.
|
||||
pause
|
||||
exit /b
|
||||
)
|
||||
|
||||
@echo conda_sd_gfpgan_deps_installed >> ..\scripts\install_status.txt
|
||||
)
|
||||
|
||||
@>nul grep -c "conda_sd_esrgan_deps_installed" ..\scripts\install_status.txt
|
||||
@if "%ERRORLEVEL%" EQU "0" (
|
||||
@echo "Packages necessary for ESRGAN (Resolution Upscaling) were already installed"
|
||||
) else (
|
||||
@echo. & echo "Downloading packages necessary for ESRGAN (Resolution Upscaling).." & echo.
|
||||
|
||||
@set PYTHONNOUSERSITE=1
|
||||
|
||||
@call pip install -e git+https://github.com/xinntao/Real-ESRGAN#egg=realesrgan || (
|
||||
@echo. & echo "Error installing the packages necessary for ESRGAN (Resolution Upscaling). 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/blob/main/Troubleshooting.md" & 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!" & echo.
|
||||
pause
|
||||
exit /b
|
||||
)
|
||||
|
||||
for /f "tokens=*" %%a in ('python -c "from basicsr.archs.rrdbnet_arch import RRDBNet; from realesrgan import RealESRGANer; print(42)"') do if "%%a" NEQ "42" (
|
||||
@echo. & echo "Dependency test failed! Error installing the packages necessary for ESRGAN (Resolution Upscaling). 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/blob/main/Troubleshooting.md" & 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!" & echo.
|
||||
pause
|
||||
exit /b
|
||||
)
|
||||
|
||||
@echo conda_sd_esrgan_deps_installed >> ..\scripts\install_status.txt
|
||||
)
|
||||
|
||||
@>nul grep -c "conda_sd_ui_deps_installed" ..\scripts\install_status.txt
|
||||
@if "%ERRORLEVEL%" EQU "0" (
|
||||
echo "Packages necessary for Stable Diffusion UI were already installed"
|
||||
) else (
|
||||
@echo. & echo "Downloading packages necessary for Stable Diffusion UI.." & echo.
|
||||
|
||||
@set PYTHONNOUSERSITE=1
|
||||
|
||||
@call conda install -c conda-forge -y --prefix env uvicorn fastapi || (
|
||||
echo "Error installing the packages 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/blob/main/Troubleshooting.md" & 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
|
||||
)
|
||||
)
|
||||
|
||||
call WHERE uvicorn > .tmp
|
||||
@>nul grep -c "uvicorn" .tmp
|
||||
@if "%ERRORLEVEL%" NEQ "0" (
|
||||
@echo. & echo "UI packages not found! 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/blob/main/Troubleshooting.md" & 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!" & echo.
|
||||
pause
|
||||
exit /b
|
||||
)
|
||||
|
||||
@>nul grep -c "conda_sd_ui_deps_installed" ..\scripts\install_status.txt
|
||||
@if "%ERRORLEVEL%" NEQ "0" (
|
||||
@echo conda_sd_ui_deps_installed >> ..\scripts\install_status.txt
|
||||
)
|
||||
|
||||
|
||||
|
||||
@if exist "sd-v1-4.ckpt" (
|
||||
for %%I in ("sd-v1-4.ckpt") do if "%%~zI" EQU "4265380512" (
|
||||
echo "Data files (weights) necessary for Stable Diffusion were already downloaded. Using the HuggingFace 4 GB Model."
|
||||
) else (
|
||||
for %%J in ("sd-v1-4.ckpt") do if "%%~zJ" EQU "7703807346" (
|
||||
echo "Data files (weights) necessary for Stable Diffusion were already downloaded. Using the HuggingFace 7 GB Model."
|
||||
) else (
|
||||
for %%K in ("sd-v1-4.ckpt") do if "%%~zK" EQU "7703810927" (
|
||||
echo "Data files (weights) necessary for Stable Diffusion were already downloaded. Using the Waifu Model."
|
||||
) else (
|
||||
echo. & echo "The model file present at %cd%\sd-v1-4.ckpt is invalid. It is only %%~zK bytes in size. Re-downloading.." & echo.
|
||||
del "sd-v1-4.ckpt"
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
@if not exist "sd-v1-4.ckpt" (
|
||||
@echo. & echo "Downloading data files (weights) for Stable Diffusion.." & echo.
|
||||
|
||||
@call curl -L -k https://me.cmdr2.org/stable-diffusion-ui/sd-v1-4.ckpt > sd-v1-4.ckpt
|
||||
|
||||
@if exist "sd-v1-4.ckpt" (
|
||||
for %%I in ("sd-v1-4.ckpt") do if "%%~zI" NEQ "4265380512" (
|
||||
echo. & echo "Error: The downloaded model file was invalid! Bytes downloaded: %%~zI" & echo.
|
||||
echo. & echo "Error downloading the data files (weights) for Stable Diffusion. 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/blob/main/Troubleshooting.md" & 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!" & echo.
|
||||
pause
|
||||
exit /b
|
||||
)
|
||||
) else (
|
||||
@echo. & echo "Error downloading the data files (weights) for Stable Diffusion. 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/blob/main/Troubleshooting.md" & 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!" & echo.
|
||||
pause
|
||||
exit /b
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
|
||||
@if exist "GFPGANv1.3.pth" (
|
||||
for %%I in ("GFPGANv1.3.pth") do if "%%~zI" EQU "348632874" (
|
||||
echo "Data files (weights) necessary for GFPGAN (Face Correction) were already downloaded"
|
||||
) else (
|
||||
echo. & echo "The GFPGAN model file present at %cd%\GFPGANv1.3.pth is invalid. It is only %%~zI bytes in size. Re-downloading.." & echo.
|
||||
del "GFPGANv1.3.pth"
|
||||
)
|
||||
)
|
||||
|
||||
@if not exist "GFPGANv1.3.pth" (
|
||||
@echo. & echo "Downloading data files (weights) for GFPGAN (Face Correction).." & echo.
|
||||
|
||||
@call curl -L -k https://github.com/TencentARC/GFPGAN/releases/download/v1.3.0/GFPGANv1.3.pth > GFPGANv1.3.pth
|
||||
|
||||
@if exist "GFPGANv1.3.pth" (
|
||||
for %%I in ("GFPGANv1.3.pth") do if "%%~zI" NEQ "348632874" (
|
||||
echo. & echo "Error: The downloaded GFPGAN model file was invalid! Bytes downloaded: %%~zI" & echo.
|
||||
echo. & echo "Error downloading the data files (weights) for GFPGAN (Face Correction). 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/blob/main/Troubleshooting.md" & 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!" & echo.
|
||||
pause
|
||||
exit /b
|
||||
)
|
||||
) else (
|
||||
@echo. & echo "Error downloading the data files (weights) for GFPGAN (Face Correction). 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/blob/main/Troubleshooting.md" & 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!" & echo.
|
||||
pause
|
||||
exit /b
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
|
||||
@if exist "RealESRGAN_x4plus.pth" (
|
||||
for %%I in ("RealESRGAN_x4plus.pth") do if "%%~zI" EQU "67040989" (
|
||||
echo "Data files (weights) necessary for ESRGAN (Resolution Upscaling) x4plus were already downloaded"
|
||||
) 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.
|
||||
del "RealESRGAN_x4plus.pth"
|
||||
)
|
||||
)
|
||||
|
||||
@if not exist "RealESRGAN_x4plus.pth" (
|
||||
@echo. & echo "Downloading data files (weights) for ESRGAN (Resolution Upscaling) x4plus.." & echo.
|
||||
|
||||
@call curl -L -k https://github.com/xinntao/Real-ESRGAN/releases/download/v0.1.0/RealESRGAN_x4plus.pth > RealESRGAN_x4plus.pth
|
||||
|
||||
@if exist "RealESRGAN_x4plus.pth" (
|
||||
for %%I in ("RealESRGAN_x4plus.pth") do if "%%~zI" NEQ "67040989" (
|
||||
echo. & echo "Error: The downloaded ESRGAN x4plus model file was invalid! Bytes downloaded: %%~zI" & echo.
|
||||
echo. & echo "Error downloading the data files (weights) for ESRGAN (Resolution Upscaling) x4plus. 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/blob/main/Troubleshooting.md" & 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!" & echo.
|
||||
pause
|
||||
exit /b
|
||||
)
|
||||
) else (
|
||||
@echo. & echo "Error downloading the data files (weights) for ESRGAN (Resolution Upscaling) x4plus. 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/blob/main/Troubleshooting.md" & 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!" & echo.
|
||||
pause
|
||||
exit /b
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
|
||||
@if exist "RealESRGAN_x4plus_anime_6B.pth" (
|
||||
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"
|
||||
) 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.
|
||||
del "RealESRGAN_x4plus_anime_6B.pth"
|
||||
)
|
||||
)
|
||||
|
||||
@if not exist "RealESRGAN_x4plus_anime_6B.pth" (
|
||||
@echo. & echo "Downloading data files (weights) for ESRGAN (Resolution Upscaling) x4plus_anime.." & echo.
|
||||
|
||||
@call curl -L -k https://github.com/xinntao/Real-ESRGAN/releases/download/v0.2.2.4/RealESRGAN_x4plus_anime_6B.pth > RealESRGAN_x4plus_anime_6B.pth
|
||||
|
||||
@if exist "RealESRGAN_x4plus_anime_6B.pth" (
|
||||
for %%I in ("RealESRGAN_x4plus_anime_6B.pth") do if "%%~zI" NEQ "17938799" (
|
||||
echo. & echo "Error: The downloaded ESRGAN x4plus_anime model file was invalid! Bytes downloaded: %%~zI" & echo.
|
||||
echo. & echo "Error downloading the data files (weights) for ESRGAN (Resolution Upscaling) x4plus_anime. 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/blob/main/Troubleshooting.md" & 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!" & echo.
|
||||
pause
|
||||
exit /b
|
||||
)
|
||||
) else (
|
||||
@echo. & echo "Error downloading the data files (weights) for ESRGAN (Resolution Upscaling) x4plus_anime. 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/blob/main/Troubleshooting.md" & 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!" & echo.
|
||||
pause
|
||||
exit /b
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
|
||||
@>nul grep -c "sd_install_complete" ..\scripts\install_status.txt
|
||||
@if "%ERRORLEVEL%" NEQ "0" (
|
||||
@echo sd_weights_downloaded >> ..\scripts\install_status.txt
|
||||
@echo sd_install_complete >> ..\scripts\install_status.txt
|
||||
)
|
||||
|
||||
@echo. & echo "Stable Diffusion is ready!" & echo.
|
||||
|
||||
@set SD_DIR=%cd%
|
||||
|
||||
@cd env\lib\site-packages
|
||||
@set PYTHONPATH=%SD_DIR%;%cd%
|
||||
@cd ..\..\..
|
||||
@echo PYTHONPATH=%PYTHONPATH%
|
||||
|
||||
@cd ..
|
||||
@set SD_UI_PATH=%cd%\ui
|
||||
@cd stable-diffusion
|
||||
|
||||
@call python --version
|
||||
|
||||
@uvicorn server:app --app-dir "%SD_UI_PATH%" --port 9000 --host 0.0.0.0
|
||||
|
||||
@pause
|
@ -1,309 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
cp sd-ui-files/scripts/on_env_start.sh scripts/
|
||||
|
||||
source installer/etc/profile.d/conda.sh
|
||||
|
||||
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');"
|
||||
|
||||
# Caution, this file will make your eyes and brain bleed. It's such an unholy mess.
|
||||
# Note to self: Please rewrite this in Python. For the sake of your own sanity.
|
||||
|
||||
if [ -e "scripts/install_status.txt" ] && [ `grep -c sd_git_cloned scripts/install_status.txt` -gt "0" ]; then
|
||||
echo "Stable Diffusion's git repository was already installed. Updating.."
|
||||
|
||||
cd stable-diffusion
|
||||
|
||||
git reset --hard
|
||||
git pull
|
||||
git checkout f6cfebffa752ee11a7b07497b8529d5971de916c
|
||||
|
||||
git apply ../ui/sd_internal/ddim_callback.patch
|
||||
git apply ../ui/sd_internal/env_yaml.patch
|
||||
|
||||
cd ..
|
||||
else
|
||||
printf "\n\nDownloading Stable Diffusion..\n\n"
|
||||
|
||||
if git clone https://github.com/basujindal/stable-diffusion.git ; then
|
||||
echo sd_git_cloned >> scripts/install_status.txt
|
||||
else
|
||||
printf "\n\nError downloading Stable Diffusion. Sorry about that, please try to:\n 1. Run this installer again.\n 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/blob/main/Troubleshooting.md\n 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\n 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues\nThanks!\n\n"
|
||||
read -p "Press any key to continue"
|
||||
exit
|
||||
fi
|
||||
|
||||
cd stable-diffusion
|
||||
git checkout f6cfebffa752ee11a7b07497b8529d5971de916c
|
||||
|
||||
git apply ../ui/sd_internal/ddim_callback.patch
|
||||
git apply ../ui/sd_internal/env_yaml.patch
|
||||
|
||||
cd ..
|
||||
fi
|
||||
|
||||
cd stable-diffusion
|
||||
|
||||
if [ `grep -c conda_sd_env_created ../scripts/install_status.txt` -gt "0" ]; then
|
||||
echo "Packages necessary for Stable Diffusion were already installed"
|
||||
|
||||
conda activate ./env
|
||||
else
|
||||
printf "\n\nDownloading packages necessary for Stable Diffusion..\n"
|
||||
printf "\n\n***** This will take some time (depending on the speed of the Internet connection) and may appear to be stuck, but please be patient ***** ..\n\n"
|
||||
|
||||
# prevent conda from using packages from the user's home directory, to avoid conflicts
|
||||
export PYTHONNOUSERSITE=1
|
||||
|
||||
if conda env create --prefix env --force -f environment.yaml ; then
|
||||
echo "Installed. Testing.."
|
||||
else
|
||||
printf "\n\nError installing the packages necessary for Stable Diffusion. Sorry about that, please try to:\n 1. Run this installer again.\n 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/blob/main/Troubleshooting.md\n 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\n 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues\nThanks!\n\n"
|
||||
read -p "Press any key to continue"
|
||||
exit
|
||||
fi
|
||||
|
||||
conda activate ./env
|
||||
|
||||
if conda install -c conda-forge --prefix ./env -y antlr4-python3-runtime=4.8 ; then
|
||||
echo "Installed. Testing.."
|
||||
else
|
||||
printf "\n\nError installing antlr4-python3-runtime for Stable Diffusion. Sorry about that, please try to:\n 1. Run this installer again.\n 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/blob/main/Troubleshooting.md\n 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\n 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues\nThanks!\n\n"
|
||||
read -p "Press any key to continue"
|
||||
exit
|
||||
fi
|
||||
|
||||
out_test=`python -c "import torch; import ldm; import transformers; import numpy; import antlr4; print(42)"`
|
||||
if [ "$out_test" != "42" ]; then
|
||||
printf "\n\nDependency test failed! Error installing the packages necessary for Stable Diffusion. Sorry about that, please try to:\n 1. Run this installer again.\n 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/blob/main/Troubleshooting.md\n 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\n 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues\nThanks!\n\n"
|
||||
read -p "Press any key to continue"
|
||||
exit
|
||||
fi
|
||||
|
||||
echo conda_sd_env_created >> ../scripts/install_status.txt
|
||||
fi
|
||||
|
||||
if [ `grep -c conda_sd_gfpgan_deps_installed ../scripts/install_status.txt` -gt "0" ]; then
|
||||
echo "Packages necessary for GFPGAN (Face Correction) were already installed"
|
||||
else
|
||||
printf "\n\nDownloading packages necessary for GFPGAN (Face Correction)..\n"
|
||||
|
||||
export PYTHONNOUSERSITE=1
|
||||
|
||||
if pip install -e git+https://github.com/TencentARC/GFPGAN#egg=GFPGAN ; then
|
||||
echo "Installed. Testing.."
|
||||
else
|
||||
printf "\n\nError installing the packages necessary for GFPGAN (Face Correction). Sorry about that, please try to:\n 1. Run this installer again.\n 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/blob/main/Troubleshooting.md\n 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\n 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues\nThanks!\n\n"
|
||||
read -p "Press any key to continue"
|
||||
exit
|
||||
fi
|
||||
|
||||
out_test=`python -c "from gfpgan import GFPGANer; print(42)"`
|
||||
if [ "$out_test" != "42" ]; then
|
||||
printf "\n\nDependency test failed! Error installing the packages necessary for GFPGAN (Face Correction). Sorry about that, please try to:\n 1. Run this installer again.\n 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/blob/main/Troubleshooting.md\n 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\n 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues\nThanks!\n\n"
|
||||
read -p "Press any key to continue"
|
||||
exit
|
||||
fi
|
||||
|
||||
echo conda_sd_gfpgan_deps_installed >> ../scripts/install_status.txt
|
||||
fi
|
||||
|
||||
if [ `grep -c conda_sd_esrgan_deps_installed ../scripts/install_status.txt` -gt "0" ]; then
|
||||
echo "Packages necessary for ESRGAN (Resolution Upscaling) were already installed"
|
||||
else
|
||||
printf "\n\nDownloading packages necessary for ESRGAN (Resolution Upscaling)..\n"
|
||||
|
||||
export PYTHONNOUSERSITE=1
|
||||
|
||||
if pip install -e git+https://github.com/xinntao/Real-ESRGAN#egg=realesrgan ; then
|
||||
echo "Installed. Testing.."
|
||||
else
|
||||
printf "\n\nError installing the packages necessary for ESRGAN (Resolution Upscaling). Sorry about that, please try to:\n 1. Run this installer again.\n 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/blob/main/Troubleshooting.md\n 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\n 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues\nThanks!\n\n"
|
||||
read -p "Press any key to continue"
|
||||
exit
|
||||
fi
|
||||
|
||||
out_test=`python -c "from basicsr.archs.rrdbnet_arch import RRDBNet; from realesrgan import RealESRGANer; print(42)"`
|
||||
if [ "$out_test" != "42" ]; then
|
||||
printf "\n\nDependency test failed! Error installing the packages necessary for ESRGAN (Resolution Upscaling). Sorry about that, please try to:\n 1. Run this installer again.\n 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/blob/main/Troubleshooting.md\n 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\n 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues\nThanks!\n\n"
|
||||
read -p "Press any key to continue"
|
||||
exit
|
||||
fi
|
||||
|
||||
echo conda_sd_esrgan_deps_installed >> ../scripts/install_status.txt
|
||||
fi
|
||||
|
||||
if [ `grep -c conda_sd_ui_deps_installed ../scripts/install_status.txt` -gt "0" ]; then
|
||||
echo "Packages necessary for Stable Diffusion UI were already installed"
|
||||
else
|
||||
printf "\n\nDownloading packages necessary for Stable Diffusion UI..\n\n"
|
||||
|
||||
export PYTHONNOUSERSITE=1
|
||||
|
||||
if conda install -c conda-forge --prefix ./env -y uvicorn fastapi ; then
|
||||
echo "Installed. Testing.."
|
||||
else
|
||||
printf "\n\nError installing the packages necessary for Stable Diffusion UI. Sorry about that, please try to:\n 1. Run this installer again.\n 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/blob/main/Troubleshooting.md\n 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\n 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues\nThanks!\n\n"
|
||||
read -p "Press any key to continue"
|
||||
exit
|
||||
fi
|
||||
|
||||
if ! command -v uvicorn &> /dev/null; then
|
||||
printf "\n\nUI packages not found! Error installing the packages necessary for Stable Diffusion UI. Sorry about that, please try to:\n 1. Run this installer again.\n 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/blob/main/Troubleshooting.md\n 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\n 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues\nThanks!\n\n"
|
||||
read -p "Press any key to continue"
|
||||
exit
|
||||
fi
|
||||
|
||||
echo conda_sd_ui_deps_installed >> ../scripts/install_status.txt
|
||||
fi
|
||||
|
||||
|
||||
|
||||
if [ -f "sd-v1-4.ckpt" ]; then
|
||||
model_size=`ls -l sd-v1-4.ckpt | awk '{print $5}'`
|
||||
|
||||
if [ "$model_size" -eq "4265380512" ] || [ "$model_size" -eq "7703807346" ] || [ "$model_size" -eq "7703810927" ]; then
|
||||
echo "Data files (weights) necessary for Stable Diffusion were already downloaded"
|
||||
else
|
||||
printf "\n\nThe model file present at $PWD/sd-v1-4.ckpt is invalid. It is only $model_size bytes in size. Re-downloading.."
|
||||
rm sd-v1-4.ckpt
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -f "sd-v1-4.ckpt" ]; then
|
||||
echo "Downloading data files (weights) for Stable Diffusion.."
|
||||
|
||||
curl -L -k https://me.cmdr2.org/stable-diffusion-ui/sd-v1-4.ckpt > sd-v1-4.ckpt
|
||||
|
||||
if [ -f "sd-v1-4.ckpt" ]; then
|
||||
model_size=`ls -l sd-v1-4.ckpt | awk '{print $5}'`
|
||||
if [ ! "$model_size" == "4265380512" ]; then
|
||||
printf "\n\nError: The downloaded model file was invalid! Bytes downloaded: $model_size\n\n"
|
||||
printf "\n\nError downloading the data files (weights) for Stable Diffusion. Sorry about that, please try to:\n 1. Run this installer again.\n 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/blob/main/Troubleshooting.md\n 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\n 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues\nThanks!\n\n"
|
||||
read -p "Press any key to continue"
|
||||
exit
|
||||
fi
|
||||
else
|
||||
printf "\n\nError downloading the data files (weights) for Stable Diffusion. Sorry about that, please try to:\n 1. Run this installer again.\n 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/blob/main/Troubleshooting.md\n 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\n 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues\nThanks!\n\n"
|
||||
read -p "Press any key to continue"
|
||||
exit
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
if [ -f "GFPGANv1.3.pth" ]; then
|
||||
model_size=`ls -l GFPGANv1.3.pth | awk '{print $5}'`
|
||||
|
||||
if [ "$model_size" -eq "348632874" ]; then
|
||||
echo "Data files (weights) necessary for GFPGAN (Face Correction) were already downloaded"
|
||||
else
|
||||
printf "\n\nThe model file present at $PWD/GFPGANv1.3.pth is invalid. It is only $model_size bytes in size. Re-downloading.."
|
||||
rm GFPGANv1.3.pth
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -f "GFPGANv1.3.pth" ]; then
|
||||
echo "Downloading data files (weights) for GFPGAN (Face Correction).."
|
||||
|
||||
curl -L -k https://github.com/TencentARC/GFPGAN/releases/download/v1.3.0/GFPGANv1.3.pth > GFPGANv1.3.pth
|
||||
|
||||
if [ -f "GFPGANv1.3.pth" ]; then
|
||||
model_size=`ls -l GFPGANv1.3.pth | awk '{print $5}'`
|
||||
if [ ! "$model_size" -eq "348632874" ]; then
|
||||
printf "\n\nError: The downloaded GFPGAN model file was invalid! Bytes downloaded: $model_size\n\n"
|
||||
printf "\n\nError downloading the data files (weights) for GFPGAN (Face Correction). Sorry about that, please try to:\n 1. Run this installer again.\n 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/blob/main/Troubleshooting.md\n 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\n 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues\nThanks!\n\n"
|
||||
read -p "Press any key to continue"
|
||||
exit
|
||||
fi
|
||||
else
|
||||
printf "\n\nError downloading the data files (weights) for GFPGAN (Face Correction). Sorry about that, please try to:\n 1. Run this installer again.\n 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/blob/main/Troubleshooting.md\n 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\n 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues\nThanks!\n\n"
|
||||
read -p "Press any key to continue"
|
||||
exit
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
if [ -f "RealESRGAN_x4plus.pth" ]; then
|
||||
model_size=`ls -l RealESRGAN_x4plus.pth | awk '{print $5}'`
|
||||
|
||||
if [ "$model_size" -eq "67040989" ]; then
|
||||
echo "Data files (weights) necessary for ESRGAN (Resolution Upscaling) x4plus were already downloaded"
|
||||
else
|
||||
printf "\n\nThe model file present at $PWD/RealESRGAN_x4plus.pth is invalid. It is only $model_size bytes in size. Re-downloading.."
|
||||
rm RealESRGAN_x4plus.pth
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -f "RealESRGAN_x4plus.pth" ]; then
|
||||
echo "Downloading data files (weights) for ESRGAN (Resolution Upscaling) x4plus.."
|
||||
|
||||
curl -L -k https://github.com/xinntao/Real-ESRGAN/releases/download/v0.1.0/RealESRGAN_x4plus.pth > RealESRGAN_x4plus.pth
|
||||
|
||||
if [ -f "RealESRGAN_x4plus.pth" ]; then
|
||||
model_size=`ls -l RealESRGAN_x4plus.pth | awk '{print $5}'`
|
||||
if [ ! "$model_size" -eq "67040989" ]; then
|
||||
printf "\n\nError: The downloaded ESRGAN x4plus model file was invalid! Bytes downloaded: $model_size\n\n"
|
||||
printf "\n\nError downloading the data files (weights) for ESRGAN (Resolution Upscaling) x4plus. Sorry about that, please try to:\n 1. Run this installer again.\n 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/blob/main/Troubleshooting.md\n 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\n 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues\nThanks!\n\n"
|
||||
read -p "Press any key to continue"
|
||||
exit
|
||||
fi
|
||||
else
|
||||
printf "\n\nError downloading the data files (weights) for ESRGAN (Resolution Upscaling) x4plus. Sorry about that, please try to:\n 1. Run this installer again.\n 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/blob/main/Troubleshooting.md\n 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\n 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues\nThanks!\n\n"
|
||||
read -p "Press any key to continue"
|
||||
exit
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
if [ -f "RealESRGAN_x4plus_anime_6B.pth" ]; then
|
||||
model_size=`ls -l RealESRGAN_x4plus_anime_6B.pth | awk '{print $5}'`
|
||||
|
||||
if [ "$model_size" -eq "17938799" ]; then
|
||||
echo "Data files (weights) necessary for ESRGAN (Resolution Upscaling) x4plus_anime were already downloaded"
|
||||
else
|
||||
printf "\n\nThe model file present at $PWD/RealESRGAN_x4plus_anime_6B.pth is invalid. It is only $model_size bytes in size. Re-downloading.."
|
||||
rm RealESRGAN_x4plus_anime_6B.pth
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -f "RealESRGAN_x4plus_anime_6B.pth" ]; then
|
||||
echo "Downloading data files (weights) for ESRGAN (Resolution Upscaling) x4plus_anime.."
|
||||
|
||||
curl -L -k https://github.com/xinntao/Real-ESRGAN/releases/download/v0.2.2.4/RealESRGAN_x4plus_anime_6B.pth > RealESRGAN_x4plus_anime_6B.pth
|
||||
|
||||
if [ -f "RealESRGAN_x4plus_anime_6B.pth" ]; then
|
||||
model_size=`ls -l RealESRGAN_x4plus_anime_6B.pth | awk '{print $5}'`
|
||||
if [ ! "$model_size" -eq "17938799" ]; then
|
||||
printf "\n\nError: The downloaded ESRGAN x4plus_anime model file was invalid! Bytes downloaded: $model_size\n\n"
|
||||
printf "\n\nError downloading the data files (weights) for ESRGAN (Resolution Upscaling) x4plus_anime. Sorry about that, please try to:\n 1. Run this installer again.\n 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/blob/main/Troubleshooting.md\n 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\n 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues\nThanks!\n\n"
|
||||
read -p "Press any key to continue"
|
||||
exit
|
||||
fi
|
||||
else
|
||||
printf "\n\nError downloading the data files (weights) for ESRGAN (Resolution Upscaling) x4plus_anime. Sorry about that, please try to:\n 1. Run this installer again.\n 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/blob/main/Troubleshooting.md\n 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\n 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues\nThanks!\n\n"
|
||||
read -p "Press any key to continue"
|
||||
exit
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
if [ `grep -c sd_install_complete ../scripts/install_status.txt` -gt "0" ]; then
|
||||
echo sd_weights_downloaded >> ../scripts/install_status.txt
|
||||
echo sd_install_complete >> ../scripts/install_status.txt
|
||||
fi
|
||||
|
||||
printf "\n\nStable Diffusion is ready!\n\n"
|
||||
|
||||
SD_PATH=`pwd`
|
||||
export PYTHONPATH="$SD_PATH;$SD_PATH/env/lib/python3.8/site-packages"
|
||||
echo "PYTHONPATH=$PYTHONPATH"
|
||||
|
||||
cd ..
|
||||
export SD_UI_PATH=`pwd`/ui
|
||||
cd stable-diffusion
|
||||
|
||||
python --version
|
||||
|
||||
uvicorn server:app --app-dir "$SD_UI_PATH" --port 9000 --host 0.0.0.0
|
||||
|
||||
read -p "Press any key to continue"
|
@ -1,6 +0,0 @@
|
||||
@call conda --version
|
||||
@call git --version
|
||||
|
||||
cd %CONDA_PREFIX%\..\scripts
|
||||
|
||||
on_env_start.bat
|
@ -1,12 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
conda-unpack
|
||||
|
||||
source $CONDA_PREFIX/etc/profile.d/conda.sh
|
||||
|
||||
conda --version
|
||||
git --version
|
||||
|
||||
cd $CONDA_PREFIX/../scripts
|
||||
|
||||
./on_env_start.sh
|
@ -1,10 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
source installer/bin/activate
|
||||
|
||||
conda-unpack
|
||||
|
||||
conda --version
|
||||
git --version
|
||||
|
||||
scripts/on_env_start.sh
|
@ -1,2 +0,0 @@
|
||||
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem' -Name LongPathsEnabled -Type DWord -Value 1
|
||||
pause
|
18
start.sh
Executable file
@ -0,0 +1,18 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "Stable Diffusion UI - v2.5"
|
||||
echo ""
|
||||
|
||||
export SD_BASE_DIR=$(pwd)
|
||||
|
||||
echo "Working in $SD_BASE_DIR"
|
||||
|
||||
# Setup the packages required for the installer
|
||||
installer/bootstrap/bootstrap.sh
|
||||
|
||||
# Test the bootstrap
|
||||
git --version
|
||||
python --version
|
||||
|
||||
# Download the rest of the installer and UI
|
||||
installer/installer/start.sh
|
@ -1,87 +0,0 @@
|
||||
const path = require("path");
|
||||
|
||||
module.exports = {
|
||||
env: {
|
||||
browser: true,
|
||||
es2021: true,
|
||||
},
|
||||
parser: "@typescript-eslint/parser",
|
||||
parserOptions: {
|
||||
ecmaVersion: "latest",
|
||||
sourceType: "module",
|
||||
ecmaFeatures: {
|
||||
jsx: true,
|
||||
},
|
||||
tsconfigRootDir: __dirname,
|
||||
},
|
||||
|
||||
plugins: ["react"],
|
||||
|
||||
extends: [
|
||||
"prettier",
|
||||
"plugin:react/recommended",
|
||||
"standard-with-typescript",
|
||||
"plugin:i18next/recommended",
|
||||
"plugin:i18n-json/recommended",
|
||||
],
|
||||
settings: {
|
||||
react: {
|
||||
version: "detect",
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
// general things turned off for now
|
||||
"no-debugger": "warn",
|
||||
"eol-last": "off",
|
||||
"comma-dangle": ["off", "always-multiline"],
|
||||
"no-void": ["off"],
|
||||
"array-callback-return": ["off"],
|
||||
"spaced-comment": ["off"],
|
||||
"padded-blocks": ["off"],
|
||||
"no-multiple-empty-lines": ["off", { max: 2, maxEOF: 1 }],
|
||||
quotes: ["off", "double"],
|
||||
semi: ["off", "always"],
|
||||
yoda: ["off"],
|
||||
eqeqeq: ["off"],
|
||||
"react/display-name": "warn",
|
||||
|
||||
// TS THINGS WE DONT WANT
|
||||
"@typescript-eslint/explicit-function-return-type": "off",
|
||||
"@typescript-eslint/ban-ts-comment": "off",
|
||||
|
||||
// these are things that fight with prettier
|
||||
"@typescript-eslint/comma-dangle": "off",
|
||||
"@typescript-eslint/space-before-function-paren": "off",
|
||||
"@typescript-eslint/quotes": "off",
|
||||
"@typescript-eslint/semi": "off",
|
||||
"@typescript-eslint/brace-style": "off",
|
||||
"@typescript-eslint/indent": "off",
|
||||
"@typescript-eslint/member-delimiter-style": "off",
|
||||
|
||||
// TS WARNINGS WE WANT
|
||||
"@typescript-eslint/no-unused-vars": "warn",
|
||||
"@typescript-eslint/no-non-null-assertion": "warn",
|
||||
|
||||
// i18n stuff no string literal works but turned off for now
|
||||
"i18next/no-literal-string": "off",
|
||||
// still need to figure out how to get this to work
|
||||
// it should error if we dont haev all the keys in the translation file
|
||||
"i18n-json/identical-keys": [
|
||||
"error",
|
||||
{
|
||||
filePath: {
|
||||
"home.json/": path.resolve("./Translation/locales/en/home.json"),
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: ["*.ts", "*.tsx"],
|
||||
parserOptions: {
|
||||
project: ["./tsconfig.json"], // Specify it only for TypeScript files
|
||||
},
|
||||
},
|
||||
],
|
||||
// eslint-disable-next-line semi
|
||||
};
|
18
ui/frontend/build_src/.gitignore
vendored
@ -1,18 +0,0 @@
|
||||
# local ignores - We could move these to the global ignores,
|
||||
# but I think it makes sense to keep them here
|
||||
|
||||
# env
|
||||
*.local
|
||||
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
# installed dependencies
|
||||
node_modules
|
||||
|
@ -1,17 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="icon" type="image/png" href="/media/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="icon" type="image/png" href="/media/favicon-32x32.png" sizes="32x32">
|
||||
<meta name="color-scheme" content="dark light" />
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.0/css/all.min.css">
|
||||
<title>Stable Diffusion UI</title>
|
||||
</head>
|
||||
<body>
|
||||
<!-- The react app entry point. Currently no ui just poc importing and logging -->
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/main.tsx"></script>
|
||||
</body>
|
||||
</html>
|
8225
ui/frontend/build_src/package-lock.json
generated
@ -1,56 +0,0 @@
|
||||
{
|
||||
"name": "react-ts",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"pretty": "prettier --write .",
|
||||
"dev": "vite",
|
||||
"build": "tsc && vite build --emptyOutDir",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@headlessui/react": "^1.7.2",
|
||||
"@tanstack/react-location": "^3.7.4",
|
||||
"@tanstack/react-query": "^4.2.3",
|
||||
"@tanstack/react-query-devtools": "^4.2.3",
|
||||
"@vanilla-extract/css": "^1.9.0",
|
||||
"@vanilla-extract/css-utils": "^0.1.2",
|
||||
"@vanilla-extract/recipes": "^0.2.5",
|
||||
"@vanilla-extract/vite-plugin": "^3.5.0",
|
||||
"i18next": "^21.9.2",
|
||||
"immer": "^9.0.15",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-i18next": "^11.18.6",
|
||||
"uuid": "^9.0.0",
|
||||
"zustand": "^4.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^18.7.18",
|
||||
"@types/react": "^18.0.17",
|
||||
"@types/react-dom": "^18.0.6",
|
||||
"@types/uuid": "^8.3.4",
|
||||
"@typescript-eslint/eslint-plugin": "^5.37.0",
|
||||
"@typescript-eslint/parser": "^5.37.0",
|
||||
"@vitejs/plugin-react": "^2.0.1",
|
||||
"eslint": "^8.23.1",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-config-standard-with-typescript": "^23.0.0",
|
||||
"eslint-plugin-i18n-json": "^4.0.0",
|
||||
"eslint-plugin-i18next": "^6.0.0-4",
|
||||
"eslint-plugin-import": "^2.26.0",
|
||||
"eslint-plugin-n": "^15.2.5",
|
||||
"eslint-plugin-promise": "^6.0.1",
|
||||
"eslint-plugin-react": "^7.31.8",
|
||||
"prettier": "^2.7.1",
|
||||
"typescript": "^4.8.3",
|
||||
"vite": "^3.0.7",
|
||||
"vite-plugin-eslint": "^1.8.1"
|
||||
},
|
||||
"overrides": {
|
||||
"@vanilla-extract/vite-plugin": {
|
||||
"vite": "^3"
|
||||
}
|
||||
}
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
module.exports = {
|
||||
singleQuote: true,
|
||||
tabWidth: 2,
|
||||
semi: true,
|
||||
trailingComma: "es5",
|
||||
endOfLine: "lf",
|
||||
};
|
@ -1,21 +0,0 @@
|
||||
import React from "react";
|
||||
import { ReactLocation, Router } from "@tanstack/react-location";
|
||||
import Home from "./pages/Home";
|
||||
import Settings from "./pages/Settings";
|
||||
import "./Translation/config";
|
||||
const location = new ReactLocation();
|
||||
|
||||
function App() {
|
||||
|
||||
return (
|
||||
<Router
|
||||
location={location}
|
||||
routes={[
|
||||
{ path: "/", element: <Home /> },
|
||||
{ path: "/settings", element: <Settings /> },
|
||||
]}
|
||||
></Router>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
@ -1,32 +0,0 @@
|
||||
import i18n from "i18next";
|
||||
// this should be updated to an interface
|
||||
import ENTranslation from "./locales/en/home.json";
|
||||
import ESTranslation from "./locales/es/home.json";
|
||||
import { initReactI18next } from "react-i18next";
|
||||
|
||||
export const resources = {
|
||||
en: {
|
||||
translation: ENTranslation,
|
||||
},
|
||||
es: {
|
||||
translation: ESTranslation,
|
||||
},
|
||||
} as const;
|
||||
i18n
|
||||
.use(initReactI18next)
|
||||
.init({
|
||||
lng: "en",
|
||||
interpolation: {
|
||||
escapeValue: false,
|
||||
},
|
||||
resources,
|
||||
})
|
||||
.then(() => {
|
||||
console.log("i18n initialized");
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error("i18n initialization failed", err);
|
||||
})
|
||||
.finally(() => {
|
||||
console.log("i18n initialization finished");
|
||||
});
|
@ -1,110 +0,0 @@
|
||||
{
|
||||
"title": "Stable Diffusion UI",
|
||||
"description": "",
|
||||
"navbar": {
|
||||
"home": "Home",
|
||||
"history": "History",
|
||||
"community": "Community",
|
||||
"settings": "Settings"
|
||||
},
|
||||
"land-cre": {
|
||||
"cp": "Create Profile",
|
||||
"cp-place": "Profile name",
|
||||
"pp": "Profile Picture",
|
||||
"pp-disc": "",
|
||||
"ast": "Automatically save to",
|
||||
"ast-disc": "File path to auto save your creations",
|
||||
"place": "File path",
|
||||
"cre": "Create"
|
||||
},
|
||||
"land-pre": {
|
||||
"user": "Username",
|
||||
"add": "Add Profile"
|
||||
},
|
||||
"home": {
|
||||
"status-starting": "Stable Diffusion is starting...",
|
||||
"status-ready": "Stable Diffusion is ready to use!",
|
||||
"status-error": "Stable Diffusion is not running!",
|
||||
"editor-title": "Prompt",
|
||||
"initial-img-txt": "Initial Image: (optional)",
|
||||
"initial-img-btn": "Browse...",
|
||||
"initial-img-text2": "No file selected.",
|
||||
"make-img-btn": "Make Image",
|
||||
"make-img-btn-stop": "Stop"
|
||||
},
|
||||
"in-paint": {
|
||||
"txt": "In-Painting (select the area which the AI will paint into)",
|
||||
"clear": "Clear"
|
||||
},
|
||||
"settings": {
|
||||
"base-img": "Use base image:",
|
||||
"seed": "Seed:",
|
||||
"amount-of-img": "Amount of images to make:",
|
||||
"how-many": "How many at once:",
|
||||
"stream-img": "Stream images (this will slow down image generation):",
|
||||
"width": "Width:",
|
||||
"height": "Height:",
|
||||
"sampler": "Sampler:",
|
||||
"steps": "Number of inference steps:",
|
||||
"guide-scale": "Guidance Scale:",
|
||||
"prompt-str": "Prompt Strength:",
|
||||
"live-preview": "Show a live preview of the image (disable this for faster image generation)",
|
||||
"fix-face": "Fix incorrect faces and eyes (uses GFPGAN)",
|
||||
"ups": "Upscale the image to 4x resolution using:",
|
||||
"no-ups": "No Upscaling",
|
||||
"corrected": "Show only the corrected/upscaled image"
|
||||
},
|
||||
"tags": {
|
||||
"txt": "Image Modifiers (art styles, tags etc)"
|
||||
},
|
||||
"preview-prompt": {
|
||||
"part1": "Type a prompt and press the \"Make Image\" button.",
|
||||
"part2": "You can set an \"Initial Image\" if you want to guide the AI.\n",
|
||||
"part3": "You can also add modifiers like \"Realistic\", \"Pencil Sketch\", \"ArtStation\" etc by browsing through the \"Image Modifiers\" section and selecting the desired modifiers.\n",
|
||||
"part4": "Click \"Advanced Settings\" for additional settings like seed, image size, number of images to generate etc.",
|
||||
"part5": "Enjoy! :)"
|
||||
},
|
||||
"current-task": "Current task",
|
||||
"recent-create": "Recently Created",
|
||||
"popup": {
|
||||
"use-btn": "Use Image",
|
||||
"use-btn2": "Use Image and Tags"
|
||||
},
|
||||
"history": {
|
||||
"fave": "Favorites Only",
|
||||
"search": "Search"
|
||||
},
|
||||
"advanced-settings": {
|
||||
"sound": "Play sound on task completion",
|
||||
"sound-disc": "Will play a sound so user can hear when image is done.",
|
||||
"turbo": "Turbo mode",
|
||||
"turbo-disc": "Generates images faster, but uses an additional 1 GB of GPU memory",
|
||||
"cpu": "Use CPU instead of GPU",
|
||||
"cpu-disc": "Warning: this will be *very* slow",
|
||||
"gpu": "Use full precision",
|
||||
"gpu-disc": "(for GPU-only. warning: this will consume more VRAM)",
|
||||
"beta": "Beta Features",
|
||||
"beta-disc": "Get the latest features immediately (but could be less stable). \nPlease restart the program after changing this.",
|
||||
"save": "SAVE"
|
||||
},
|
||||
"storage": {
|
||||
"ast": "Automatically save to",
|
||||
"ast-disc": "File path to auto save your creations",
|
||||
"place": "File path",
|
||||
"cps": "Cross profile sharing",
|
||||
"cps-disc": "Profiles will see suggestions from each other.",
|
||||
"acb": "Allow cloud backup",
|
||||
"acb-disc": "A button will show up for images on hover",
|
||||
"acb-place": "Choose your",
|
||||
"acc-api": "Api key",
|
||||
"acb-api-place": "Your API key",
|
||||
"save": "SAVE"
|
||||
},
|
||||
"import": {
|
||||
"imp-btn": "IMPORT",
|
||||
"exp-btn": "EXPORT",
|
||||
"disc": "It is a good idea to leave the exported file as it is. Otherwise it may not import correctly",
|
||||
"disc:2": "When importing, only profiles that are not already present on the will be added."
|
||||
},
|
||||
"about": "If you found this project useful and want to help keep it alive, please to help cover the cost of development and maintenance! Thank you for your support!\n\nPlease feel free to join the discord community or file an issue if you have any problems or suggestions in using this interface.\n\nDisclaimer: The authors of this project are not responsible for any content generated using this interface.\n\nThis license of this software forbids you from sharing any content that violates any laws, produce any harm to a person, disseminate any personal information that would be meant for harm,\nspread misinformation and target vulnerable groups. For the full list of restrictions please read the license.\n\nBy using this software, you consent to the terms and conditions of the license.\n"
|
||||
}
|
@ -1,108 +0,0 @@
|
||||
{
|
||||
"title": "Stable Diffusion UI",
|
||||
"description": "",
|
||||
"navbar": {
|
||||
"home": "Home",
|
||||
"history": "History",
|
||||
"community": "Community",
|
||||
"settings": "Settings"
|
||||
},
|
||||
"land-cre": {
|
||||
"cp": "Create Profile",
|
||||
"cp-place": "Profile name",
|
||||
"pp": "Profile Picture",
|
||||
"pp-disc": "",
|
||||
"ast": "Automatically save to",
|
||||
"ast-disc": "File path to auto save your creations",
|
||||
"place": "File path",
|
||||
"cre": "Create"
|
||||
},
|
||||
"land-pre": {
|
||||
"user": "Username",
|
||||
"add": "Add Profile"
|
||||
},
|
||||
"home": {
|
||||
"status-starting": "Stable Diffusion is starting...",
|
||||
"status-ready": "Stable Diffusion is ready to use!",
|
||||
"status-error": "Stable Diffusion is not running!",
|
||||
"editor-title": "Prompt",
|
||||
"initial-img-txt": "Initial Image: (optional)",
|
||||
"initial-img-btn": "Browse...",
|
||||
"initial-img-text2": "No file selected.",
|
||||
"make-img-btn": "Make Image",
|
||||
"make-img-btn-stop": "Stop"
|
||||
},
|
||||
"in-paint": {
|
||||
"txt": "In-Painting (select the area which the AI will paint into)",
|
||||
"clear": "Clear"
|
||||
},
|
||||
"settings": {
|
||||
"base-img": "Use base image:",
|
||||
"seed": "Seed:",
|
||||
"amount-of-img": "Amount of images to make:",
|
||||
"how-many": "How many at once:",
|
||||
"width": "Width:",
|
||||
"height": "Height:",
|
||||
"steps": "Number of inference steps:",
|
||||
"guide-scale": "Guidance Scale:",
|
||||
"prompt-str": "Prompt Strength:",
|
||||
"live-preview": "Show a live preview of the image (disable this for faster image generation)",
|
||||
"fix-face": "Fix incorrect faces and eyes (uses GFPGAN)",
|
||||
"ups": "Upscale the image to 4x resolution using:",
|
||||
"no-ups": "No Upscaling",
|
||||
"corrected": "Show only the corrected/upscaled image"
|
||||
},
|
||||
"tags": {
|
||||
"txt": "Image Modifiers (art styles, tags etc)"
|
||||
},
|
||||
"preview-prompt": {
|
||||
"part1": "Type a prompt and press the \"Make Image\" button.",
|
||||
"part2": "You can set an \"Initial Image\" if you want to guide the AI.\n",
|
||||
"part3": "You can also add modifiers like \"Realistic\", \"Pencil Sketch\", \"ArtStation\" etc by browsing through the \"Image Modifiers\" section and selecting the desired modifiers.\n",
|
||||
"part4": "Click \"Advanced Settings\" for additional settings like seed, image size, number of images to generate etc.",
|
||||
"part5": "Enjoy! :)"
|
||||
},
|
||||
"current-task": "Current task",
|
||||
"recent-create": "Recently Created",
|
||||
"popup": {
|
||||
"use-btn": "Use Image",
|
||||
"use-btn2": "Use Image and Tags"
|
||||
},
|
||||
"history": {
|
||||
"fave": "Favorites Only",
|
||||
"search": "Search"
|
||||
},
|
||||
"advanced-settings": {
|
||||
"sound": "Play sound on task completion",
|
||||
"sound-disc": "Will play a sound so user can hear when image is done.",
|
||||
"turbo": "Turbo mode",
|
||||
"turbo-disc": "Generates images faster, but uses an additional 1 GB of GPU memory",
|
||||
"cpu": "Use CPU instead of GPU",
|
||||
"cpu-disc": "Warning: this will be *very* slow",
|
||||
"gpu": "Use full precision",
|
||||
"gpu-disc": "(for GPU-only. warning: this will consume more VRAM)",
|
||||
"beta": "Beta Features",
|
||||
"beta-disc": "Get the latest features immediately (but could be less stable). \nPlease restart the program after changing this.",
|
||||
"save": "SAVE"
|
||||
},
|
||||
"storage": {
|
||||
"ast": "Automatically save to",
|
||||
"ast-disc": "File path to auto save your creations",
|
||||
"place": "File path",
|
||||
"cps": "Cross profile sharing",
|
||||
"cps-disc": "Profiles will see suggestions from each other.",
|
||||
"acb": "Allow cloud backup",
|
||||
"acb-disc": "A button will show up for images on hover",
|
||||
"acb-place": "Choose your",
|
||||
"acc-api": "Api key",
|
||||
"acb-api-place": "Your API key",
|
||||
"save": "SAVE"
|
||||
},
|
||||
"import": {
|
||||
"imp-btn": "IMPORT",
|
||||
"exp-btn": "EXPORT",
|
||||
"disc": "It is a good idea to leave the exported file as it is. Otherwise it may not import correctly",
|
||||
"disc:2": "When importing, only profiles that are not already present on the will be added."
|
||||
},
|
||||
"about": "If you found this project useful and want to help keep it alive, please to help cover the cost of development and maintenance! Thank you for your support!\n\nPlease feel free to join the discord community or file an issue if you have any problems or suggestions in using this interface.\n\nDisclaimer: The authors of this project are not responsible for any content generated using this interface.\n\nThis license of this software forbids you from sharing any content that violates any laws, produce any harm to a person, disseminate any personal information that would be meant for harm,\nspread misinformation and target vulnerable groups. For the full list of restrictions please read the license.\n\nBy using this software, you consent to the terms and conditions of the license.\n"
|
||||
}
|
@ -1,146 +0,0 @@
|
||||
/**
|
||||
* basic server health
|
||||
*/
|
||||
|
||||
import type { SAMPLER_OPTIONS } from "../stores/imageCreateStore";
|
||||
|
||||
// when we are on dev we want to specifiy 9000 as the port for the backend
|
||||
// when we are on prod we want be realtive to the current url
|
||||
export const API_URL = import.meta.env.DEV ? "http://localhost:9000" : "";
|
||||
|
||||
export const HEALTH_PING_INTERVAL = 5000; // 5 seconds
|
||||
export const healthPing = async () => {
|
||||
const pingUrl = `${API_URL}/ping`;
|
||||
const response = await fetch(pingUrl);
|
||||
const data = await response.json();
|
||||
return data;
|
||||
};
|
||||
|
||||
/**
|
||||
* the local list of modifications
|
||||
*/
|
||||
export const loadModifications = async () => {
|
||||
const response = await fetch(`${API_URL}/modifiers.json`);
|
||||
const data = await response.json();
|
||||
return data;
|
||||
};
|
||||
|
||||
export const getSaveDirectory = async () => {
|
||||
const response = await fetch(`${API_URL}/output_dir`);
|
||||
const data = await response.json();
|
||||
return data[0];
|
||||
};
|
||||
|
||||
export const KEY_CONFIG = "config";
|
||||
export const getConfig = async () => {
|
||||
const response = await fetch(`${API_URL}/app_config`);
|
||||
const data = await response.json();
|
||||
return data;
|
||||
};
|
||||
|
||||
export const KEY_TOGGLE_CONFIG = "toggle_config";
|
||||
export const toggleBetaConfig = async (branch: string) => {
|
||||
const response = await fetch(`${API_URL}/app_config`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
update_branch: branch,
|
||||
}),
|
||||
});
|
||||
const data = await response.json();
|
||||
return data;
|
||||
};
|
||||
|
||||
/**
|
||||
* post a new request for an image
|
||||
*/
|
||||
// TODO; put hese some place better
|
||||
export interface ImageRequest {
|
||||
session_id: string;
|
||||
prompt: string;
|
||||
negative_prompt: string;
|
||||
seed: number;
|
||||
num_outputs: number;
|
||||
num_inference_steps: number;
|
||||
guidance_scale: number;
|
||||
width:
|
||||
| 128
|
||||
| 192
|
||||
| 256
|
||||
| 320
|
||||
| 384
|
||||
| 448
|
||||
| 512
|
||||
| 576
|
||||
| 640
|
||||
| 704
|
||||
| 768
|
||||
| 832
|
||||
| 896
|
||||
| 960
|
||||
| 1024;
|
||||
height:
|
||||
| 128
|
||||
| 192
|
||||
| 256
|
||||
| 320
|
||||
| 384
|
||||
| 448
|
||||
| 512
|
||||
| 576
|
||||
| 640
|
||||
| 704
|
||||
| 768
|
||||
| 832
|
||||
| 896
|
||||
| 960
|
||||
| 1024;
|
||||
// allow_nsfw: boolean
|
||||
turbo: boolean;
|
||||
use_cpu: boolean;
|
||||
use_full_precision: boolean;
|
||||
save_to_disk_path: null | string;
|
||||
use_face_correction: null | "GFPGANv1.3";
|
||||
use_upscale: null | "RealESRGAN_x4plus" | "RealESRGAN_x4plus_anime_6B" | "";
|
||||
show_only_filtered_image: boolean;
|
||||
init_image: undefined | string;
|
||||
prompt_strength: undefined | number;
|
||||
mask: undefined | string;
|
||||
sampler: typeof SAMPLER_OPTIONS[number];
|
||||
stream_progress_updates: true;
|
||||
stream_image_progress: boolean;
|
||||
|
||||
}
|
||||
|
||||
export interface ImageOutput {
|
||||
data: string;
|
||||
path_abs: string | null;
|
||||
seed: number;
|
||||
}
|
||||
|
||||
export interface ImageReturnType {
|
||||
output: ImageOutput[];
|
||||
request: ImageRequest;
|
||||
status: string;
|
||||
}
|
||||
|
||||
export const MakeImageKey = "MakeImage";
|
||||
export const doMakeImage = async (reqBody: ImageRequest) => {
|
||||
const res = await fetch(`${API_URL}/image`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(reqBody),
|
||||
});
|
||||
return res;
|
||||
};
|
||||
|
||||
export const doStopImage = async () => {
|
||||
|
||||
const response = await fetch(`${API_URL}/image/stop`);
|
||||
const data = await response.json();
|
||||
return data;
|
||||
};
|
@ -1,140 +0,0 @@
|
||||
// would prefer to use a var here, but it doesn't work
|
||||
// vars: {
|
||||
// '--button-base-saturation': vars.colorMod.saturation.normal,
|
||||
// '--button-base-lightness': vars.colorMod.lightness.normal,
|
||||
// },
|
||||
|
||||
|
||||
import { recipe } from "@vanilla-extract/recipes";
|
||||
import { vars } from "../../styles/theme/index.css";
|
||||
|
||||
export const buttonStyle = recipe({
|
||||
|
||||
base: {
|
||||
fontSize: vars.fonts.sizes.Subheadline,
|
||||
fontWeight: "bold",
|
||||
color: vars.colors.text.normal,
|
||||
padding: vars.spacing.small,
|
||||
border: "0",
|
||||
borderRadius: vars.trim.smallBorderRadius,
|
||||
},
|
||||
|
||||
variants: {
|
||||
color: {
|
||||
primary: {
|
||||
// @ts-expect-error
|
||||
'--button-hue': vars.brandHue,
|
||||
'--button-base-saturation': vars.colorMod.saturation.normal,
|
||||
'--button-base-lightness': vars.colorMod.lightness.normal,
|
||||
},
|
||||
secondary: {
|
||||
// @ts-expect-error
|
||||
'--button-hue': vars.secondaryHue,
|
||||
'--button-base-saturation': vars.colorMod.saturation.normal,
|
||||
'--button-base-lightness': vars.colorMod.lightness.normal,
|
||||
},
|
||||
tertiary: {
|
||||
// @ts-expect-error
|
||||
'--button-hue': vars.tertiaryHue,
|
||||
'--button-base-saturation': vars.colorMod.saturation.normal,
|
||||
'--button-base-lightness': vars.colorMod.lightness.normal,
|
||||
},
|
||||
cancel: {
|
||||
// @ts-expect-error
|
||||
'--button-hue': vars.errorHue,
|
||||
'--button-base-saturation': vars.colorMod.saturation.normal,
|
||||
'--button-base-lightness': vars.colorMod.lightness.normal,
|
||||
},
|
||||
accent: {
|
||||
// @ts-expect-error
|
||||
'--button-hue': vars.backgroundAccentHue,
|
||||
'--button-base-saturation': vars.backgroundAccentSaturation,
|
||||
'--button-base-lightness': vars.backgroundAccentLightness,
|
||||
},
|
||||
clear: {
|
||||
backgroundColor: "transparent",
|
||||
},
|
||||
},
|
||||
|
||||
type: {
|
||||
fill: {
|
||||
backgroundColor: `hsl(var(--button-hue),var(--button-base-saturation),${vars.colorMod.lightness.normal})`,
|
||||
border: `1px solid hsl(var(--button-hue),var(--button-base-saturation),${vars.colorMod.lightness.normal})`,
|
||||
":hover": {
|
||||
backgroundColor: `hsl(var(--button-hue),${vars.colorMod.saturation.bright},${vars.colorMod.lightness.normal})`,
|
||||
border: `1px solid hsl(var(--button-hue),${vars.colorMod.saturation.bright},${vars.colorMod.lightness.normal})`,
|
||||
},
|
||||
":active": {
|
||||
backgroundColor: `hsl(var(--button-hue),${vars.colorMod.saturation.bright},${vars.colorMod.lightness.dim})`,
|
||||
border: `1px solid hsl(var(--button-hue),${vars.colorMod.saturation.bright},${vars.colorMod.lightness.dim})`,
|
||||
},
|
||||
|
||||
":focus": {
|
||||
backgroundColor: `hsl(var(--button-hue),${vars.colorMod.saturation.bright},${vars.colorMod.lightness.dim})`,
|
||||
border: `1px solid hsl(var(--button-hue),${vars.colorMod.saturation.bright},${vars.colorMod.lightness.dim})`,
|
||||
},
|
||||
|
||||
":disabled": {
|
||||
backgroundColor: `hsl(var(--button-hue),${vars.colorMod.saturation.dim},${vars.colorMod.lightness.dim})`,
|
||||
border: `1px solid hsl(var(--button-hue),${vars.colorMod.saturation.dim},${vars.colorMod.lightness.dim})`,
|
||||
},
|
||||
},
|
||||
outline: {
|
||||
backgroundColor: "transparent",
|
||||
border: `1px solid hsl(var(--button-hue),var(--button-base-saturation),${vars.colorMod.lightness.normal})`,
|
||||
":hover": {
|
||||
borderColor: `hsl(var(--button-hue),${vars.colorMod.saturation.bright},${vars.colorMod.lightness.normal})`,
|
||||
},
|
||||
|
||||
":active": {
|
||||
borderColor: `hsl(var(--button-hue),${vars.colorMod.saturation.bright},${vars.colorMod.lightness.dim})`,
|
||||
},
|
||||
|
||||
":focus": {
|
||||
borderColor: `hsl(var(--button-hue),${vars.colorMod.saturation.bright},${vars.colorMod.lightness.dim})`,
|
||||
},
|
||||
|
||||
":disabled": {
|
||||
borderColor: `hsl(var(--button-hue),${vars.colorMod.saturation.dim},${vars.colorMod.lightness.dim})`,
|
||||
},
|
||||
},
|
||||
action: {
|
||||
backgroundColor: "transparent",
|
||||
color: `hsl(var(--button-hue),var(--button-base-saturation),${vars.colorMod.lightness.normal})`,
|
||||
textDecoration: "underline",
|
||||
":hover": {
|
||||
color: `hsl(var(--button-hue),${vars.colorMod.saturation.bright},${vars.colorMod.lightness.normal})`,
|
||||
},
|
||||
|
||||
":active": {
|
||||
color: `hsl(var(--button-hue),${vars.colorMod.saturation.bright},${vars.colorMod.lightness.dim})`,
|
||||
},
|
||||
|
||||
":focus": {
|
||||
color: `hsl(var(--button-hue),${vars.colorMod.saturation.bright},${vars.colorMod.lightness.dim})`,
|
||||
},
|
||||
|
||||
":disabled": {
|
||||
color: `hsl(var(--button-hue),${vars.colorMod.saturation.dim},${vars.colorMod.lightness.dim})`,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
size: {
|
||||
slim: {
|
||||
padding: vars.spacing.min,
|
||||
fontSize: vars.fonts.sizes.Caption,
|
||||
},
|
||||
large: {
|
||||
width: "100%",
|
||||
fontSize: vars.fonts.sizes.Headline,
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
defaultVariants: {
|
||||
color: "primary",
|
||||
type: "fill",
|
||||
},
|
||||
|
||||
});
|
@ -1,51 +0,0 @@
|
||||
import { recipe } from "@vanilla-extract/recipes";
|
||||
import { vars } from "../../styles/theme/index.css";
|
||||
|
||||
export const card = recipe({
|
||||
|
||||
base: {
|
||||
color: vars.colors.text.normal,
|
||||
padding: vars.spacing.medium,
|
||||
},
|
||||
|
||||
variants: {
|
||||
backing: {
|
||||
normal: {
|
||||
background: vars.backgroundMain,
|
||||
},
|
||||
light: {
|
||||
background: vars.backgroundLight,
|
||||
},
|
||||
dark: {
|
||||
background: vars.backgroundDark,
|
||||
},
|
||||
},
|
||||
|
||||
rounded: {
|
||||
true: {
|
||||
borderRadius: vars.trim.smallBorderRadius,
|
||||
},
|
||||
},
|
||||
|
||||
info: {
|
||||
true: {
|
||||
background: vars.backgroundDark,
|
||||
border: `1px solid ${vars.backgroundAccentMain}`,
|
||||
},
|
||||
},
|
||||
|
||||
level: {
|
||||
flat: {},
|
||||
1: { boxShadow: "0 4px 8px 0 rgba(0, 0, 0, 0.15), 0 6px 20px 0 rgba(0, 0, 0, 0.15)" },
|
||||
2: { boxShadow: "0 4px 8px 0 rgba(0, 0, 0, 0.15), 0 6px 20px 0 rgba(0, 0, 0, 0.15)" },
|
||||
3: { boxShadow: "0 4px 8px 0 rgba(0, 0, 0, 0.15), 0 6px 20px 0 rgba(0, 0, 0, 0.15)" },
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
backing: "light",
|
||||
level: 'flat',
|
||||
rounded: true,
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -1,24 +0,0 @@
|
||||
import { recipe } from "@vanilla-extract/recipes";
|
||||
import { vars } from "../../styles/theme/index.css";
|
||||
|
||||
|
||||
export const card = recipe({
|
||||
base: {
|
||||
background: vars.backgroundMain,
|
||||
color: vars.colors.text.normal,
|
||||
padding: vars.spacing.medium,
|
||||
borderRadius: vars.trim.smallBorderRadius,
|
||||
},
|
||||
variants: {
|
||||
level: {
|
||||
1: { boxShadow: "0 4px 8px 0 rgba(0, 0, 0, 0.15), 0 6px 20px 0 rgba(0, 0, 0, 0.15)" },
|
||||
2: { boxShadow: "0 4px 8px 0 rgba(0, 0, 0, 0.15), 0 6px 20px 0 rgba(0, 0, 0, 0.15)" },
|
||||
3: { boxShadow: "0 4px 8px 0 rgba(0, 0, 0, 0.15), 0 6px 20px 0 rgba(0, 0, 0, 0.15)" },
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
level: 1,
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -1,39 +0,0 @@
|
||||
|
||||
import { style, globalStyle } from "@vanilla-extract/css";
|
||||
|
||||
// import { recipe } from "@vanilla-extract/recipes";
|
||||
import { vars } from "../../styles/theme/index.css";
|
||||
|
||||
import {
|
||||
card
|
||||
} from "./card.css";
|
||||
|
||||
export const PopoverMain = style({
|
||||
position: 'relative'
|
||||
});
|
||||
|
||||
export const PopoverButtonStyle = style({
|
||||
backgroundColor: "transparent",
|
||||
border: "0 none",
|
||||
cursor: "pointer",
|
||||
padding: vars.spacing.none,
|
||||
fontSize: vars.fonts.sizes.Subheadline,
|
||||
});
|
||||
|
||||
globalStyle(`${PopoverButtonStyle} > i`, {
|
||||
marginRight: vars.spacing.small,
|
||||
});
|
||||
|
||||
export const PopoverPanelMain = style([card(
|
||||
{
|
||||
backing: 'dark',
|
||||
level: 2,
|
||||
}
|
||||
), {
|
||||
position: 'absolute',
|
||||
top: '100%',
|
||||
right: '0',
|
||||
zIndex: '1',
|
||||
}]);
|
||||
|
||||
|
@ -1,19 +0,0 @@
|
||||
import { style, } from "@vanilla-extract/css";
|
||||
|
||||
// import { recipe } from "@vanilla-extract/recipes";
|
||||
import { vars } from "../../styles/theme/index.css";
|
||||
|
||||
export const SwitchGroupMain = style({
|
||||
});
|
||||
|
||||
export const SwitchMain = style({
|
||||
});
|
||||
|
||||
export const SwitchLabel = style({
|
||||
});
|
||||
|
||||
export const SwitchEnabled = style({
|
||||
});
|
||||
|
||||
export const SwitchPill = style({
|
||||
});
|
@ -1,60 +0,0 @@
|
||||
import { style } from '@vanilla-extract/css';
|
||||
import { recipe } from "@vanilla-extract/recipes";
|
||||
import { vars } from "../../styles/theme/index.css";
|
||||
|
||||
export const tabStyles = recipe({
|
||||
base: {
|
||||
background: vars.backgroundMain,
|
||||
color: vars.colors.text.normal,
|
||||
padding: vars.spacing.small,
|
||||
borderRadius: `${vars.trim.smallBorderRadius} ${vars.trim.smallBorderRadius} 0 0`,
|
||||
border: `1px solid ${vars.backgroundLight}`,
|
||||
borderBottom: 'none',
|
||||
marginLeft: vars.spacing.small,
|
||||
boxShadow: `0px -1px 4px -2px ${vars.backgroundAccentMain} inset`,
|
||||
width: 'fit-content',
|
||||
':focus': {
|
||||
outline: 'none',
|
||||
},
|
||||
},
|
||||
|
||||
variants: {
|
||||
selected: {
|
||||
true: {
|
||||
background: vars.backgroundLight,
|
||||
color: vars.colors.text.normal,
|
||||
boxShadow: `0px -1px 4px -2px ${vars.backgroundDark} inset`,
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
export const tabPanelStyles = recipe({
|
||||
base: {
|
||||
color: vars.colors.text.normal,
|
||||
// borderRadius: `0 0 ${vars.trim.smallBorderRadius} ${vars.trim.smallBorderRadius}`,
|
||||
background: vars.backgroundLight,
|
||||
padding: vars.spacing.medium,
|
||||
flexGrow: 1,
|
||||
overflow: 'auto',
|
||||
// "::-webkit-scrollbar": {
|
||||
// width: "4px",
|
||||
// },
|
||||
|
||||
},
|
||||
variants: {
|
||||
|
||||
backing: {
|
||||
normal: {
|
||||
background: vars.backgroundMain,
|
||||
},
|
||||
light: {
|
||||
background: vars.backgroundLight,
|
||||
},
|
||||
dark: {
|
||||
background: vars.backgroundDark,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
@ -1,34 +0,0 @@
|
||||
import { style, globalStyle } from "@vanilla-extract/css";
|
||||
import { vars } from "../../../styles/theme/index.css";
|
||||
import {
|
||||
tabPanelStyles,
|
||||
} from "../../_recipes/tabs_headless.css";
|
||||
|
||||
|
||||
export const TabpanelScrollFlop = style([tabPanelStyles(), {
|
||||
direction: 'rtl',
|
||||
// position: 'relative',
|
||||
overflow: 'overlay',
|
||||
"::-webkit-scrollbar": {
|
||||
position: 'absolute',
|
||||
width: "6px",
|
||||
backgroundColor: vars.backgroundAccentMain,
|
||||
},
|
||||
|
||||
"::-webkit-scrollbar-thumb": {
|
||||
backgroundColor: vars.backgroundDark,
|
||||
borderRadius: "4px",
|
||||
},
|
||||
|
||||
|
||||
// "::-webkit-scrollbar-button: {
|
||||
// backgroundColor: vars.backgroundDark,
|
||||
// }
|
||||
|
||||
|
||||
}]);
|
||||
|
||||
globalStyle(`${TabpanelScrollFlop} > *`, {
|
||||
direction: 'ltr',
|
||||
|
||||
});
|
@ -1,61 +0,0 @@
|
||||
import React, { Fragment } from "react";
|
||||
import { Tab } from '@headlessui/react';
|
||||
|
||||
|
||||
|
||||
import CreationPanel from "../../organisms/creationPanel";
|
||||
import QueueDisplay from "../../organisms/queueDisplay";
|
||||
|
||||
import ProcessingStatus from "../../molecules/queueStatusTab";
|
||||
|
||||
import {
|
||||
tabStyles,
|
||||
} from "../../_recipes/tabs_headless.css";
|
||||
|
||||
import {
|
||||
TabpanelScrollFlop
|
||||
} from "./creationTabs.css";
|
||||
|
||||
export default function CreationTabs() {
|
||||
|
||||
return (
|
||||
<Tab.Group>
|
||||
<Tab.List>
|
||||
<Tab as={Fragment}>
|
||||
{({ selected }) => (
|
||||
<button
|
||||
className={tabStyles({
|
||||
selected,
|
||||
})}
|
||||
>
|
||||
Create
|
||||
</button>
|
||||
)}
|
||||
</Tab>
|
||||
|
||||
<Tab as={Fragment}>
|
||||
{({ selected }) => (
|
||||
|
||||
<button
|
||||
className={tabStyles({
|
||||
selected,
|
||||
})}
|
||||
>
|
||||
<ProcessingStatus></ProcessingStatus>
|
||||
</button>
|
||||
)}
|
||||
</Tab>
|
||||
|
||||
|
||||
</Tab.List>
|
||||
<Tab.Panels className={TabpanelScrollFlop}>
|
||||
<Tab.Panel>
|
||||
<CreationPanel></CreationPanel>
|
||||
</Tab.Panel>
|
||||
<Tab.Panel>
|
||||
<QueueDisplay></QueueDisplay>
|
||||
</Tab.Panel>
|
||||
</Tab.Panels>
|
||||
</Tab.Group>
|
||||
);
|
||||
}
|
@ -1,107 +0,0 @@
|
||||
import { style, globalStyle } from "@vanilla-extract/css";
|
||||
import { vars } from "../../../styles/theme/index.css";
|
||||
|
||||
import {
|
||||
tabStyles
|
||||
} from "../../_recipes/tabs_headless.css";
|
||||
|
||||
|
||||
export const basicDisplayLayout = style({
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
display: "grid",
|
||||
gridTemplateColumns: "1fr 250px",
|
||||
gridTemplateRows: "1fr 250px",
|
||||
gridTemplateAreas: `
|
||||
"content info"
|
||||
"history history"`,
|
||||
|
||||
overflow: "hidden",
|
||||
|
||||
selectors: {
|
||||
'&[data-hide-info]': {
|
||||
gridTemplateColumns: "1fr",
|
||||
gridTemplateRows: "1fr 250px",
|
||||
// gridTemplateAreas: `
|
||||
// "content"
|
||||
// "history"`,
|
||||
},
|
||||
'&[data-hide-history]': {
|
||||
gridTemplateColumns: "1fr 250px",
|
||||
gridTemplateRows: "1fr 0px",
|
||||
// gridTemplateAreas: `
|
||||
// "content info"`,
|
||||
},
|
||||
'&[data-hide-info][data-hide-history]': {
|
||||
gridTemplateColumns: "1fr 0px",
|
||||
gridTemplateRows: "1fr 0px",
|
||||
// gridTemplateAreas: `
|
||||
// "content"`,
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
// "@media": {
|
||||
// "screen and (max-width: 800px)": {
|
||||
// gridTemplateColumns: "1fr",
|
||||
// gridTemplateRows: "100px 300px 1fr",
|
||||
// gridTemplateAreas: `
|
||||
// "header"
|
||||
// "create"
|
||||
// "display"
|
||||
// `,
|
||||
// },
|
||||
// },
|
||||
|
||||
});
|
||||
|
||||
// globalStyle(`${basicDisplayLayout}.hideHistory`, {
|
||||
|
||||
// });
|
||||
|
||||
export const contentLayout = style({
|
||||
gridArea: "content",
|
||||
});
|
||||
|
||||
export const infoLayout = style({
|
||||
gridArea: "info",
|
||||
position: "relative",
|
||||
});
|
||||
|
||||
export const historyLayout = style({
|
||||
gridArea: "history",
|
||||
position: "relative",
|
||||
});
|
||||
|
||||
globalStyle(`${historyLayout} > button`, {
|
||||
position: "absolute",
|
||||
top: '-29px',
|
||||
});
|
||||
|
||||
export const displayContainer = style({
|
||||
flexGrow: 1,
|
||||
overflow: 'auto',
|
||||
display: "flex",
|
||||
});
|
||||
|
||||
export const displayData = style({
|
||||
width: '250px',
|
||||
height: '100%',
|
||||
backgroundColor: 'rebeccapurple',
|
||||
position: 'relative',
|
||||
});
|
||||
|
||||
export const DataTab = style([tabStyles(), {
|
||||
position: 'absolute',
|
||||
top: '0',
|
||||
left: '0',
|
||||
|
||||
// pretty sure this is a magic number
|
||||
transformOrigin: '37% 275%',
|
||||
transform: 'rotate(-90deg)',
|
||||
}]);
|
||||
|
||||
|
||||
// export const previousImages = style({
|
||||
// minHeight: '250px',
|
||||
// });
|
@ -1,65 +0,0 @@
|
||||
|
||||
import React, { useState, useRef, useEffect } from "react";
|
||||
import { Transition } from '@headlessui/react'
|
||||
|
||||
import CurrentDisplay from "../../organisms/currentDisplay";
|
||||
import CompletedImages from "../../organisms/completedImages";
|
||||
import CurrentInfo from "../../organisms/currentInfo";
|
||||
|
||||
|
||||
import {
|
||||
tabStyles
|
||||
} from "../../_recipes/tabs_headless.css";
|
||||
|
||||
import {
|
||||
basicDisplayLayout,
|
||||
contentLayout,
|
||||
infoLayout,
|
||||
historyLayout
|
||||
} from "./basicDisplay.css";
|
||||
|
||||
export default function BasicDisplay() {
|
||||
|
||||
const [isShowingHistory, setIsShowingHistory] = useState(true)
|
||||
|
||||
const layoutRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
if (layoutRef.current != undefined) {
|
||||
// set the hide-history data attribute
|
||||
if (isShowingHistory) {
|
||||
layoutRef.current.removeAttribute('data-hide-history');
|
||||
}
|
||||
else {
|
||||
// layoutRef.current.dataset.hideHistory = "true";
|
||||
layoutRef.current.setAttribute('data-hide-history', '');
|
||||
}
|
||||
}
|
||||
}, [layoutRef, isShowingHistory]);
|
||||
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={layoutRef}
|
||||
className={basicDisplayLayout}
|
||||
>
|
||||
<div className={contentLayout}>
|
||||
<CurrentDisplay></CurrentDisplay>
|
||||
</div>
|
||||
|
||||
{/* <div className={infoLayout}>
|
||||
<CurrentInfo ></CurrentInfo>
|
||||
</div> */}
|
||||
|
||||
<div className={historyLayout}>
|
||||
<button
|
||||
className={tabStyles({})}
|
||||
onClick={() => setIsShowingHistory((isShowingHistory) => !isShowingHistory)}>
|
||||
{isShowingHistory ? "Hide History" : "Show History"}
|
||||
</button>
|
||||
<CompletedImages></CompletedImages>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
import React from "react";
|
||||
import { API_URL } from "../../../api";
|
||||
|
||||
const url = `${API_URL}/ding.mp3`;
|
||||
|
||||
const AudioDing = React.forwardRef((props, ref) => (
|
||||
// @ts-expect-error
|
||||
<audio ref={ref} style={{ display: "none" }}>
|
||||
<source src={url} type="audio/mp3" />
|
||||
</audio>
|
||||
));
|
||||
|
||||
AudioDing.displayName = "AudioDing";
|
||||
|
||||
export default AudioDing;
|
||||
|
@ -1,73 +0,0 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
|
||||
import {
|
||||
KEY_CONFIG,
|
||||
getConfig,
|
||||
KEY_TOGGLE_CONFIG,
|
||||
toggleBetaConfig,
|
||||
} from "../../../api";
|
||||
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
export default function BetaMode() {
|
||||
const { t } = useTranslation();
|
||||
// gate for the toggle
|
||||
const [shouldSetCofig, setShouldSetConfig] = useState(false);
|
||||
// next branch to get
|
||||
const [branchToGetNext, setBranchToGetNext] = useState("beta");
|
||||
|
||||
// our basic config
|
||||
const { status: configStatus, data: configData } = useQuery(
|
||||
[KEY_CONFIG],
|
||||
getConfig
|
||||
);
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
// the toggle config
|
||||
const { status: toggleStatus, data: toggleData } = useQuery(
|
||||
[KEY_TOGGLE_CONFIG],
|
||||
async () => await toggleBetaConfig(branchToGetNext),
|
||||
{
|
||||
enabled: shouldSetCofig,
|
||||
}
|
||||
);
|
||||
|
||||
// this is also in the Header Display
|
||||
// TODO: make this a custom hook
|
||||
useEffect(() => {
|
||||
if (configStatus === "success") {
|
||||
const { update_branch: updateBranch } = configData;
|
||||
|
||||
if (updateBranch === "main") {
|
||||
setBranchToGetNext("beta");
|
||||
} else {
|
||||
// setIsBeta(true);
|
||||
setBranchToGetNext("main");
|
||||
}
|
||||
}
|
||||
}, [configStatus, configData]);
|
||||
|
||||
useEffect(() => {
|
||||
if (toggleStatus === "success") {
|
||||
if (toggleData[0] === "OK") {
|
||||
// force a refetch of the config
|
||||
void queryClient.invalidateQueries([KEY_CONFIG])
|
||||
}
|
||||
setShouldSetConfig(false);
|
||||
}
|
||||
}, [toggleStatus, toggleData, setShouldSetConfig]);
|
||||
|
||||
return (
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={branchToGetNext === "main"}
|
||||
onChange={(e) => {
|
||||
setShouldSetConfig(true);
|
||||
}}
|
||||
/>🔥
|
||||
{t("advanced-settings.beta")} {t("advanced-settings.beta-disc")}
|
||||
</label>
|
||||
);
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
import React from "react";
|
||||
import { doStopImage } from "../../../api";
|
||||
import { useRequestQueue } from "../../../stores/requestQueueStore";
|
||||
|
||||
import {
|
||||
buttonStyle
|
||||
} from "../../_recipes/button.css";
|
||||
|
||||
|
||||
export default function ClearQueue() {
|
||||
|
||||
const hasQueue = useRequestQueue((state) => state.hasAnyQueue());
|
||||
const clearQueue = useRequestQueue((state) => state.clearQueue);
|
||||
|
||||
const stopAll = async () => {
|
||||
try {
|
||||
clearQueue();
|
||||
const res = await doStopImage();
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<button className={buttonStyle(
|
||||
{
|
||||
color: "cancel",
|
||||
size: "large",
|
||||
}
|
||||
)}
|
||||
disabled={!hasQueue} onClick={() => void stopAll()}>
|
||||
STOP ALL
|
||||
</button>
|
||||
);
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
import { style, globalStyle } from "@vanilla-extract/css";
|
||||
|
||||
export const DrawImageMain = style({
|
||||
position: "relative",
|
||||
});
|
||||
|
||||
globalStyle(`${DrawImageMain} > canvas`, {
|
||||
position: "absolute",
|
||||
top: "0",
|
||||
left: "0",
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
});
|
||||
|
||||
globalStyle(`${DrawImageMain} > canvas:first-of-type`, {
|
||||
opacity: ".7",
|
||||
});
|
||||
|
||||
globalStyle(`${DrawImageMain} > img`, {
|
||||
top: "0",
|
||||
left: "0",
|
||||
});
|
@ -1,194 +0,0 @@
|
||||
import React, { useRef, useState, useEffect } from "react";
|
||||
|
||||
import {
|
||||
DrawImageMain,
|
||||
} from "./drawImage.css";
|
||||
|
||||
// https://github.com/embiem/react-canvas-draw
|
||||
|
||||
interface DrawImageProps {
|
||||
imageData: string;
|
||||
brushSize: number;
|
||||
|
||||
brushShape: string;
|
||||
brushColor: string;
|
||||
isErasing: boolean;
|
||||
setData: (data: string) => void;
|
||||
}
|
||||
|
||||
export default function DrawImage({
|
||||
imageData,
|
||||
brushSize,
|
||||
brushShape,
|
||||
brushColor,
|
||||
isErasing,
|
||||
setData,
|
||||
}: DrawImageProps) {
|
||||
const drawingRef = useRef<HTMLCanvasElement>(null);
|
||||
const cursorRef = useRef<HTMLCanvasElement>(null);
|
||||
const [isUpdating, setIsUpdating] = useState(false);
|
||||
|
||||
const [canvasWidth, setCanvasWidth] = useState(512);
|
||||
const [canvasHeight, setCanvasHeight] = useState(512);
|
||||
|
||||
useEffect(() => {
|
||||
const img = new Image();
|
||||
img.onload = () => {
|
||||
setCanvasWidth(img.width);
|
||||
setCanvasHeight(img.height);
|
||||
};
|
||||
img.src = imageData;
|
||||
}, [imageData]);
|
||||
|
||||
useEffect(() => {
|
||||
// when the brush color changes, change the color of all the
|
||||
// drawn pixels to the new color
|
||||
if (drawingRef.current != null) {
|
||||
const ctx = drawingRef.current.getContext("2d");
|
||||
if (ctx != null) {
|
||||
|
||||
const imageData = ctx.getImageData(0, 0, canvasWidth, canvasHeight);
|
||||
const data = imageData.data;
|
||||
for (let i = 0; i < data.length; i += 4) {
|
||||
if (data[i + 3] > 0) {
|
||||
data[i] = parseInt(brushColor, 16);
|
||||
data[i + 1] = parseInt(brushColor, 16);
|
||||
data[i + 2] = parseInt(brushColor, 16);
|
||||
}
|
||||
}
|
||||
ctx.putImageData(imageData, 0, 0);
|
||||
}
|
||||
}
|
||||
}, [brushColor]);
|
||||
|
||||
const _handleMouseDown = (
|
||||
e: React.MouseEvent<HTMLCanvasElement, MouseEvent>
|
||||
) => {
|
||||
const {
|
||||
nativeEvent: { offsetX, offsetY },
|
||||
} = e;
|
||||
|
||||
setIsUpdating(true);
|
||||
};
|
||||
|
||||
const _handleMouseUp = (
|
||||
e: React.MouseEvent<HTMLCanvasElement, MouseEvent>
|
||||
) => {
|
||||
setIsUpdating(false);
|
||||
const canvas = drawingRef.current;
|
||||
if (canvas != null) {
|
||||
const data = canvas.toDataURL();
|
||||
setData(data);
|
||||
}
|
||||
};
|
||||
|
||||
const _drawCanvas = (x: number, y: number, brushSize: number, brushShape: string, brushColor: string | CanvasGradient | CanvasPattern) => {
|
||||
const canvas = drawingRef.current;
|
||||
if (canvas != null) {
|
||||
const ctx = canvas.getContext("2d");
|
||||
if (ctx != null) {
|
||||
if (isErasing) {
|
||||
// stack overflow https://stackoverflow.com/questions/10396991/clearing-circular-regions-from-html5-canvas
|
||||
const offset = brushSize / 2;
|
||||
ctx.clearRect(x - offset, y - offset, brushSize, brushSize);
|
||||
} else {
|
||||
ctx.beginPath();
|
||||
ctx.lineWidth = brushSize;
|
||||
// @ts-expect-error
|
||||
ctx.lineCap = brushShape;
|
||||
ctx.strokeStyle = brushColor;
|
||||
ctx.moveTo(x, y);
|
||||
ctx.lineTo(x, y);
|
||||
ctx.stroke();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const _drawCursor = (
|
||||
x: number,
|
||||
y: number,
|
||||
brushSize: number,
|
||||
brushShape: string,
|
||||
brushColor: string
|
||||
) => {
|
||||
const canvas = cursorRef.current;
|
||||
if (canvas != null) {
|
||||
const ctx = canvas.getContext("2d");
|
||||
if (ctx != null) {
|
||||
ctx.beginPath();
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
if (isErasing) {
|
||||
const offset = brushSize / 2;
|
||||
// draw a quare
|
||||
ctx.lineWidth = 2;
|
||||
ctx.lineCap = "butt";
|
||||
ctx.strokeStyle = brushColor;
|
||||
ctx.moveTo(x - offset, y - offset);
|
||||
ctx.lineTo(x + offset, y - offset);
|
||||
ctx.lineTo(x + offset, y + offset);
|
||||
ctx.lineTo(x - offset, y + offset);
|
||||
ctx.lineTo(x - offset, y - offset);
|
||||
ctx.stroke();
|
||||
} else {
|
||||
ctx.lineWidth = brushSize;
|
||||
// @ts-expect-error
|
||||
ctx.lineCap = brushShape;
|
||||
ctx.strokeStyle = brushColor;
|
||||
ctx.moveTo(x, y);
|
||||
ctx.lineTo(x, y);
|
||||
ctx.stroke();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
const _handleMouseMove = (
|
||||
e: React.MouseEvent<HTMLCanvasElement, MouseEvent>
|
||||
) => {
|
||||
const {
|
||||
nativeEvent: { offsetX: x, offsetY: y },
|
||||
} = e;
|
||||
|
||||
_drawCursor(x, y, brushSize, brushShape, brushColor);
|
||||
|
||||
if (isUpdating) {
|
||||
_drawCanvas(x, y, brushSize, brushShape, brushColor);
|
||||
}
|
||||
};
|
||||
|
||||
// function for external use
|
||||
const fillCanvas = () => {
|
||||
const canvas = drawingRef.current;
|
||||
if (canvas != null) {
|
||||
const ctx = canvas.getContext("2d");
|
||||
if (ctx != null) {
|
||||
ctx.fillStyle = brushColor;
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={DrawImageMain}>
|
||||
<img src={imageData} />
|
||||
<canvas
|
||||
ref={drawingRef}
|
||||
width={canvasWidth}
|
||||
height={canvasHeight}
|
||||
></canvas>
|
||||
<canvas
|
||||
ref={cursorRef}
|
||||
width={canvasWidth}
|
||||
height={canvasHeight}
|
||||
onMouseDown={_handleMouseDown}
|
||||
onMouseUp={_handleMouseUp}
|
||||
onMouseMove={_handleMouseMove}
|
||||
></canvas>
|
||||
</div>
|
||||
);
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
import { style, globalStyle } from "@vanilla-extract/css";
|
||||
|
||||
export const generatedImageMain = style({
|
||||
position: "relative",
|
||||
});
|
||||
|
||||
globalStyle(`${generatedImageMain} img`, {
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
objectFit: "contain",
|
||||
});
|
@ -1,25 +0,0 @@
|
||||
import React from "react";
|
||||
|
||||
import { ImageRequest } from "../../../api";
|
||||
|
||||
import {
|
||||
generatedImageMain,
|
||||
} from "./generatedImage.css";
|
||||
|
||||
interface GeneretaedImageProps {
|
||||
imageData: string | undefined;
|
||||
metadata: ImageRequest | undefined;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export default function GeneratedImage({
|
||||
imageData,
|
||||
metadata,
|
||||
className,
|
||||
}: GeneretaedImageProps) {
|
||||
return (
|
||||
<div className={[generatedImageMain, className].join(" ")}>
|
||||
<img src={imageData} alt={metadata!.prompt} />
|
||||
</div>
|
||||
);
|
||||
}
|
@ -1,276 +0,0 @@
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
import React, { useEffect, useRef } from "react";
|
||||
|
||||
import { useImageCreate } from "../../../stores/imageCreateStore";
|
||||
import {
|
||||
QueueStatus,
|
||||
useRequestQueue
|
||||
} from "../../../stores/requestQueueStore";
|
||||
|
||||
import {
|
||||
FetchingStates,
|
||||
useImageFetching
|
||||
} from "../../../stores/imageFetchingStore";
|
||||
|
||||
|
||||
import { useImageDisplay } from "../../../stores/imageDisplayStore";
|
||||
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
|
||||
import { useRandomSeed } from "../../../utils";
|
||||
import {
|
||||
ImageRequest,
|
||||
ImageReturnType,
|
||||
ImageOutput,
|
||||
doMakeImage,
|
||||
} from "../../../api";
|
||||
|
||||
import {
|
||||
buttonStyle
|
||||
} from "../../_recipes/button.css";
|
||||
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import AudioDing from "../../molecules/audioDing";
|
||||
|
||||
const idDelim = "_batch";
|
||||
|
||||
export default function MakeButton() {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const dingRef = useRef<HTMLAudioElement>();
|
||||
|
||||
const parallelCount = useImageCreate((state) => state.parallelCount);
|
||||
const builtRequest = useImageCreate((state) => state.builtRequest);
|
||||
const isRandomSeed = useImageCreate((state) => state.isRandomSeed());
|
||||
const setRequestOption = useImageCreate((state) => state.setRequestOptions);
|
||||
|
||||
const isSoundEnabled = useImageCreate((state) => state.isSoundEnabled());
|
||||
|
||||
const addtoQueue = useRequestQueue((state) => state.addtoQueue);
|
||||
const hasQueue = useRequestQueue((state) => state.hasPendingQueue());
|
||||
const { id, options } = useRequestQueue((state) => state.firstInQueue());
|
||||
const updateQueueStatus = useRequestQueue((state) => state.updateStatus);
|
||||
|
||||
const status = useImageFetching((state) => state.status);
|
||||
const setStatus = useImageFetching((state) => state.setStatus);
|
||||
const setStep = useImageFetching((state) => state.setStep);
|
||||
const setTotalSteps = useImageFetching((state) => state.setTotalSteps);
|
||||
const addProgressImage = useImageFetching((state) => state.addProgressImage);
|
||||
const setStartTime = useImageFetching((state) => state.setStartTime);
|
||||
const setNowTime = useImageFetching((state) => state.setNowTime);
|
||||
const resetForFetching = useImageFetching((state) => state.resetForFetching);
|
||||
const appendData = useImageFetching((state) => state.appendData);
|
||||
|
||||
const updateDisplay = useImageDisplay((state) => state.updateDisplay);
|
||||
|
||||
const hackJson = (jsonStr: string, id: string) => {
|
||||
|
||||
try {
|
||||
const parsed = JSON.parse(jsonStr);
|
||||
const { status, request, output: outputs } = parsed as ImageReturnType;
|
||||
|
||||
|
||||
if (status === 'succeeded') {
|
||||
|
||||
updateQueueStatus(id, QueueStatus.complete);
|
||||
outputs.forEach((output: any, index: number) => {
|
||||
|
||||
const { data, seed } = output as ImageOutput;
|
||||
const seedReq = {
|
||||
...request,
|
||||
seed,
|
||||
};
|
||||
const batchId = `${id}${idDelim}-${seed}-${index}`;
|
||||
updateDisplay(batchId, data, seedReq);
|
||||
});
|
||||
}
|
||||
|
||||
else {
|
||||
console.warn(`Unexpected status: ${status}`);
|
||||
updateQueueStatus(id, QueueStatus.error);
|
||||
}
|
||||
|
||||
}
|
||||
catch (e) {
|
||||
updateQueueStatus(id, QueueStatus.error);
|
||||
console.warn("Error HACKING JSON: ", e)
|
||||
}
|
||||
}
|
||||
|
||||
const parseRequest = async (id: string, reader: ReadableStreamDefaultReader<Uint8Array>) => {
|
||||
const decoder = new TextDecoder();
|
||||
let finalJSON = '';
|
||||
|
||||
while (true) {
|
||||
const { done, value } = await reader.read();
|
||||
const jsonStr = decoder.decode(value);
|
||||
if (done) {
|
||||
setStatus(FetchingStates.COMPLETE);
|
||||
hackJson(finalJSON, id);
|
||||
if (isSoundEnabled) {
|
||||
void dingRef.current?.play();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
try {
|
||||
const update = JSON.parse(jsonStr);
|
||||
const { status } = update;
|
||||
|
||||
if (status === "progress") {
|
||||
setStatus(FetchingStates.PROGRESSING);
|
||||
const { progress: { step, total_steps }, output: outputs } = update;
|
||||
setStep(step);
|
||||
setTotalSteps(total_steps);
|
||||
|
||||
if (step === 0) {
|
||||
setStartTime();
|
||||
}
|
||||
else {
|
||||
setNowTime();
|
||||
}
|
||||
|
||||
if (void 0 !== outputs) {
|
||||
outputs.forEach((output: any) => {
|
||||
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
||||
const timePath = `${output.path}?t=${new Date().getTime()}`
|
||||
addProgressImage(timePath);
|
||||
});
|
||||
}
|
||||
|
||||
} else if (status === "succeeded") {
|
||||
// TODO this should be the the new out instead of the try catch
|
||||
// wait for the path to come back instead of the data
|
||||
setStatus(FetchingStates.SUCCEEDED);
|
||||
}
|
||||
else if (status === 'failed') {
|
||||
console.warn('failed');
|
||||
console.warn(update);
|
||||
}
|
||||
else {
|
||||
console.warn("UNKNOWN ?", update);
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
// console.log('EXPECTED PARSE ERRROR')
|
||||
finalJSON += jsonStr;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
const startStream = async (id: string, req: ImageRequest) => {
|
||||
|
||||
try {
|
||||
updateQueueStatus(id, QueueStatus.processing);
|
||||
resetForFetching();
|
||||
const res = await doMakeImage(req);
|
||||
const reader = res.body?.getReader();
|
||||
|
||||
if (void 0 !== reader) {
|
||||
void parseRequest(id, reader);
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
console.log('TOP LINE STREAM ERROR')
|
||||
updateQueueStatus(id, QueueStatus.error);
|
||||
console.log(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const queueImageRequest = (req: ImageRequest) => {
|
||||
// the actual number of request we will make
|
||||
const requests = [];
|
||||
// the number of images we will make
|
||||
let { num_outputs } = req;
|
||||
if (parallelCount > num_outputs) {
|
||||
requests.push(num_outputs);
|
||||
} else {
|
||||
// while we have at least 1 image to make
|
||||
while (num_outputs >= 1) {
|
||||
// subtract the parallel count from the number of images to make
|
||||
num_outputs -= parallelCount;
|
||||
|
||||
// if we are still 0 or greater we can make the full parallel count
|
||||
if (num_outputs <= 0) {
|
||||
requests.push(parallelCount);
|
||||
}
|
||||
// otherwise we can only make the remaining images
|
||||
else {
|
||||
requests.push(Math.abs(num_outputs));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
requests.forEach((num, index) => {
|
||||
// get the seed we want to use
|
||||
let seed = req.seed;
|
||||
if (index !== 0) {
|
||||
// we want to use a random seed for subsequent requests
|
||||
seed = useRandomSeed();
|
||||
}
|
||||
// add the request to the queue
|
||||
addtoQueue(uuidv4(), {
|
||||
...req,
|
||||
// updated the number of images to make
|
||||
num_outputs: num,
|
||||
// update the seed
|
||||
seed,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const makeImageQueue = async () => {
|
||||
// potentially update the seed
|
||||
if (isRandomSeed) {
|
||||
// update the seed for the next time we click the button
|
||||
setRequestOption("seed", useRandomSeed());
|
||||
}
|
||||
// the request that we have built
|
||||
const req = builtRequest();
|
||||
queueImageRequest(req);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const makeImages = async (options: ImageRequest) => {
|
||||
// removeFirstInQueue();
|
||||
await startStream(id ?? "", options);
|
||||
}
|
||||
|
||||
if (status === FetchingStates.PROGRESSING || status === FetchingStates.FETCHING) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (hasQueue) {
|
||||
|
||||
if (options === undefined) {
|
||||
console.log('req is undefined');
|
||||
return;
|
||||
}
|
||||
|
||||
makeImages(options).catch((e) => {
|
||||
console.log('HAS QUEUE ERROR');
|
||||
console.log(e);
|
||||
});
|
||||
}
|
||||
|
||||
}, [hasQueue, status, id, options, startStream]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<button
|
||||
className={buttonStyle({
|
||||
size: "large",
|
||||
})}
|
||||
onClick={() => {
|
||||
void makeImageQueue();
|
||||
}}
|
||||
>
|
||||
{t("home.make-img-btn")}
|
||||
</button>
|
||||
<AudioDing ref={dingRef}></AudioDing>
|
||||
</>
|
||||
);
|
||||
}
|
@ -1,93 +0,0 @@
|
||||
import React, { useState } from "react";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import {
|
||||
ModifierPreview,
|
||||
useImageCreate
|
||||
} from "../../../stores/imageCreateStore";
|
||||
|
||||
import { API_URL } from "../../../api";
|
||||
|
||||
import {
|
||||
IconFont,
|
||||
} from "../../../styles/shared.css";
|
||||
|
||||
import {
|
||||
ModifierTagMain,
|
||||
ModifierActions,
|
||||
tagPreview,
|
||||
TagText,
|
||||
TagToggle,
|
||||
} from "./modifierTags.css";
|
||||
|
||||
interface ModifierTagProps {
|
||||
name: string;
|
||||
category: string;
|
||||
previews: ModifierPreview[];
|
||||
}
|
||||
|
||||
export default function ModifierTag({ name, category, previews }: ModifierTagProps) {
|
||||
|
||||
const previewType: 'portrait' | 'landscape' = "portrait";
|
||||
|
||||
const [showActions, setShowActions] = useState(false);
|
||||
|
||||
const handleHover = () => {
|
||||
setShowActions(true);
|
||||
};
|
||||
|
||||
const handleLeave = () => {
|
||||
setShowActions(false);
|
||||
};
|
||||
|
||||
const addCreateTag = useImageCreate((state) => state.addCreateTag);
|
||||
const setPositivePrompt = () => {
|
||||
addCreateTag({ id: uuidv4(), name, type: 'positive' });
|
||||
}
|
||||
const setNegativePrompt = () => {
|
||||
addCreateTag({ id: uuidv4(), name, type: 'negative' });
|
||||
}
|
||||
|
||||
|
||||
const hasTag = useImageCreate((state) => state.hasTag(category, name))
|
||||
? "selected"
|
||||
: "";
|
||||
const toggleTag = useImageCreate((state) => state.toggleTag);
|
||||
|
||||
const _toggleTag = () => {
|
||||
toggleTag(category, name);
|
||||
};
|
||||
|
||||
// , hasTag].join(" ")
|
||||
return (
|
||||
<div className={ModifierTagMain}
|
||||
onMouseEnter={handleHover}
|
||||
onMouseLeave={handleLeave}>
|
||||
<p className={!showActions ? TagText : TagToggle}>{name}</p>
|
||||
{showActions && (
|
||||
<div className={ModifierActions}>
|
||||
<button onClick={setPositivePrompt}>
|
||||
<i className={[IconFont, 'fa-solid', 'fa-plus'].join(" ")}></i>
|
||||
</button>
|
||||
<button onClick={setNegativePrompt}>
|
||||
<i className={[IconFont, 'fa-solid', 'fa-minus'].join(" ")}></i>
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
{/* <div className={tagPreview}>
|
||||
{previews.map((preview) => {
|
||||
if (preview.name !== previewType) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<img
|
||||
key={preview.name}
|
||||
src={`${API_URL}/media/modifier-thumbnails/${preview.path}`}
|
||||
alt={preview.name}
|
||||
title={preview.name}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div> */}
|
||||
</div>
|
||||
);
|
||||
}
|
@ -1,69 +0,0 @@
|
||||
import { style, globalStyle } from "@vanilla-extract/css";
|
||||
import { vars } from '../../../styles/theme/index.css';
|
||||
|
||||
import { card } from '../../_recipes/card.css';
|
||||
|
||||
export const ModifierTagMain = style([
|
||||
card({
|
||||
backing: 'normal',
|
||||
level: 1,
|
||||
info: true
|
||||
}), {
|
||||
position: "relative",
|
||||
width: "fit-content",
|
||||
borderColor: `hsl(${vars.brandHue}, ${vars.colorMod.saturation.normal}, ${vars.colorMod.lightness.normal})`,
|
||||
padding: vars.spacing.small,
|
||||
}
|
||||
]);
|
||||
|
||||
globalStyle(`${ModifierTagMain}.selected`, {
|
||||
backgroundColor: "rgb(131, 11, 121)",
|
||||
})
|
||||
|
||||
globalStyle(`${ModifierTagMain} p`, {
|
||||
margin: 0,
|
||||
textAlign: "center",
|
||||
marginBottom: "2px",
|
||||
});
|
||||
|
||||
|
||||
export const TagText = style({
|
||||
opacity: 1,
|
||||
});
|
||||
|
||||
export const TagToggle = style({
|
||||
opacity: 0.3,
|
||||
});
|
||||
|
||||
|
||||
export const ModifierActions = style({
|
||||
position: "absolute",
|
||||
top: "0",
|
||||
left: "0",
|
||||
height: "100%",
|
||||
width: "100%",
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
});
|
||||
|
||||
globalStyle(`${ModifierActions} button`, {
|
||||
flexGrow: 1,
|
||||
backgroundColor: "transparent",
|
||||
border: "none",
|
||||
boxShadow: `inset 0 0 24px 0px rgb(255 255 255 / 50%)`,
|
||||
borderRadius: "5px",
|
||||
padding: "0",
|
||||
});
|
||||
|
||||
export const tagPreview = style({
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
});
|
||||
|
||||
globalStyle(`${tagPreview} img`, {
|
||||
width: "90px",
|
||||
height: "100%",
|
||||
objectFit: "cover",
|
||||
objectPosition: "center",
|
||||
});
|
||||
|
@ -1,68 +0,0 @@
|
||||
import React, { useState } from "react";
|
||||
|
||||
import { useImageCreate } from "../../../stores/imageCreateStore";
|
||||
|
||||
import {
|
||||
IconFont,
|
||||
} from "../../../styles/shared.css";
|
||||
|
||||
import {
|
||||
PromptTagMain,
|
||||
TagToggle,
|
||||
TagRemoveButton,
|
||||
PromptTagText,
|
||||
PromptTagToggle
|
||||
} from "./promptTag.css";
|
||||
|
||||
interface PromptTagProps {
|
||||
id: string;
|
||||
name: string;
|
||||
category?: string;
|
||||
previews?: string[];
|
||||
type: string;
|
||||
};
|
||||
|
||||
export default function PromptTag({ id, name, category, previews, type }: PromptTagProps) {
|
||||
|
||||
const [showToggle, setShowToggle] = useState(false);
|
||||
|
||||
const removeCreateTag = useImageCreate((state) => state.removeCreateTag);
|
||||
const changeCreateTagType = useImageCreate((state) => state.changeCreateTagType);
|
||||
|
||||
const handleHover = () => {
|
||||
setShowToggle(true);
|
||||
};
|
||||
|
||||
const handleLeave = () => {
|
||||
setShowToggle(false);
|
||||
};
|
||||
|
||||
const toggleType = () => {
|
||||
if (type === 'positive') {
|
||||
changeCreateTagType(id, 'negative');
|
||||
}
|
||||
else {
|
||||
changeCreateTagType(id, 'positive');
|
||||
}
|
||||
};
|
||||
|
||||
const handleRemove = () => {
|
||||
console.log('remove');
|
||||
removeCreateTag(id);
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
onMouseEnter={handleHover}
|
||||
onMouseLeave={handleLeave}
|
||||
className={[PromptTagMain, type].join(' ')}>
|
||||
<p className={!showToggle ? PromptTagText : PromptTagToggle}>{name}</p>
|
||||
{showToggle && <button className={TagToggle} onClick={toggleType}>
|
||||
{type === 'positive' ? <i className={[IconFont, 'fa-solid', 'fa-minus'].join(" ")}></i> : <i className={[IconFont, 'fa-solid', 'fa-plus'].join(" ")}></i>}
|
||||
</button>}
|
||||
{showToggle && <button className={TagRemoveButton} onClick={handleRemove}>
|
||||
<i className={[IconFont, 'fa-solid', 'fa-close'].join(" ")}></i>
|
||||
</button>}
|
||||
</div>
|
||||
);
|
||||
};
|
@ -1,55 +0,0 @@
|
||||
/* eslint-disable @typescript-eslint/restrict-template-expressions */
|
||||
import { style, globalStyle } from '@vanilla-extract/css';
|
||||
|
||||
import { XButton } from "../../../styles/shared.css";
|
||||
import { vars } from '../../../styles/theme/index.css';
|
||||
import { card } from '../../_recipes/card.css';
|
||||
|
||||
|
||||
export const PromptTagMain = style([
|
||||
card({
|
||||
backing: 'normal',
|
||||
level: 1,
|
||||
info: true
|
||||
}), {
|
||||
position: "relative",
|
||||
width: "fit-content",
|
||||
backgroundColor: `hsl(${vars.backgroundLight}, ${vars.colorMod.saturation.normal}, ${vars.colorMod.lightness.normal})`,
|
||||
padding: vars.spacing.small,
|
||||
}
|
||||
]);
|
||||
|
||||
export const PromptTagText = style({
|
||||
opacity: 1,
|
||||
fontSize: vars.fonts.sizes.Plain,
|
||||
});
|
||||
|
||||
export const PromptTagToggle = style({
|
||||
opacity: 0.3,
|
||||
fontSize: vars.fonts.sizes.Plain,
|
||||
});
|
||||
|
||||
globalStyle(`${PromptTagMain}.positive`, {
|
||||
borderColor: `hsl(${vars.brandHue}, ${vars.colorMod.saturation.normal}, ${vars.colorMod.lightness.normal})`,
|
||||
});
|
||||
|
||||
globalStyle(`${PromptTagMain}.negative`, {
|
||||
borderColor: `hsl(${vars.errorHue}, ${vars.colorMod.saturation.normal}, ${vars.colorMod.lightness.normal})`,
|
||||
});
|
||||
|
||||
export const TagToggle = style({
|
||||
position: "absolute",
|
||||
top: "0",
|
||||
right: "0",
|
||||
height: "100%",
|
||||
width: "100%",
|
||||
border: "none",
|
||||
backgroundColor: "transparent",
|
||||
boxShadow: `inset 0 0 24px 0px rgb(255 255 255 / 50%)`,
|
||||
});
|
||||
|
||||
export const TagRemoveButton = style([XButton, {
|
||||
top: '-4px',
|
||||
left: '4px',
|
||||
padding: '0',
|
||||
}]);
|
@ -1,70 +0,0 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
|
||||
import { FetchingStates, useImageFetching } from "../../../stores/imageFetchingStore";
|
||||
import { useRequestQueue } from "../../../stores/requestQueueStore";
|
||||
|
||||
export default function QueueStatusTab() {
|
||||
|
||||
|
||||
const [showBasicQueue, setShowBasicQueue] = useState(true);
|
||||
|
||||
const hasPendingQueue = useRequestQueue((state) => state.hasPendingQueue());
|
||||
const pendingRequests = useRequestQueue((state) => state.pendingRequests());
|
||||
|
||||
const status = useImageFetching((state) => state.status);
|
||||
|
||||
const step = useImageFetching((state) => state.step);
|
||||
const totalSteps = useImageFetching((state) => state.totalSteps);
|
||||
|
||||
const startTime = useImageFetching((state) => state.timeStarted);
|
||||
const timeNow = useImageFetching((state) => state.timeNow);
|
||||
const [timeRemaining, setTimeRemaining] = useState(0);
|
||||
|
||||
const [percent, setPercent] = useState(0);
|
||||
|
||||
useEffect(() => {
|
||||
if (totalSteps > 0) {
|
||||
setPercent(Math.round((step / totalSteps) * 100));
|
||||
} else {
|
||||
setPercent(0);
|
||||
}
|
||||
}, [step, totalSteps]);
|
||||
|
||||
useEffect(() => {
|
||||
// find the remaining time
|
||||
const timeTaken = +timeNow - +startTime;
|
||||
const timePerStep = step == 0 ? 0 : timeTaken / step;
|
||||
const totalTime = timePerStep * totalSteps;
|
||||
const timeRemaining = (totalTime - timeTaken) / 1000;
|
||||
// @ts-expect-error
|
||||
setTimeRemaining(timeRemaining.toPrecision(3));
|
||||
|
||||
}, [step, totalSteps, startTime, timeNow, setTimeRemaining]);
|
||||
|
||||
useEffect(() => {
|
||||
if (hasPendingQueue) {
|
||||
setShowBasicQueue(false);
|
||||
}
|
||||
}, [status, hasPendingQueue]);
|
||||
|
||||
// {/* {showBasicQueue
|
||||
// ? <> */}
|
||||
// Queue
|
||||
// {/* </>
|
||||
// : <>
|
||||
// <span>Percent: {percent}%</span>
|
||||
// </>npm
|
||||
// } */}
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
<span>Queue </span>
|
||||
{hasPendingQueue && <span> Items Remaining: {pendingRequests.length} </span>}
|
||||
</>
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,25 +0,0 @@
|
||||
import React from "react";
|
||||
import { doStopImage } from "../../../api";
|
||||
|
||||
|
||||
import {
|
||||
buttonStyle
|
||||
} from "../../_recipes/button.css";
|
||||
|
||||
export default function StopButton() {
|
||||
|
||||
const stopMake = async () => {
|
||||
try {
|
||||
const res = await doStopImage();
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
};
|
||||
|
||||
return <button className={buttonStyle(
|
||||
{
|
||||
color: "cancel",
|
||||
size: "large",
|
||||
}
|
||||
)} onClick={() => void stopMake()}>Stop</button>;
|
||||
}
|
@ -1,63 +0,0 @@
|
||||
import { style, globalStyle } from "@vanilla-extract/css";
|
||||
|
||||
import { vars } from "../../../styles/theme/index.css";
|
||||
import {
|
||||
card as cardStyle,
|
||||
} from '../../_recipes/card.css'
|
||||
|
||||
export const completedImagesMain = style({
|
||||
position: "relative",
|
||||
});
|
||||
|
||||
// globalStyle(`${completedImagesMain} > button`, {
|
||||
// position: "absolute",
|
||||
// top: '-29px',
|
||||
// });
|
||||
|
||||
export const completedImagesContent = style([cardStyle(), {
|
||||
height: "250px",
|
||||
width: "100%",
|
||||
display: "flex",
|
||||
padding: vars.spacing.medium,
|
||||
borderRadius: 0,
|
||||
}]);
|
||||
|
||||
export const completedImagesList = style({
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
flexWrap: "nowrap",
|
||||
height: "100%",
|
||||
width: "100%",
|
||||
overflow: "auto",
|
||||
paddingLeft: vars.spacing.none,
|
||||
});
|
||||
|
||||
globalStyle(`${completedImagesContent} li`, {
|
||||
position: "relative",
|
||||
});
|
||||
|
||||
globalStyle(`${completedImagesContent} > li:first-of-type`, {
|
||||
marginLeft: vars.spacing.medium,
|
||||
});
|
||||
|
||||
globalStyle(`${completedImagesContent} > li:last-of-type`, {
|
||||
marginRight: 0,
|
||||
});
|
||||
|
||||
export const imageContain = style({
|
||||
width: "206px",
|
||||
backgroundColor: "black",
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
flexShrink: 0,
|
||||
border: "0 none",
|
||||
padding: "0",
|
||||
marginLeft: vars.spacing.medium,
|
||||
cursor: "pointer",
|
||||
});
|
||||
|
||||
globalStyle(`${imageContain} img`, {
|
||||
width: "100%",
|
||||
objectFit: "contain",
|
||||
});
|