From 5a4765046eb235ec8bd74b58fd1cc3c1fc15bfff Mon Sep 17 00:00:00 2001 From: Lincoln Stein Date: Tue, 11 Apr 2023 09:33:28 -0400 Subject: [PATCH 01/68] add logging support This commit adds invokeai.backend.util.logging, which provides support for formatted console and logfile messages that follow the status reporting conventions of earlier InvokeAI versions. Examples: ### A critical error (logging.CRITICAL) *** A non-fatal error (logging.ERROR) ** A warning (logging.WARNING) >> Informational message (logging.INFO) | Debugging message (logging.DEBUG) --- .../backend/model_management/model_manager.py | 181 +++++++++--------- invokeai/backend/util/logging.py | 107 +++++++++++ 2 files changed, 194 insertions(+), 94 deletions(-) create mode 100644 invokeai/backend/util/logging.py diff --git a/invokeai/backend/model_management/model_manager.py b/invokeai/backend/model_management/model_manager.py index 534b526081..4f9ea75964 100644 --- a/invokeai/backend/model_management/model_manager.py +++ b/invokeai/backend/model_management/model_manager.py @@ -24,6 +24,7 @@ import safetensors import safetensors.torch import torch import transformers +import invokeai.backend.util.logging as ialog from diffusers import ( AutoencoderKL, UNet2DConditionModel, @@ -132,8 +133,8 @@ class ModelManager(object): ) if not self.valid_model(model_name): - print( - f'** "{model_name}" is not a known model name. Please check your models.yaml file' + ialog.error( + f'"{model_name}" is not a known model name. Please check your models.yaml file' ) return self.current_model @@ -144,7 +145,7 @@ class ModelManager(object): if model_name in self.models: requested_model = self.models[model_name]["model"] - print(f">> Retrieving model {model_name} from system RAM cache") + ialog.info(f"Retrieving model {model_name} from system RAM cache") requested_model.ready() width = self.models[model_name]["width"] height = self.models[model_name]["height"] @@ -379,7 +380,7 @@ class ModelManager(object): """ omega = self.config if model_name not in omega: - print(f"** Unknown model {model_name}") + ialog.error(f"Unknown model {model_name}") return # save these for use in deletion later conf = omega[model_name] @@ -392,13 +393,13 @@ class ModelManager(object): self.stack.remove(model_name) if delete_files: if weights: - print(f"** Deleting file {weights}") + ialog.info(f"Deleting file {weights}") Path(weights).unlink(missing_ok=True) elif path: - print(f"** Deleting directory {path}") + ialog.info(f"Deleting directory {path}") rmtree(path, ignore_errors=True) elif repo_id: - print(f"** Deleting the cached model directory for {repo_id}") + ialog.info(f"Deleting the cached model directory for {repo_id}") self._delete_model_from_cache(repo_id) def add_model( @@ -439,7 +440,7 @@ class ModelManager(object): def _load_model(self, model_name: str): """Load and initialize the model from configuration variables passed at object creation time""" if model_name not in self.config: - print( + ialog.error( f'"{model_name}" is not a known model name. Please check your models.yaml file' ) return @@ -457,7 +458,7 @@ class ModelManager(object): model_format = mconfig.get("format", "ckpt") if model_format == "ckpt": weights = mconfig.weights - print(f">> Loading {model_name} from {weights}") + ialog.info(f"Loading {model_name} from {weights}") model, width, height, model_hash = self._load_ckpt_model( model_name, mconfig ) @@ -473,13 +474,15 @@ class ModelManager(object): # usage statistics toc = time.time() - print(">> Model loaded in", "%4.2fs" % (toc - tic)) + ialog.info("Model loaded in " + "%4.2fs" % (toc - tic)) if self._has_cuda(): - print( - ">> Max VRAM used to load the model:", - "%4.2fG" % (torch.cuda.max_memory_allocated() / 1e9), - "\n>> Current VRAM usage:" - "%4.2fG" % (torch.cuda.memory_allocated() / 1e9), + ialog.info( + "Max VRAM used to load the model: "+ + "%4.2fG" % (torch.cuda.max_memory_allocated() / 1e9) + ) + ialog.info( + "Current VRAM usage: "+ + "%4.2fG" % (torch.cuda.memory_allocated() / 1e9) ) return model, width, height, model_hash @@ -487,11 +490,11 @@ class ModelManager(object): name_or_path = self.model_name_or_path(mconfig) using_fp16 = self.precision == "float16" - print(f">> Loading diffusers model from {name_or_path}") + ialog.info(f"Loading diffusers model from {name_or_path}") if using_fp16: - print(" | Using faster float16 precision") + ialog.debug("Using faster float16 precision") else: - print(" | Using more accurate float32 precision") + ialog.debug("Using more accurate float32 precision") # TODO: scan weights maybe? pipeline_args: dict[str, Any] = dict( @@ -523,8 +526,8 @@ class ModelManager(object): if str(e).startswith("fp16 is not a valid"): pass else: - print( - f"** An unexpected error occurred while downloading the model: {e})" + ialog.error( + f"An unexpected error occurred while downloading the model: {e})" ) if pipeline: break @@ -542,7 +545,7 @@ class ModelManager(object): # square images??? width = pipeline.unet.config.sample_size * pipeline.vae_scale_factor height = width - print(f" | Default image dimensions = {width} x {height}") + ialog.debug(f"Default image dimensions = {width} x {height}") return pipeline, width, height, model_hash @@ -559,14 +562,14 @@ class ModelManager(object): weights = os.path.normpath(os.path.join(Globals.root, weights)) # Convert to diffusers and return a diffusers pipeline - print(f">> Converting legacy checkpoint {model_name} into a diffusers model...") + ialog.info(f"Converting legacy checkpoint {model_name} into a diffusers model...") from . import load_pipeline_from_original_stable_diffusion_ckpt try: if self.list_models()[self.current_model]["status"] == "active": self.offload_model(self.current_model) - except Exception as e: + except Exception: pass vae_path = None @@ -624,7 +627,7 @@ class ModelManager(object): if model_name not in self.models: return - print(f">> Offloading {model_name} to CPU") + ialog.info(f"Offloading {model_name} to CPU") model = self.models[model_name]["model"] model.offload_all() self.current_model = None @@ -640,30 +643,26 @@ class ModelManager(object): and option to exit if an infected file is identified. """ # scan model - print(f" | Scanning Model: {model_name}") + ialog.debug(f"Scanning Model: {model_name}") scan_result = scan_file_path(checkpoint) if scan_result.infected_files != 0: if scan_result.infected_files == 1: - print(f"\n### Issues Found In Model: {scan_result.issues_count}") - print( - "### WARNING: The model you are trying to load seems to be infected." - ) - print("### For your safety, InvokeAI will not load this model.") - print("### Please use checkpoints from trusted sources.") - print("### Exiting InvokeAI") + ialog.critical(f"Issues Found In Model: {scan_result.issues_count}") + ialog.critical("The model you are trying to load seems to be infected.") + ialog.critical("For your safety, InvokeAI will not load this model.") + ialog.critical("Please use checkpoints from trusted sources.") + ialog.critical("Exiting InvokeAI") sys.exit() else: - print( - "\n### WARNING: InvokeAI was unable to scan the model you are using." - ) + ialog.warning("InvokeAI was unable to scan the model you are using.") model_safe_check_fail = ask_user( "Do you want to to continue loading the model?", ["y", "n"] ) if model_safe_check_fail.lower() != "y": - print("### Exiting InvokeAI") + ialog.critical("Exiting InvokeAI") sys.exit() else: - print(" | Model scanned ok") + ialog.debug("Model scanned ok") def import_diffuser_model( self, @@ -780,26 +779,24 @@ class ModelManager(object): model_path: Path = None thing = path_url_or_repo # to save typing - print(f">> Probing {thing} for import") + ialog.info(f"Probing {thing} for import") if thing.startswith(("http:", "https:", "ftp:")): - print(f" | {thing} appears to be a URL") + ialog.info(f"{thing} appears to be a URL") model_path = self._resolve_path( thing, "models/ldm/stable-diffusion-v1" ) # _resolve_path does a download if needed elif Path(thing).is_file() and thing.endswith((".ckpt", ".safetensors")): if Path(thing).stem in ["model", "diffusion_pytorch_model"]: - print( - f" | {Path(thing).name} appears to be part of a diffusers model. Skipping import" - ) + ialog.debug(f"{Path(thing).name} appears to be part of a diffusers model. Skipping import") return else: - print(f" | {thing} appears to be a checkpoint file on disk") + ialog.debug(f"{thing} appears to be a checkpoint file on disk") model_path = self._resolve_path(thing, "models/ldm/stable-diffusion-v1") elif Path(thing).is_dir() and Path(thing, "model_index.json").exists(): - print(f" | {thing} appears to be a diffusers file on disk") + ialog.debug(f"{thing} appears to be a diffusers file on disk") model_name = self.import_diffuser_model( thing, vae=dict(repo_id="stabilityai/sd-vae-ft-mse"), @@ -810,34 +807,30 @@ class ModelManager(object): elif Path(thing).is_dir(): if (Path(thing) / "model_index.json").exists(): - print(f" | {thing} appears to be a diffusers model.") + ialog.debug(f"{thing} appears to be a diffusers model.") model_name = self.import_diffuser_model( thing, commit_to_conf=commit_to_conf ) else: - print( - f" |{thing} appears to be a directory. Will scan for models to import" - ) + ialog.debug(f"{thing} appears to be a directory. Will scan for models to import") for m in list(Path(thing).rglob("*.ckpt")) + list( Path(thing).rglob("*.safetensors") ): if model_name := self.heuristic_import( str(m), commit_to_conf=commit_to_conf ): - print(f" >> {model_name} successfully imported") + ialog.info(f"{model_name} successfully imported") return model_name elif re.match(r"^[\w.+-]+/[\w.+-]+$", thing): - print(f" | {thing} appears to be a HuggingFace diffusers repo_id") + ialog.debug(f"{thing} appears to be a HuggingFace diffusers repo_id") model_name = self.import_diffuser_model( thing, commit_to_conf=commit_to_conf ) pipeline, _, _, _ = self._load_diffusers_model(self.config[model_name]) return model_name else: - print( - f"** {thing}: Unknown thing. Please provide a URL, file path, directory or HuggingFace repo_id" - ) + ialog.warning(f"{thing}: Unknown thing. Please provide a URL, file path, directory or HuggingFace repo_id") # Model_path is set in the event of a legacy checkpoint file. # If not set, we're all done @@ -845,7 +838,7 @@ class ModelManager(object): return if model_path.stem in self.config: # already imported - print(" | Already imported. Skipping") + ialog.debug("Already imported. Skipping") return model_path.stem # another round of heuristics to guess the correct config file. @@ -861,39 +854,39 @@ class ModelManager(object): # look for a like-named .yaml file in same directory if model_path.with_suffix(".yaml").exists(): model_config_file = model_path.with_suffix(".yaml") - print(f" | Using config file {model_config_file.name}") + ialog.debug(f"Using config file {model_config_file.name}") else: model_type = self.probe_model_type(checkpoint) if model_type == SDLegacyType.V1: - print(" | SD-v1 model detected") + ialog.debug("SD-v1 model detected") model_config_file = Path( Globals.root, "configs/stable-diffusion/v1-inference.yaml" ) elif model_type == SDLegacyType.V1_INPAINT: - print(" | SD-v1 inpainting model detected") + ialog.debug("SD-v1 inpainting model detected") model_config_file = Path( Globals.root, "configs/stable-diffusion/v1-inpainting-inference.yaml", ) elif model_type == SDLegacyType.V2_v: - print(" | SD-v2-v model detected") + ialog.debug("SD-v2-v model detected") model_config_file = Path( Globals.root, "configs/stable-diffusion/v2-inference-v.yaml" ) elif model_type == SDLegacyType.V2_e: - print(" | SD-v2-e model detected") + ialog.debug("SD-v2-e model detected") model_config_file = Path( Globals.root, "configs/stable-diffusion/v2-inference.yaml" ) elif model_type == SDLegacyType.V2: - print( - f"** {thing} is a V2 checkpoint file, but its parameterization cannot be determined. Please provide configuration file path." + ialog.warning( + f"{thing} is a V2 checkpoint file, but its parameterization cannot be determined. Please provide configuration file path." ) return else: - print( - f"** {thing} is a legacy checkpoint file but not a known Stable Diffusion model. Please provide configuration file path." + ialog.warning( + f"{thing} is a legacy checkpoint file but not a known Stable Diffusion model. Please provide configuration file path." ) return @@ -909,7 +902,7 @@ class ModelManager(object): for suffix in ["pt", "ckpt", "safetensors"]: if (model_path.with_suffix(f".vae.{suffix}")).exists(): vae_path = model_path.with_suffix(f".vae.{suffix}") - print(f" | Using VAE file {vae_path.name}") + ialog.debug(f"Using VAE file {vae_path.name}") vae = None if vae_path else dict(repo_id="stabilityai/sd-vae-ft-mse") diffuser_path = Path( @@ -955,14 +948,14 @@ class ModelManager(object): from . import convert_ckpt_to_diffusers if diffusers_path.exists(): - print( - f"ERROR: The path {str(diffusers_path)} already exists. Please move or remove it and try again." + ialog.error( + f"The path {str(diffusers_path)} already exists. Please move or remove it and try again." ) return model_name = model_name or diffusers_path.name model_description = model_description or f"Converted version of {model_name}" - print(f" | Converting {model_name} to diffusers (30-60s)") + ialog.debug(f"Converting {model_name} to diffusers (30-60s)") try: # By passing the specified VAE to the conversion function, the autoencoder # will be built into the model rather than tacked on afterward via the config file @@ -979,10 +972,10 @@ class ModelManager(object): vae_path=vae_path, scan_needed=scan_needed, ) - print( - f" | Success. Converted model is now located at {str(diffusers_path)}" + ialog.debug( + f"Success. Converted model is now located at {str(diffusers_path)}" ) - print(f" | Writing new config file entry for {model_name}") + ialog.debug(f"Writing new config file entry for {model_name}") new_config = dict( path=str(diffusers_path), description=model_description, @@ -993,17 +986,17 @@ class ModelManager(object): self.add_model(model_name, new_config, True) if commit_to_conf: self.commit(commit_to_conf) - print(" | Conversion succeeded") + ialog.debug("Conversion succeeded") except Exception as e: - print(f"** Conversion failed: {str(e)}") - print( - "** If you are trying to convert an inpainting or 2.X model, please indicate the correct config file (e.g. v1-inpainting-inference.yaml)" + ialog.warning(f"Conversion failed: {str(e)}") + ialog.warning( + "If you are trying to convert an inpainting or 2.X model, please indicate the correct config file (e.g. v1-inpainting-inference.yaml)" ) return model_name def search_models(self, search_folder): - print(f">> Finding Models In: {search_folder}") + ialog.info(f"Finding Models In: {search_folder}") models_folder_ckpt = Path(search_folder).glob("**/*.ckpt") models_folder_safetensors = Path(search_folder).glob("**/*.safetensors") @@ -1027,8 +1020,8 @@ class ModelManager(object): num_loaded_models = len(self.models) if num_loaded_models >= self.max_loaded_models: least_recent_model = self._pop_oldest_model() - print( - f">> Cache limit (max={self.max_loaded_models}) reached. Purging {least_recent_model}" + ialog.info( + f"Cache limit (max={self.max_loaded_models}) reached. Purging {least_recent_model}" ) if least_recent_model is not None: del self.models[least_recent_model] @@ -1036,8 +1029,8 @@ class ModelManager(object): def print_vram_usage(self) -> None: if self._has_cuda: - print( - ">> Current VRAM usage: ", + ialog.info( + "Current VRAM usage:"+ "%4.2fG" % (torch.cuda.memory_allocated() / 1e9), ) @@ -1126,10 +1119,10 @@ class ModelManager(object): dest = hub / model.stem if dest.exists() and not source.exists(): continue - print(f"** {source} => {dest}") + ialog.info(f"{source} => {dest}") if source.exists(): if dest.is_symlink(): - print(f"** Found symlink at {dest.name}. Not migrating.") + ialog.warning(f"Found symlink at {dest.name}. Not migrating.") elif dest.exists(): if source.is_dir(): rmtree(source) @@ -1146,7 +1139,7 @@ class ModelManager(object): ] for d in empty: os.rmdir(d) - print("** Migration is done. Continuing...") + ialog.info("Migration is done. Continuing...") def _resolve_path( self, source: Union[str, Path], dest_directory: str @@ -1189,15 +1182,15 @@ class ModelManager(object): def _add_embeddings_to_model(self, model: StableDiffusionGeneratorPipeline): if self.embedding_path is not None: - print(f">> Loading embeddings from {self.embedding_path}") + ialog.info(f"Loading embeddings from {self.embedding_path}") for root, _, files in os.walk(self.embedding_path): for name in files: ti_path = os.path.join(root, name) model.textual_inversion_manager.load_textual_inversion( ti_path, defer_injecting_tokens=True ) - print( - f'>> Textual inversion triggers: {", ".join(sorted(model.textual_inversion_manager.get_all_trigger_strings()))}' + ialog.info( + f'Textual inversion triggers: {", ".join(sorted(model.textual_inversion_manager.get_all_trigger_strings()))}' ) def _has_cuda(self) -> bool: @@ -1219,7 +1212,7 @@ class ModelManager(object): with open(hashpath) as f: hash = f.read() return hash - print(" | Calculating sha256 hash of model files") + ialog.debug("Calculating sha256 hash of model files") tic = time.time() sha = hashlib.sha256() count = 0 @@ -1231,7 +1224,7 @@ class ModelManager(object): sha.update(chunk) hash = sha.hexdigest() toc = time.time() - print(f" | sha256 = {hash} ({count} files hashed in", "%4.2fs)" % (toc - tic)) + ialog.debug(f"sha256 = {hash} ({count} files hashed in", "%4.2fs)" % (toc - tic)) with open(hashpath, "w") as f: f.write(hash) return hash @@ -1249,13 +1242,13 @@ class ModelManager(object): hash = f.read() return hash - print(" | Calculating sha256 hash of weights file") + ialog.debug("Calculating sha256 hash of weights file") tic = time.time() sha = hashlib.sha256() sha.update(data) hash = sha.hexdigest() toc = time.time() - print(f">> sha256 = {hash}", "(%4.2fs)" % (toc - tic)) + ialog.debug(f"sha256 = {hash} "+"(%4.2fs)" % (toc - tic)) with open(hashpath, "w") as f: f.write(hash) @@ -1276,12 +1269,12 @@ class ModelManager(object): local_files_only=not Globals.internet_available, ) - print(f" | Loading diffusers VAE from {name_or_path}") + ialog.debug(f"Loading diffusers VAE from {name_or_path}") if using_fp16: vae_args.update(torch_dtype=torch.float16) fp_args_list = [{"revision": "fp16"}, {}] else: - print(" | Using more accurate float32 precision") + ialog.debug("Using more accurate float32 precision") fp_args_list = [{}] vae = None @@ -1305,7 +1298,7 @@ class ModelManager(object): break if not vae and deferred_error: - print(f"** Could not load VAE {name_or_path}: {str(deferred_error)}") + ialog.warning(f"Could not load VAE {name_or_path}: {str(deferred_error)}") return vae @@ -1321,8 +1314,8 @@ class ModelManager(object): for revision in repo.revisions: hashes_to_delete.add(revision.commit_hash) strategy = cache_info.delete_revisions(*hashes_to_delete) - print( - f"** Deletion of this model is expected to free {strategy.expected_freed_size_str}" + ialog.warning( + f"Deletion of this model is expected to free {strategy.expected_freed_size_str}" ) strategy.execute() diff --git a/invokeai/backend/util/logging.py b/invokeai/backend/util/logging.py new file mode 100644 index 0000000000..cce85fadbd --- /dev/null +++ b/invokeai/backend/util/logging.py @@ -0,0 +1,107 @@ +"""invokeai.util.logging +Copyright 2023 The InvokeAI Development Team + +Logging class for InvokeAI that produces console messages that follow +the conventions established in InvokeAI 1.X through 2.X. + + +One way to use it: + +from invokeai.backend.util.logging import InvokeAILogger + +logger = InvokeAILogger.getLogger(__name__) +logger.critical('this is critical') +logger.error('this is an error') +logger.warning('this is a warning') +logger.info('this is info') +logger.debug('this is debugging') + +Console messages: + ### this is critical + *** this is an error *** + ** this is a warning + >> this is info + | this is debugging + +Another way: +import invokeai.backend.util.logging as ialog +ialog.debug('this is a debugging message') +""" +import logging +import sys + +def debug(msg:str): + InvokeAILogger.getLogger().debug(msg) + +def info(msg:str): + InvokeAILogger.getLogger().info(msg) + +def warning(msg:str): + InvokeAILogger.getLogger().warning(msg) + +def error(msg:str): + InvokeAILogger.getLogger().error(msg) + +def critical(msg:str): + InvokeAILogger.getLogger().critical(msg) + +class InvokeAILogFormatter(logging.Formatter): + ''' + Repurposed from: + https://stackoverflow.com/questions/14844970/modifying-logging-message-format-based-on-message-logging-level-in-python3 + ''' + crit_fmt = "### %(msg)s" + err_fmt = "!!! %(msg)s !!!" + warn_fmt = "** %(msg)s" + info_fmt = ">> %(msg)s" + dbg_fmt = " | %(msg)s" + + def __init__(self): + super().__init__(fmt="%(levelno)d: %(msg)s", datefmt=None, style='%') + + def format(self, record): + # Remember the format used when the logging module + # was installed (in the event that this formatter is + # used with the vanilla logging module. + format_orig = self._style._fmt + if record.levelno == logging.DEBUG: + self._style._fmt = InvokeAILogFormatter.dbg_fmt + if record.levelno == logging.INFO: + self._style._fmt = InvokeAILogFormatter.info_fmt + if record.levelno == logging.WARNING: + self._style._fmt = InvokeAILogFormatter.warn_fmt + if record.levelno == logging.ERROR: + self._style._fmt = InvokeAILogFormatter.err_fmt + if record.levelno == logging.CRITICAL: + self._style._fmt = InvokeAILogFormatter.crit_fmt + + # parent class does the work + result = super().format(record) + self._style._fmt = format_orig + return result + +class InvokeAILogger(object): + loggers = dict() + + @classmethod + def getLogger(self, name:str='invokeai')->logging.Logger: + if name not in self.loggers: + logger = logging.getLogger(name) + logger.setLevel(logging.DEBUG) + ch = logging.StreamHandler() + fmt = InvokeAILogFormatter() + ch.setFormatter(fmt) + logger.addHandler(ch) + self.loggers[name] = logger + return self.loggers[name] + +def test(): + logger = InvokeAILogger.getLogger('foobar') + logger.info('InvokeAI initialized') + logger.info('Running on GPU 14') + logger.info('Loading model foobar') + logger.debug('scanning for malware') + logger.debug('combobulating') + logger.warning('Oops. This model is strange.') + logger.error('Bailing out. sorry.') + logging.info('what happens when I log with logging?') From 8917a6d99beaec4ef7dbc09ae57814540f1b4265 Mon Sep 17 00:00:00 2001 From: Lincoln Stein Date: Tue, 11 Apr 2023 10:46:38 -0400 Subject: [PATCH 02/68] add logging support This commit adds invokeai.backend.util.logging, which provides support for formatted console and logfile messages that follow the status reporting conventions of earlier InvokeAI versions. Examples: ### A critical error (logging.CRITICAL) *** A non-fatal error (logging.ERROR) ** A warning (logging.WARNING) >> Informational message (logging.INFO) | Debugging message (logging.DEBUG) This style logs everything through a single logging object and is identical to using Python's `logging` module. The commonly-used module-level logging functions are implemented as simple pass-thrus to logging: import invokeai.backend.util.logging as ialog ialog.debug('this is a debugging message') ialog.info('this is a informational message') ialog.log(level=logging.CRITICAL, 'get out of dodge') ialog.disable(level=logging.INFO) ialog.basicConfig(filename='/var/log/invokeai.log') Internally, the invokeai logging module creates a new default logger named "invokeai" so that its logging does not interfere with other module's use of the vanilla logging module. So `logging.error("foo")` will go through the regular logging path and not add the additional message decorations. For more control, the logging module's object-oriented logging style is also supported. The API is identical to the vanilla logging usage. In fact, the only thing that has changed is that the getLogger() method adds a custom formatter to the log messages. import logging from invokeai.backend.util.logging import InvokeAILogger logger = InvokeAILogger.getLogger(__name__) fh = logging.FileHandler('/var/invokeai.log') logger.addHandler(fh) logger.critical('this will be logged to both the console and the log file') --- invokeai/backend/util/logging.py | 28 +++--- invokeai/frontend/CLI/CLI.py | 158 +++++++++++++++---------------- 2 files changed, 94 insertions(+), 92 deletions(-) diff --git a/invokeai/backend/util/logging.py b/invokeai/backend/util/logging.py index cce85fadbd..093c148beb 100644 --- a/invokeai/backend/util/logging.py +++ b/invokeai/backend/util/logging.py @@ -28,22 +28,28 @@ import invokeai.backend.util.logging as ialog ialog.debug('this is a debugging message') """ import logging -import sys -def debug(msg:str): - InvokeAILogger.getLogger().debug(msg) +# module level functions +def debug(msg, *args, **kwargs): + InvokeAILogger.getLogger().debug(msg, *args, **kwargs) -def info(msg:str): - InvokeAILogger.getLogger().info(msg) +def info(msg, *args, **kwargs): + InvokeAILogger.getLogger().info(msg, *args, **kwargs) -def warning(msg:str): - InvokeAILogger.getLogger().warning(msg) +def warning(msg, *args, **kwargs): + InvokeAILogger.getLogger().warning(msg, *args, **kwargs) -def error(msg:str): - InvokeAILogger.getLogger().error(msg) +def error(msg, *args, **kwargs): + InvokeAILogger.getLogger().error(msg, *args, **kwargs) -def critical(msg:str): - InvokeAILogger.getLogger().critical(msg) +def critical(msg, *args, **kwargs): + InvokeAILogger.getLogger().critical(msg, *args, **kwargs) + +def log(level, msg, *args, **kwargs): + InvokeAILogger.getLogger().log(level, msg, *args, **kwargs) + +def disable(level=logging.CRITICAL): + InvokeAILogger.getLogger().disable(level) class InvokeAILogFormatter(logging.Formatter): ''' diff --git a/invokeai/frontend/CLI/CLI.py b/invokeai/frontend/CLI/CLI.py index 352ee83812..f2027d8926 100644 --- a/invokeai/frontend/CLI/CLI.py +++ b/invokeai/frontend/CLI/CLI.py @@ -16,6 +16,7 @@ if sys.platform == "darwin": import pyparsing # type: ignore import invokeai.version as invokeai +import invokeai.backend.util.logging as ialog from ...backend import Generate, ModelManager from ...backend.args import Args, dream_cmd_from_png, metadata_dumps, metadata_from_png @@ -69,7 +70,7 @@ def main(): # run any post-install patches needed run_patches() - print(f">> Internet connectivity is {Globals.internet_available}") + ialog.info(f"Internet connectivity is {Globals.internet_available}") if not args.conf: config_file = os.path.join(Globals.root, "configs", "models.yaml") @@ -78,8 +79,8 @@ def main(): opt, FileNotFoundError(f"The file {config_file} could not be found.") ) - print(f">> {invokeai.__app_name__}, version {invokeai.__version__}") - print(f'>> InvokeAI runtime directory is "{Globals.root}"') + ialog.info(f"{invokeai.__app_name__}, version {invokeai.__version__}") + ialog.info(f'InvokeAI runtime directory is "{Globals.root}"') # loading here to avoid long delays on startup # these two lines prevent a horrible warning message from appearing @@ -121,7 +122,7 @@ def main(): else: raise FileNotFoundError(f"{opt.infile} not found.") except (FileNotFoundError, IOError) as e: - print(f"{e}. Aborting.") + ialog.critical('Aborted',exc_info=True) sys.exit(-1) # creating a Generate object: @@ -142,12 +143,12 @@ def main(): ) except (FileNotFoundError, TypeError, AssertionError) as e: report_model_error(opt, e) - except (IOError, KeyError) as e: - print(f"{e}. Aborting.") + except (IOError, KeyError): + ialog.critical("Aborted",exc_info=True) sys.exit(-1) if opt.seamless: - print(">> changed to seamless tiling mode") + ialog.info("Changed to seamless tiling mode") # preload the model try: @@ -180,9 +181,7 @@ def main(): f'\nGoodbye!\nYou can start InvokeAI again by running the "invoke.bat" (or "invoke.sh") script from {Globals.root}' ) except Exception: - print(">> An error occurred:") - traceback.print_exc() - + ialog.error("An error occurred",exc_info=True) # TODO: main_loop() has gotten busy. Needs to be refactored. def main_loop(gen, opt): @@ -248,7 +247,7 @@ def main_loop(gen, opt): if not opt.prompt: oldargs = metadata_from_png(opt.init_img) opt.prompt = oldargs.prompt - print(f'>> Retrieved old prompt "{opt.prompt}" from {opt.init_img}') + ialog.info(f'Retrieved old prompt "{opt.prompt}" from {opt.init_img}') except (OSError, AttributeError, KeyError): pass @@ -265,9 +264,9 @@ def main_loop(gen, opt): if opt.init_img is not None and re.match("^-\\d+$", opt.init_img): try: opt.init_img = last_results[int(opt.init_img)][0] - print(f">> Reusing previous image {opt.init_img}") + ialog.info(f"Reusing previous image {opt.init_img}") except IndexError: - print(f">> No previous initial image at position {opt.init_img} found") + ialog.info(f"No previous initial image at position {opt.init_img} found") opt.init_img = None continue @@ -288,9 +287,9 @@ def main_loop(gen, opt): if opt.seed is not None and opt.seed < 0 and operation != "postprocess": try: opt.seed = last_results[opt.seed][1] - print(f">> Reusing previous seed {opt.seed}") + ialog.info(f"Reusing previous seed {opt.seed}") except IndexError: - print(f">> No previous seed at position {opt.seed} found") + ialog.info(f"No previous seed at position {opt.seed} found") opt.seed = None continue @@ -309,7 +308,7 @@ def main_loop(gen, opt): subdir = subdir[: (path_max - 39 - len(os.path.abspath(opt.outdir)))] current_outdir = os.path.join(opt.outdir, subdir) - print('Writing files to directory: "' + current_outdir + '"') + ialog.info('Writing files to directory: "' + current_outdir + '"') # make sure the output directory exists if not os.path.exists(current_outdir): @@ -438,15 +437,14 @@ def main_loop(gen, opt): catch_interrupts=catch_ctrl_c, **vars(opt), ) - except (PromptParser.ParsingException, pyparsing.ParseException) as e: - print("** An error occurred while processing your prompt **") - print(f"** {str(e)} **") + except (PromptParser.ParsingException, pyparsing.ParseException): + ialog.error("An error occurred while processing your prompt",exc_info=True) elif operation == "postprocess": - print(f">> fixing {opt.prompt}") + ialog.info(f"fixing {opt.prompt}") opt.last_operation = do_postprocess(gen, opt, image_writer) elif operation == "mask": - print(f">> generating masks from {opt.prompt}") + ialog.info(f"generating masks from {opt.prompt}") do_textmask(gen, opt, image_writer) if opt.grid and len(grid_images) > 0: @@ -469,12 +467,12 @@ def main_loop(gen, opt): ) results = [[path, formatted_dream_prompt]] - except AssertionError as e: - print(e) + except AssertionError: + ialog.error(e) continue except OSError as e: - print(e) + ialog.error(e) continue print("Outputs:") @@ -513,7 +511,7 @@ def do_command(command: str, gen, opt: Args, completer) -> tuple: gen.set_model(model_name) add_embedding_terms(gen, completer) except KeyError as e: - print(str(e)) + ialog.error(e) except Exception as e: report_model_error(opt, e) completer.add_history(command) @@ -527,8 +525,8 @@ def do_command(command: str, gen, opt: Args, completer) -> tuple: elif command.startswith("!import"): path = shlex.split(command) if len(path) < 2: - print( - "** please provide (1) a URL to a .ckpt file to import; (2) a local path to a .ckpt file; or (3) a diffusers repository id in the form stabilityai/stable-diffusion-2-1" + ialog.warning( + "please provide (1) a URL to a .ckpt file to import; (2) a local path to a .ckpt file; or (3) a diffusers repository id in the form stabilityai/stable-diffusion-2-1" ) else: try: @@ -541,7 +539,7 @@ def do_command(command: str, gen, opt: Args, completer) -> tuple: elif command.startswith(("!convert", "!optimize")): path = shlex.split(command) if len(path) < 2: - print("** please provide the path to a .ckpt or .safetensors model") + ialog.warning("please provide the path to a .ckpt or .safetensors model") else: try: convert_model(path[1], gen, opt, completer) @@ -553,7 +551,7 @@ def do_command(command: str, gen, opt: Args, completer) -> tuple: elif command.startswith("!edit"): path = shlex.split(command) if len(path) < 2: - print("** please provide the name of a model") + ialog.warning("please provide the name of a model") else: edit_model(path[1], gen, opt, completer) completer.add_history(command) @@ -562,7 +560,7 @@ def do_command(command: str, gen, opt: Args, completer) -> tuple: elif command.startswith("!del"): path = shlex.split(command) if len(path) < 2: - print("** please provide the name of a model") + ialog.warning("please provide the name of a model") else: del_config(path[1], gen, opt, completer) completer.add_history(command) @@ -642,8 +640,8 @@ def import_model(model_path: str, gen, opt, completer): try: default_name = url_attachment_name(model_path) default_name = Path(default_name).stem - except Exception as e: - print(f"** URL: {str(e)}") + except Exception: + ialog.warning(f"A problem occurred while assigning the name of the downloaded model",exc_info=True) model_name, model_desc = _get_model_name_and_desc( gen.model_manager, completer, @@ -664,11 +662,11 @@ def import_model(model_path: str, gen, opt, completer): model_config_file=config_file, ) if not imported_name: - print("** Aborting import.") + ialog.error("Aborting import.") return if not _verify_load(imported_name, gen): - print("** model failed to load. Discarding configuration entry") + ialog.error("model failed to load. Discarding configuration entry") gen.model_manager.del_model(imported_name) return if click.confirm("Make this the default model?", default=False): @@ -676,7 +674,7 @@ def import_model(model_path: str, gen, opt, completer): gen.model_manager.commit(opt.conf) completer.update_models(gen.model_manager.list_models()) - print(f">> {imported_name} successfully installed") + ialog.info(f"{imported_name} successfully installed") def _pick_configuration_file(completer)->Path: print( @@ -720,21 +718,21 @@ Please select the type of this model: return choice def _verify_load(model_name: str, gen) -> bool: - print(">> Verifying that new model loads...") + ialog.info("Verifying that new model loads...") current_model = gen.model_name try: if not gen.set_model(model_name): return except Exception as e: - print(f"** model failed to load: {str(e)}") - print( + ialog.warning(f"model failed to load: {str(e)}") + ialog.warning( "** note that importing 2.X checkpoints is not supported. Please use !convert_model instead." ) return False if click.confirm("Keep model loaded?", default=True): gen.set_model(model_name) else: - print(">> Restoring previous model") + ialog.info("Restoring previous model") gen.set_model(current_model) return True @@ -757,7 +755,7 @@ def convert_model(model_name_or_path: Union[Path, str], gen, opt, completer): ckpt_path = None original_config_file = None if model_name_or_path == gen.model_name: - print("** Can't convert the active model. !switch to another model first. **") + ialog.warning("Can't convert the active model. !switch to another model first. **") return elif model_info := manager.model_info(model_name_or_path): if "weights" in model_info: @@ -767,7 +765,7 @@ def convert_model(model_name_or_path: Union[Path, str], gen, opt, completer): model_description = model_info["description"] vae_path = model_info.get("vae") else: - print(f"** {model_name_or_path} is not a legacy .ckpt weights file") + ialog.warning(f"{model_name_or_path} is not a legacy .ckpt weights file") return model_name = manager.convert_and_import( ckpt_path, @@ -788,16 +786,16 @@ def convert_model(model_name_or_path: Union[Path, str], gen, opt, completer): manager.commit(opt.conf) if click.confirm(f"Delete the original .ckpt file at {ckpt_path}?", default=False): ckpt_path.unlink(missing_ok=True) - print(f"{ckpt_path} deleted") + ialog.warning(f"{ckpt_path} deleted") def del_config(model_name: str, gen, opt, completer): current_model = gen.model_name if model_name == current_model: - print("** Can't delete active model. !switch to another model first. **") + ialog.warning("Can't delete active model. !switch to another model first. **") return if model_name not in gen.model_manager.config: - print(f"** Unknown model {model_name}") + ialog.warning(f"Unknown model {model_name}") return if not click.confirm( @@ -810,17 +808,17 @@ def del_config(model_name: str, gen, opt, completer): ) gen.model_manager.del_model(model_name, delete_files=delete_completely) gen.model_manager.commit(opt.conf) - print(f"** {model_name} deleted") + ialog.warning(f"{model_name} deleted") completer.update_models(gen.model_manager.list_models()) def edit_model(model_name: str, gen, opt, completer): manager = gen.model_manager if not (info := manager.model_info(model_name)): - print(f"** Unknown model {model_name}") + ialog.warning(f"** Unknown model {model_name}") return - - print(f"\n>> Editing model {model_name} from configuration file {opt.conf}") + print() + ialog.info(f"Editing model {model_name} from configuration file {opt.conf}") new_name = _get_model_name(manager.list_models(), completer, model_name) for attribute in info.keys(): @@ -858,7 +856,7 @@ def edit_model(model_name: str, gen, opt, completer): manager.set_default_model(new_name) manager.commit(opt.conf) completer.update_models(manager.list_models()) - print(">> Model successfully updated") + ialog.info("Model successfully updated") def _get_model_name(existing_names, completer, default_name: str = "") -> str: @@ -869,11 +867,11 @@ def _get_model_name(existing_names, completer, default_name: str = "") -> str: if len(model_name) == 0: model_name = default_name if not re.match("^[\w._+:/-]+$", model_name): - print( - '** model name must contain only words, digits and the characters "._+:/-" **' + ialog.warning( + 'model name must contain only words, digits and the characters "._+:/-" **' ) elif model_name != default_name and model_name in existing_names: - print(f"** the name {model_name} is already in use. Pick another.") + ialog.warning(f"the name {model_name} is already in use. Pick another.") else: done = True return model_name @@ -940,11 +938,10 @@ def do_postprocess(gen, opt, callback): opt=opt, ) except OSError: - print(traceback.format_exc(), file=sys.stderr) - print(f"** {file_path}: file could not be read") + ialog.error(f"{file_path}: file could not be read",exc_info=True) return except (KeyError, AttributeError): - print(traceback.format_exc(), file=sys.stderr) + ialog.error(f"an error occurred while applying the {tool} postprocessor",exc_info=True) return return opt.last_operation @@ -999,13 +996,13 @@ def prepare_image_metadata( try: filename = opt.fnformat.format(**wildcards) except KeyError as e: - print( - f"** The filename format contains an unknown key '{e.args[0]}'. Will use {{prefix}}.{{seed}}.png' instead" + ialog.error( + f"The filename format contains an unknown key '{e.args[0]}'. Will use {{prefix}}.{{seed}}.png' instead" ) filename = f"{prefix}.{seed}.png" except IndexError: - print( - "** The filename format is broken or complete. Will use '{prefix}.{seed}.png' instead" + ialog.error( + "The filename format is broken or complete. Will use '{prefix}.{seed}.png' instead" ) filename = f"{prefix}.{seed}.png" @@ -1094,14 +1091,14 @@ def split_variations(variations_string) -> list: for part in variations_string.split(","): seed_and_weight = part.split(":") if len(seed_and_weight) != 2: - print(f'** Could not parse with_variation part "{part}"') + ialog.warning(f'Could not parse with_variation part "{part}"') broken = True break try: seed = int(seed_and_weight[0]) weight = float(seed_and_weight[1]) except ValueError: - print(f'** Could not parse with_variation part "{part}"') + ialog.warning(f'Could not parse with_variation part "{part}"') broken = True break parts.append([seed, weight]) @@ -1125,23 +1122,23 @@ def load_face_restoration(opt): opt.gfpgan_model_path ) else: - print(">> Face restoration disabled") + ialog.info("Face restoration disabled") if opt.esrgan: esrgan = restoration.load_esrgan(opt.esrgan_bg_tile) else: - print(">> Upscaling disabled") + ialog.info("Upscaling disabled") else: - print(">> Face restoration and upscaling disabled") + ialog.info("Face restoration and upscaling disabled") except (ModuleNotFoundError, ImportError): print(traceback.format_exc(), file=sys.stderr) - print(">> You may need to install the ESRGAN and/or GFPGAN modules") + ialog.info("You may need to install the ESRGAN and/or GFPGAN modules") return gfpgan, codeformer, esrgan def make_step_callback(gen, opt, prefix): destination = os.path.join(opt.outdir, "intermediates", prefix) os.makedirs(destination, exist_ok=True) - print(f">> Intermediate images will be written into {destination}") + ialog.info(f"Intermediate images will be written into {destination}") def callback(state: PipelineIntermediateState): latents = state.latents @@ -1183,21 +1180,20 @@ def retrieve_dream_command(opt, command, completer): try: cmd = dream_cmd_from_png(path) except OSError: - print(f"## {tokens[0]}: file could not be read") + ialog.error(f"{tokens[0]}: file could not be read") except (KeyError, AttributeError, IndexError): - print(f"## {tokens[0]}: file has no metadata") + ialog.error(f"{tokens[0]}: file has no metadata") except: - print(f"## {tokens[0]}: file could not be processed") + ialog.error(f"{tokens[0]}: file could not be processed") if len(cmd) > 0: completer.set_line(cmd) - def write_commands(opt, file_path: str, outfilepath: str): dir, basename = os.path.split(file_path) try: paths = sorted(list(Path(dir).glob(basename))) except ValueError: - print(f'## "{basename}": unacceptable pattern') + ialog.error(f'"{basename}": unacceptable pattern') return commands = [] @@ -1206,9 +1202,9 @@ def write_commands(opt, file_path: str, outfilepath: str): try: cmd = dream_cmd_from_png(path) except (KeyError, AttributeError, IndexError): - print(f"## {path}: file has no metadata") + ialog.error(f"{path}: file has no metadata") except: - print(f"## {path}: file could not be processed") + ialog.error(f"{path}: file could not be processed") if cmd: commands.append(f"# {path}") commands.append(cmd) @@ -1218,18 +1214,18 @@ def write_commands(opt, file_path: str, outfilepath: str): outfilepath = os.path.join(opt.outdir, basename) with open(outfilepath, "w", encoding="utf-8") as f: f.write("\n".join(commands)) - print(f">> File {outfilepath} with commands created") + ialog.info(f"File {outfilepath} with commands created") def report_model_error(opt: Namespace, e: Exception): - print(f'** An error occurred while attempting to initialize the model: "{str(e)}"') - print( - "** This can be caused by a missing or corrupted models file, and can sometimes be fixed by (re)installing the models." + ialog.warning(f'An error occurred while attempting to initialize the model: "{str(e)}"') + ialog.warning( + "This can be caused by a missing or corrupted models file, and can sometimes be fixed by (re)installing the models." ) yes_to_all = os.environ.get("INVOKE_MODEL_RECONFIGURE") if yes_to_all: - print( - "** Reconfiguration is being forced by environment variable INVOKE_MODEL_RECONFIGURE" + ialog.warning( + "Reconfiguration is being forced by environment variable INVOKE_MODEL_RECONFIGURE" ) else: if not click.confirm( @@ -1238,7 +1234,7 @@ def report_model_error(opt: Namespace, e: Exception): ): return - print("invokeai-configure is launching....\n") + ialog.info("invokeai-configure is launching....\n") # Match arguments that were set on the CLI # only the arguments accepted by the configuration script are parsed @@ -1255,7 +1251,7 @@ def report_model_error(opt: Namespace, e: Exception): from ..install import invokeai_configure invokeai_configure() - print("** InvokeAI will now restart") + ialog.warning("InvokeAI will now restart") sys.argv = previous_args main() # would rather do a os.exec(), but doesn't exist? sys.exit(0) From f904f14f9e72c9acec449b19286f27b291f506d8 Mon Sep 17 00:00:00 2001 From: Lincoln Stein Date: Tue, 11 Apr 2023 11:10:43 -0400 Subject: [PATCH 03/68] add missing module-level methods --- invokeai/backend/util/logging.py | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/invokeai/backend/util/logging.py b/invokeai/backend/util/logging.py index 093c148beb..c2f999e50f 100644 --- a/invokeai/backend/util/logging.py +++ b/invokeai/backend/util/logging.py @@ -51,6 +51,9 @@ def log(level, msg, *args, **kwargs): def disable(level=logging.CRITICAL): InvokeAILogger.getLogger().disable(level) +def basicConfig(**kwargs): + InvokeAILogger.getLogger().basicConfig(**kwargs) + class InvokeAILogFormatter(logging.Formatter): ''' Repurposed from: @@ -100,14 +103,3 @@ class InvokeAILogger(object): logger.addHandler(ch) self.loggers[name] = logger return self.loggers[name] - -def test(): - logger = InvokeAILogger.getLogger('foobar') - logger.info('InvokeAI initialized') - logger.info('Running on GPU 14') - logger.info('Loading model foobar') - logger.debug('scanning for malware') - logger.debug('combobulating') - logger.warning('Oops. This model is strange.') - logger.error('Bailing out. sorry.') - logging.info('what happens when I log with logging?') From f3081e7013abfcec58944e6d096c47e752066f2b Mon Sep 17 00:00:00 2001 From: Lincoln Stein Date: Tue, 11 Apr 2023 12:23:13 -0400 Subject: [PATCH 04/68] add module-level getLogger() method --- invokeai/backend/util/logging.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/invokeai/backend/util/logging.py b/invokeai/backend/util/logging.py index c2f999e50f..6b85b5b288 100644 --- a/invokeai/backend/util/logging.py +++ b/invokeai/backend/util/logging.py @@ -54,13 +54,16 @@ def disable(level=logging.CRITICAL): def basicConfig(**kwargs): InvokeAILogger.getLogger().basicConfig(**kwargs) +def getLogger(name: str=None)->logging.Logger: + return InvokeAILogger.getLogger(name) + class InvokeAILogFormatter(logging.Formatter): ''' Repurposed from: https://stackoverflow.com/questions/14844970/modifying-logging-message-format-based-on-message-logging-level-in-python3 ''' crit_fmt = "### %(msg)s" - err_fmt = "!!! %(msg)s !!!" + err_fmt = "*** %(msg)s" warn_fmt = "** %(msg)s" info_fmt = ">> %(msg)s" dbg_fmt = " | %(msg)s" From c132dbdefabe34619697f97da753fc1f94e3d6d6 Mon Sep 17 00:00:00 2001 From: Lincoln Stein Date: Tue, 11 Apr 2023 18:48:20 -0400 Subject: [PATCH 05/68] change "ialog" to "log" --- .../backend/model_management/model_manager.py | 140 +++++++++--------- invokeai/frontend/CLI/CLI.py | 132 ++++++++--------- 2 files changed, 136 insertions(+), 136 deletions(-) diff --git a/invokeai/backend/model_management/model_manager.py b/invokeai/backend/model_management/model_manager.py index 4f9ea75964..f10cd8c4f5 100644 --- a/invokeai/backend/model_management/model_manager.py +++ b/invokeai/backend/model_management/model_manager.py @@ -24,7 +24,7 @@ import safetensors import safetensors.torch import torch import transformers -import invokeai.backend.util.logging as ialog +import invokeai.backend.util.logging as log from diffusers import ( AutoencoderKL, UNet2DConditionModel, @@ -133,7 +133,7 @@ class ModelManager(object): ) if not self.valid_model(model_name): - ialog.error( + log.error( f'"{model_name}" is not a known model name. Please check your models.yaml file' ) return self.current_model @@ -145,7 +145,7 @@ class ModelManager(object): if model_name in self.models: requested_model = self.models[model_name]["model"] - ialog.info(f"Retrieving model {model_name} from system RAM cache") + log.info(f"Retrieving model {model_name} from system RAM cache") requested_model.ready() width = self.models[model_name]["width"] height = self.models[model_name]["height"] @@ -380,7 +380,7 @@ class ModelManager(object): """ omega = self.config if model_name not in omega: - ialog.error(f"Unknown model {model_name}") + log.error(f"Unknown model {model_name}") return # save these for use in deletion later conf = omega[model_name] @@ -393,13 +393,13 @@ class ModelManager(object): self.stack.remove(model_name) if delete_files: if weights: - ialog.info(f"Deleting file {weights}") + log.info(f"Deleting file {weights}") Path(weights).unlink(missing_ok=True) elif path: - ialog.info(f"Deleting directory {path}") + log.info(f"Deleting directory {path}") rmtree(path, ignore_errors=True) elif repo_id: - ialog.info(f"Deleting the cached model directory for {repo_id}") + log.info(f"Deleting the cached model directory for {repo_id}") self._delete_model_from_cache(repo_id) def add_model( @@ -440,7 +440,7 @@ class ModelManager(object): def _load_model(self, model_name: str): """Load and initialize the model from configuration variables passed at object creation time""" if model_name not in self.config: - ialog.error( + log.error( f'"{model_name}" is not a known model name. Please check your models.yaml file' ) return @@ -458,7 +458,7 @@ class ModelManager(object): model_format = mconfig.get("format", "ckpt") if model_format == "ckpt": weights = mconfig.weights - ialog.info(f"Loading {model_name} from {weights}") + log.info(f"Loading {model_name} from {weights}") model, width, height, model_hash = self._load_ckpt_model( model_name, mconfig ) @@ -474,13 +474,13 @@ class ModelManager(object): # usage statistics toc = time.time() - ialog.info("Model loaded in " + "%4.2fs" % (toc - tic)) + log.info("Model loaded in " + "%4.2fs" % (toc - tic)) if self._has_cuda(): - ialog.info( + log.info( "Max VRAM used to load the model: "+ "%4.2fG" % (torch.cuda.max_memory_allocated() / 1e9) ) - ialog.info( + log.info( "Current VRAM usage: "+ "%4.2fG" % (torch.cuda.memory_allocated() / 1e9) ) @@ -490,11 +490,11 @@ class ModelManager(object): name_or_path = self.model_name_or_path(mconfig) using_fp16 = self.precision == "float16" - ialog.info(f"Loading diffusers model from {name_or_path}") + log.info(f"Loading diffusers model from {name_or_path}") if using_fp16: - ialog.debug("Using faster float16 precision") + log.debug("Using faster float16 precision") else: - ialog.debug("Using more accurate float32 precision") + log.debug("Using more accurate float32 precision") # TODO: scan weights maybe? pipeline_args: dict[str, Any] = dict( @@ -526,7 +526,7 @@ class ModelManager(object): if str(e).startswith("fp16 is not a valid"): pass else: - ialog.error( + log.error( f"An unexpected error occurred while downloading the model: {e})" ) if pipeline: @@ -545,7 +545,7 @@ class ModelManager(object): # square images??? width = pipeline.unet.config.sample_size * pipeline.vae_scale_factor height = width - ialog.debug(f"Default image dimensions = {width} x {height}") + log.debug(f"Default image dimensions = {width} x {height}") return pipeline, width, height, model_hash @@ -562,7 +562,7 @@ class ModelManager(object): weights = os.path.normpath(os.path.join(Globals.root, weights)) # Convert to diffusers and return a diffusers pipeline - ialog.info(f"Converting legacy checkpoint {model_name} into a diffusers model...") + log.info(f"Converting legacy checkpoint {model_name} into a diffusers model...") from . import load_pipeline_from_original_stable_diffusion_ckpt @@ -627,7 +627,7 @@ class ModelManager(object): if model_name not in self.models: return - ialog.info(f"Offloading {model_name} to CPU") + log.info(f"Offloading {model_name} to CPU") model = self.models[model_name]["model"] model.offload_all() self.current_model = None @@ -643,26 +643,26 @@ class ModelManager(object): and option to exit if an infected file is identified. """ # scan model - ialog.debug(f"Scanning Model: {model_name}") + log.debug(f"Scanning Model: {model_name}") scan_result = scan_file_path(checkpoint) if scan_result.infected_files != 0: if scan_result.infected_files == 1: - ialog.critical(f"Issues Found In Model: {scan_result.issues_count}") - ialog.critical("The model you are trying to load seems to be infected.") - ialog.critical("For your safety, InvokeAI will not load this model.") - ialog.critical("Please use checkpoints from trusted sources.") - ialog.critical("Exiting InvokeAI") + log.critical(f"Issues Found In Model: {scan_result.issues_count}") + log.critical("The model you are trying to load seems to be infected.") + log.critical("For your safety, InvokeAI will not load this model.") + log.critical("Please use checkpoints from trusted sources.") + log.critical("Exiting InvokeAI") sys.exit() else: - ialog.warning("InvokeAI was unable to scan the model you are using.") + log.warning("InvokeAI was unable to scan the model you are using.") model_safe_check_fail = ask_user( "Do you want to to continue loading the model?", ["y", "n"] ) if model_safe_check_fail.lower() != "y": - ialog.critical("Exiting InvokeAI") + log.critical("Exiting InvokeAI") sys.exit() else: - ialog.debug("Model scanned ok") + log.debug("Model scanned ok") def import_diffuser_model( self, @@ -779,24 +779,24 @@ class ModelManager(object): model_path: Path = None thing = path_url_or_repo # to save typing - ialog.info(f"Probing {thing} for import") + log.info(f"Probing {thing} for import") if thing.startswith(("http:", "https:", "ftp:")): - ialog.info(f"{thing} appears to be a URL") + log.info(f"{thing} appears to be a URL") model_path = self._resolve_path( thing, "models/ldm/stable-diffusion-v1" ) # _resolve_path does a download if needed elif Path(thing).is_file() and thing.endswith((".ckpt", ".safetensors")): if Path(thing).stem in ["model", "diffusion_pytorch_model"]: - ialog.debug(f"{Path(thing).name} appears to be part of a diffusers model. Skipping import") + log.debug(f"{Path(thing).name} appears to be part of a diffusers model. Skipping import") return else: - ialog.debug(f"{thing} appears to be a checkpoint file on disk") + log.debug(f"{thing} appears to be a checkpoint file on disk") model_path = self._resolve_path(thing, "models/ldm/stable-diffusion-v1") elif Path(thing).is_dir() and Path(thing, "model_index.json").exists(): - ialog.debug(f"{thing} appears to be a diffusers file on disk") + log.debug(f"{thing} appears to be a diffusers file on disk") model_name = self.import_diffuser_model( thing, vae=dict(repo_id="stabilityai/sd-vae-ft-mse"), @@ -807,30 +807,30 @@ class ModelManager(object): elif Path(thing).is_dir(): if (Path(thing) / "model_index.json").exists(): - ialog.debug(f"{thing} appears to be a diffusers model.") + log.debug(f"{thing} appears to be a diffusers model.") model_name = self.import_diffuser_model( thing, commit_to_conf=commit_to_conf ) else: - ialog.debug(f"{thing} appears to be a directory. Will scan for models to import") + log.debug(f"{thing} appears to be a directory. Will scan for models to import") for m in list(Path(thing).rglob("*.ckpt")) + list( Path(thing).rglob("*.safetensors") ): if model_name := self.heuristic_import( str(m), commit_to_conf=commit_to_conf ): - ialog.info(f"{model_name} successfully imported") + log.info(f"{model_name} successfully imported") return model_name elif re.match(r"^[\w.+-]+/[\w.+-]+$", thing): - ialog.debug(f"{thing} appears to be a HuggingFace diffusers repo_id") + log.debug(f"{thing} appears to be a HuggingFace diffusers repo_id") model_name = self.import_diffuser_model( thing, commit_to_conf=commit_to_conf ) pipeline, _, _, _ = self._load_diffusers_model(self.config[model_name]) return model_name else: - ialog.warning(f"{thing}: Unknown thing. Please provide a URL, file path, directory or HuggingFace repo_id") + log.warning(f"{thing}: Unknown thing. Please provide a URL, file path, directory or HuggingFace repo_id") # Model_path is set in the event of a legacy checkpoint file. # If not set, we're all done @@ -838,7 +838,7 @@ class ModelManager(object): return if model_path.stem in self.config: # already imported - ialog.debug("Already imported. Skipping") + log.debug("Already imported. Skipping") return model_path.stem # another round of heuristics to guess the correct config file. @@ -854,38 +854,38 @@ class ModelManager(object): # look for a like-named .yaml file in same directory if model_path.with_suffix(".yaml").exists(): model_config_file = model_path.with_suffix(".yaml") - ialog.debug(f"Using config file {model_config_file.name}") + log.debug(f"Using config file {model_config_file.name}") else: model_type = self.probe_model_type(checkpoint) if model_type == SDLegacyType.V1: - ialog.debug("SD-v1 model detected") + log.debug("SD-v1 model detected") model_config_file = Path( Globals.root, "configs/stable-diffusion/v1-inference.yaml" ) elif model_type == SDLegacyType.V1_INPAINT: - ialog.debug("SD-v1 inpainting model detected") + log.debug("SD-v1 inpainting model detected") model_config_file = Path( Globals.root, "configs/stable-diffusion/v1-inpainting-inference.yaml", ) elif model_type == SDLegacyType.V2_v: - ialog.debug("SD-v2-v model detected") + log.debug("SD-v2-v model detected") model_config_file = Path( Globals.root, "configs/stable-diffusion/v2-inference-v.yaml" ) elif model_type == SDLegacyType.V2_e: - ialog.debug("SD-v2-e model detected") + log.debug("SD-v2-e model detected") model_config_file = Path( Globals.root, "configs/stable-diffusion/v2-inference.yaml" ) elif model_type == SDLegacyType.V2: - ialog.warning( + log.warning( f"{thing} is a V2 checkpoint file, but its parameterization cannot be determined. Please provide configuration file path." ) return else: - ialog.warning( + log.warning( f"{thing} is a legacy checkpoint file but not a known Stable Diffusion model. Please provide configuration file path." ) return @@ -902,7 +902,7 @@ class ModelManager(object): for suffix in ["pt", "ckpt", "safetensors"]: if (model_path.with_suffix(f".vae.{suffix}")).exists(): vae_path = model_path.with_suffix(f".vae.{suffix}") - ialog.debug(f"Using VAE file {vae_path.name}") + log.debug(f"Using VAE file {vae_path.name}") vae = None if vae_path else dict(repo_id="stabilityai/sd-vae-ft-mse") diffuser_path = Path( @@ -948,14 +948,14 @@ class ModelManager(object): from . import convert_ckpt_to_diffusers if diffusers_path.exists(): - ialog.error( + log.error( f"The path {str(diffusers_path)} already exists. Please move or remove it and try again." ) return model_name = model_name or diffusers_path.name model_description = model_description or f"Converted version of {model_name}" - ialog.debug(f"Converting {model_name} to diffusers (30-60s)") + log.debug(f"Converting {model_name} to diffusers (30-60s)") try: # By passing the specified VAE to the conversion function, the autoencoder # will be built into the model rather than tacked on afterward via the config file @@ -972,10 +972,10 @@ class ModelManager(object): vae_path=vae_path, scan_needed=scan_needed, ) - ialog.debug( + log.debug( f"Success. Converted model is now located at {str(diffusers_path)}" ) - ialog.debug(f"Writing new config file entry for {model_name}") + log.debug(f"Writing new config file entry for {model_name}") new_config = dict( path=str(diffusers_path), description=model_description, @@ -986,17 +986,17 @@ class ModelManager(object): self.add_model(model_name, new_config, True) if commit_to_conf: self.commit(commit_to_conf) - ialog.debug("Conversion succeeded") + log.debug("Conversion succeeded") except Exception as e: - ialog.warning(f"Conversion failed: {str(e)}") - ialog.warning( + log.warning(f"Conversion failed: {str(e)}") + log.warning( "If you are trying to convert an inpainting or 2.X model, please indicate the correct config file (e.g. v1-inpainting-inference.yaml)" ) return model_name def search_models(self, search_folder): - ialog.info(f"Finding Models In: {search_folder}") + log.info(f"Finding Models In: {search_folder}") models_folder_ckpt = Path(search_folder).glob("**/*.ckpt") models_folder_safetensors = Path(search_folder).glob("**/*.safetensors") @@ -1020,7 +1020,7 @@ class ModelManager(object): num_loaded_models = len(self.models) if num_loaded_models >= self.max_loaded_models: least_recent_model = self._pop_oldest_model() - ialog.info( + log.info( f"Cache limit (max={self.max_loaded_models}) reached. Purging {least_recent_model}" ) if least_recent_model is not None: @@ -1029,7 +1029,7 @@ class ModelManager(object): def print_vram_usage(self) -> None: if self._has_cuda: - ialog.info( + log.info( "Current VRAM usage:"+ "%4.2fG" % (torch.cuda.memory_allocated() / 1e9), ) @@ -1119,10 +1119,10 @@ class ModelManager(object): dest = hub / model.stem if dest.exists() and not source.exists(): continue - ialog.info(f"{source} => {dest}") + log.info(f"{source} => {dest}") if source.exists(): if dest.is_symlink(): - ialog.warning(f"Found symlink at {dest.name}. Not migrating.") + log.warning(f"Found symlink at {dest.name}. Not migrating.") elif dest.exists(): if source.is_dir(): rmtree(source) @@ -1139,7 +1139,7 @@ class ModelManager(object): ] for d in empty: os.rmdir(d) - ialog.info("Migration is done. Continuing...") + log.info("Migration is done. Continuing...") def _resolve_path( self, source: Union[str, Path], dest_directory: str @@ -1182,14 +1182,14 @@ class ModelManager(object): def _add_embeddings_to_model(self, model: StableDiffusionGeneratorPipeline): if self.embedding_path is not None: - ialog.info(f"Loading embeddings from {self.embedding_path}") + log.info(f"Loading embeddings from {self.embedding_path}") for root, _, files in os.walk(self.embedding_path): for name in files: ti_path = os.path.join(root, name) model.textual_inversion_manager.load_textual_inversion( ti_path, defer_injecting_tokens=True ) - ialog.info( + log.info( f'Textual inversion triggers: {", ".join(sorted(model.textual_inversion_manager.get_all_trigger_strings()))}' ) @@ -1212,7 +1212,7 @@ class ModelManager(object): with open(hashpath) as f: hash = f.read() return hash - ialog.debug("Calculating sha256 hash of model files") + log.debug("Calculating sha256 hash of model files") tic = time.time() sha = hashlib.sha256() count = 0 @@ -1224,7 +1224,7 @@ class ModelManager(object): sha.update(chunk) hash = sha.hexdigest() toc = time.time() - ialog.debug(f"sha256 = {hash} ({count} files hashed in", "%4.2fs)" % (toc - tic)) + log.debug(f"sha256 = {hash} ({count} files hashed in", "%4.2fs)" % (toc - tic)) with open(hashpath, "w") as f: f.write(hash) return hash @@ -1242,13 +1242,13 @@ class ModelManager(object): hash = f.read() return hash - ialog.debug("Calculating sha256 hash of weights file") + log.debug("Calculating sha256 hash of weights file") tic = time.time() sha = hashlib.sha256() sha.update(data) hash = sha.hexdigest() toc = time.time() - ialog.debug(f"sha256 = {hash} "+"(%4.2fs)" % (toc - tic)) + log.debug(f"sha256 = {hash} "+"(%4.2fs)" % (toc - tic)) with open(hashpath, "w") as f: f.write(hash) @@ -1269,12 +1269,12 @@ class ModelManager(object): local_files_only=not Globals.internet_available, ) - ialog.debug(f"Loading diffusers VAE from {name_or_path}") + log.debug(f"Loading diffusers VAE from {name_or_path}") if using_fp16: vae_args.update(torch_dtype=torch.float16) fp_args_list = [{"revision": "fp16"}, {}] else: - ialog.debug("Using more accurate float32 precision") + log.debug("Using more accurate float32 precision") fp_args_list = [{}] vae = None @@ -1298,7 +1298,7 @@ class ModelManager(object): break if not vae and deferred_error: - ialog.warning(f"Could not load VAE {name_or_path}: {str(deferred_error)}") + log.warning(f"Could not load VAE {name_or_path}: {str(deferred_error)}") return vae @@ -1314,7 +1314,7 @@ class ModelManager(object): for revision in repo.revisions: hashes_to_delete.add(revision.commit_hash) strategy = cache_info.delete_revisions(*hashes_to_delete) - ialog.warning( + log.warning( f"Deletion of this model is expected to free {strategy.expected_freed_size_str}" ) strategy.execute() diff --git a/invokeai/frontend/CLI/CLI.py b/invokeai/frontend/CLI/CLI.py index f2027d8926..85a4d1a37d 100644 --- a/invokeai/frontend/CLI/CLI.py +++ b/invokeai/frontend/CLI/CLI.py @@ -16,7 +16,7 @@ if sys.platform == "darwin": import pyparsing # type: ignore import invokeai.version as invokeai -import invokeai.backend.util.logging as ialog +import invokeai.backend.util.logging as log from ...backend import Generate, ModelManager from ...backend.args import Args, dream_cmd_from_png, metadata_dumps, metadata_from_png @@ -70,7 +70,7 @@ def main(): # run any post-install patches needed run_patches() - ialog.info(f"Internet connectivity is {Globals.internet_available}") + log.info(f"Internet connectivity is {Globals.internet_available}") if not args.conf: config_file = os.path.join(Globals.root, "configs", "models.yaml") @@ -79,8 +79,8 @@ def main(): opt, FileNotFoundError(f"The file {config_file} could not be found.") ) - ialog.info(f"{invokeai.__app_name__}, version {invokeai.__version__}") - ialog.info(f'InvokeAI runtime directory is "{Globals.root}"') + log.info(f"{invokeai.__app_name__}, version {invokeai.__version__}") + log.info(f'InvokeAI runtime directory is "{Globals.root}"') # loading here to avoid long delays on startup # these two lines prevent a horrible warning message from appearing @@ -122,7 +122,7 @@ def main(): else: raise FileNotFoundError(f"{opt.infile} not found.") except (FileNotFoundError, IOError) as e: - ialog.critical('Aborted',exc_info=True) + log.critical('Aborted',exc_info=True) sys.exit(-1) # creating a Generate object: @@ -144,11 +144,11 @@ def main(): except (FileNotFoundError, TypeError, AssertionError) as e: report_model_error(opt, e) except (IOError, KeyError): - ialog.critical("Aborted",exc_info=True) + log.critical("Aborted",exc_info=True) sys.exit(-1) if opt.seamless: - ialog.info("Changed to seamless tiling mode") + log.info("Changed to seamless tiling mode") # preload the model try: @@ -181,7 +181,7 @@ def main(): f'\nGoodbye!\nYou can start InvokeAI again by running the "invoke.bat" (or "invoke.sh") script from {Globals.root}' ) except Exception: - ialog.error("An error occurred",exc_info=True) + log.error("An error occurred",exc_info=True) # TODO: main_loop() has gotten busy. Needs to be refactored. def main_loop(gen, opt): @@ -247,7 +247,7 @@ def main_loop(gen, opt): if not opt.prompt: oldargs = metadata_from_png(opt.init_img) opt.prompt = oldargs.prompt - ialog.info(f'Retrieved old prompt "{opt.prompt}" from {opt.init_img}') + log.info(f'Retrieved old prompt "{opt.prompt}" from {opt.init_img}') except (OSError, AttributeError, KeyError): pass @@ -264,9 +264,9 @@ def main_loop(gen, opt): if opt.init_img is not None and re.match("^-\\d+$", opt.init_img): try: opt.init_img = last_results[int(opt.init_img)][0] - ialog.info(f"Reusing previous image {opt.init_img}") + log.info(f"Reusing previous image {opt.init_img}") except IndexError: - ialog.info(f"No previous initial image at position {opt.init_img} found") + log.info(f"No previous initial image at position {opt.init_img} found") opt.init_img = None continue @@ -287,9 +287,9 @@ def main_loop(gen, opt): if opt.seed is not None and opt.seed < 0 and operation != "postprocess": try: opt.seed = last_results[opt.seed][1] - ialog.info(f"Reusing previous seed {opt.seed}") + log.info(f"Reusing previous seed {opt.seed}") except IndexError: - ialog.info(f"No previous seed at position {opt.seed} found") + log.info(f"No previous seed at position {opt.seed} found") opt.seed = None continue @@ -308,7 +308,7 @@ def main_loop(gen, opt): subdir = subdir[: (path_max - 39 - len(os.path.abspath(opt.outdir)))] current_outdir = os.path.join(opt.outdir, subdir) - ialog.info('Writing files to directory: "' + current_outdir + '"') + log.info('Writing files to directory: "' + current_outdir + '"') # make sure the output directory exists if not os.path.exists(current_outdir): @@ -438,13 +438,13 @@ def main_loop(gen, opt): **vars(opt), ) except (PromptParser.ParsingException, pyparsing.ParseException): - ialog.error("An error occurred while processing your prompt",exc_info=True) + log.error("An error occurred while processing your prompt",exc_info=True) elif operation == "postprocess": - ialog.info(f"fixing {opt.prompt}") + log.info(f"fixing {opt.prompt}") opt.last_operation = do_postprocess(gen, opt, image_writer) elif operation == "mask": - ialog.info(f"generating masks from {opt.prompt}") + log.info(f"generating masks from {opt.prompt}") do_textmask(gen, opt, image_writer) if opt.grid and len(grid_images) > 0: @@ -468,11 +468,11 @@ def main_loop(gen, opt): results = [[path, formatted_dream_prompt]] except AssertionError: - ialog.error(e) + log.error(e) continue except OSError as e: - ialog.error(e) + log.error(e) continue print("Outputs:") @@ -511,7 +511,7 @@ def do_command(command: str, gen, opt: Args, completer) -> tuple: gen.set_model(model_name) add_embedding_terms(gen, completer) except KeyError as e: - ialog.error(e) + log.error(e) except Exception as e: report_model_error(opt, e) completer.add_history(command) @@ -525,7 +525,7 @@ def do_command(command: str, gen, opt: Args, completer) -> tuple: elif command.startswith("!import"): path = shlex.split(command) if len(path) < 2: - ialog.warning( + log.warning( "please provide (1) a URL to a .ckpt file to import; (2) a local path to a .ckpt file; or (3) a diffusers repository id in the form stabilityai/stable-diffusion-2-1" ) else: @@ -539,7 +539,7 @@ def do_command(command: str, gen, opt: Args, completer) -> tuple: elif command.startswith(("!convert", "!optimize")): path = shlex.split(command) if len(path) < 2: - ialog.warning("please provide the path to a .ckpt or .safetensors model") + log.warning("please provide the path to a .ckpt or .safetensors model") else: try: convert_model(path[1], gen, opt, completer) @@ -551,7 +551,7 @@ def do_command(command: str, gen, opt: Args, completer) -> tuple: elif command.startswith("!edit"): path = shlex.split(command) if len(path) < 2: - ialog.warning("please provide the name of a model") + log.warning("please provide the name of a model") else: edit_model(path[1], gen, opt, completer) completer.add_history(command) @@ -560,7 +560,7 @@ def do_command(command: str, gen, opt: Args, completer) -> tuple: elif command.startswith("!del"): path = shlex.split(command) if len(path) < 2: - ialog.warning("please provide the name of a model") + log.warning("please provide the name of a model") else: del_config(path[1], gen, opt, completer) completer.add_history(command) @@ -641,7 +641,7 @@ def import_model(model_path: str, gen, opt, completer): default_name = url_attachment_name(model_path) default_name = Path(default_name).stem except Exception: - ialog.warning(f"A problem occurred while assigning the name of the downloaded model",exc_info=True) + log.warning(f"A problem occurred while assigning the name of the downloaded model",exc_info=True) model_name, model_desc = _get_model_name_and_desc( gen.model_manager, completer, @@ -662,11 +662,11 @@ def import_model(model_path: str, gen, opt, completer): model_config_file=config_file, ) if not imported_name: - ialog.error("Aborting import.") + log.error("Aborting import.") return if not _verify_load(imported_name, gen): - ialog.error("model failed to load. Discarding configuration entry") + log.error("model failed to load. Discarding configuration entry") gen.model_manager.del_model(imported_name) return if click.confirm("Make this the default model?", default=False): @@ -674,7 +674,7 @@ def import_model(model_path: str, gen, opt, completer): gen.model_manager.commit(opt.conf) completer.update_models(gen.model_manager.list_models()) - ialog.info(f"{imported_name} successfully installed") + log.info(f"{imported_name} successfully installed") def _pick_configuration_file(completer)->Path: print( @@ -718,21 +718,21 @@ Please select the type of this model: return choice def _verify_load(model_name: str, gen) -> bool: - ialog.info("Verifying that new model loads...") + log.info("Verifying that new model loads...") current_model = gen.model_name try: if not gen.set_model(model_name): return except Exception as e: - ialog.warning(f"model failed to load: {str(e)}") - ialog.warning( + log.warning(f"model failed to load: {str(e)}") + log.warning( "** note that importing 2.X checkpoints is not supported. Please use !convert_model instead." ) return False if click.confirm("Keep model loaded?", default=True): gen.set_model(model_name) else: - ialog.info("Restoring previous model") + log.info("Restoring previous model") gen.set_model(current_model) return True @@ -755,7 +755,7 @@ def convert_model(model_name_or_path: Union[Path, str], gen, opt, completer): ckpt_path = None original_config_file = None if model_name_or_path == gen.model_name: - ialog.warning("Can't convert the active model. !switch to another model first. **") + log.warning("Can't convert the active model. !switch to another model first. **") return elif model_info := manager.model_info(model_name_or_path): if "weights" in model_info: @@ -765,7 +765,7 @@ def convert_model(model_name_or_path: Union[Path, str], gen, opt, completer): model_description = model_info["description"] vae_path = model_info.get("vae") else: - ialog.warning(f"{model_name_or_path} is not a legacy .ckpt weights file") + log.warning(f"{model_name_or_path} is not a legacy .ckpt weights file") return model_name = manager.convert_and_import( ckpt_path, @@ -786,16 +786,16 @@ def convert_model(model_name_or_path: Union[Path, str], gen, opt, completer): manager.commit(opt.conf) if click.confirm(f"Delete the original .ckpt file at {ckpt_path}?", default=False): ckpt_path.unlink(missing_ok=True) - ialog.warning(f"{ckpt_path} deleted") + log.warning(f"{ckpt_path} deleted") def del_config(model_name: str, gen, opt, completer): current_model = gen.model_name if model_name == current_model: - ialog.warning("Can't delete active model. !switch to another model first. **") + log.warning("Can't delete active model. !switch to another model first. **") return if model_name not in gen.model_manager.config: - ialog.warning(f"Unknown model {model_name}") + log.warning(f"Unknown model {model_name}") return if not click.confirm( @@ -808,17 +808,17 @@ def del_config(model_name: str, gen, opt, completer): ) gen.model_manager.del_model(model_name, delete_files=delete_completely) gen.model_manager.commit(opt.conf) - ialog.warning(f"{model_name} deleted") + log.warning(f"{model_name} deleted") completer.update_models(gen.model_manager.list_models()) def edit_model(model_name: str, gen, opt, completer): manager = gen.model_manager if not (info := manager.model_info(model_name)): - ialog.warning(f"** Unknown model {model_name}") + log.warning(f"** Unknown model {model_name}") return print() - ialog.info(f"Editing model {model_name} from configuration file {opt.conf}") + log.info(f"Editing model {model_name} from configuration file {opt.conf}") new_name = _get_model_name(manager.list_models(), completer, model_name) for attribute in info.keys(): @@ -856,7 +856,7 @@ def edit_model(model_name: str, gen, opt, completer): manager.set_default_model(new_name) manager.commit(opt.conf) completer.update_models(manager.list_models()) - ialog.info("Model successfully updated") + log.info("Model successfully updated") def _get_model_name(existing_names, completer, default_name: str = "") -> str: @@ -867,11 +867,11 @@ def _get_model_name(existing_names, completer, default_name: str = "") -> str: if len(model_name) == 0: model_name = default_name if not re.match("^[\w._+:/-]+$", model_name): - ialog.warning( + log.warning( 'model name must contain only words, digits and the characters "._+:/-" **' ) elif model_name != default_name and model_name in existing_names: - ialog.warning(f"the name {model_name} is already in use. Pick another.") + log.warning(f"the name {model_name} is already in use. Pick another.") else: done = True return model_name @@ -938,10 +938,10 @@ def do_postprocess(gen, opt, callback): opt=opt, ) except OSError: - ialog.error(f"{file_path}: file could not be read",exc_info=True) + log.error(f"{file_path}: file could not be read",exc_info=True) return except (KeyError, AttributeError): - ialog.error(f"an error occurred while applying the {tool} postprocessor",exc_info=True) + log.error(f"an error occurred while applying the {tool} postprocessor",exc_info=True) return return opt.last_operation @@ -996,12 +996,12 @@ def prepare_image_metadata( try: filename = opt.fnformat.format(**wildcards) except KeyError as e: - ialog.error( + log.error( f"The filename format contains an unknown key '{e.args[0]}'. Will use {{prefix}}.{{seed}}.png' instead" ) filename = f"{prefix}.{seed}.png" except IndexError: - ialog.error( + log.error( "The filename format is broken or complete. Will use '{prefix}.{seed}.png' instead" ) filename = f"{prefix}.{seed}.png" @@ -1091,14 +1091,14 @@ def split_variations(variations_string) -> list: for part in variations_string.split(","): seed_and_weight = part.split(":") if len(seed_and_weight) != 2: - ialog.warning(f'Could not parse with_variation part "{part}"') + log.warning(f'Could not parse with_variation part "{part}"') broken = True break try: seed = int(seed_and_weight[0]) weight = float(seed_and_weight[1]) except ValueError: - ialog.warning(f'Could not parse with_variation part "{part}"') + log.warning(f'Could not parse with_variation part "{part}"') broken = True break parts.append([seed, weight]) @@ -1122,23 +1122,23 @@ def load_face_restoration(opt): opt.gfpgan_model_path ) else: - ialog.info("Face restoration disabled") + log.info("Face restoration disabled") if opt.esrgan: esrgan = restoration.load_esrgan(opt.esrgan_bg_tile) else: - ialog.info("Upscaling disabled") + log.info("Upscaling disabled") else: - ialog.info("Face restoration and upscaling disabled") + log.info("Face restoration and upscaling disabled") except (ModuleNotFoundError, ImportError): print(traceback.format_exc(), file=sys.stderr) - ialog.info("You may need to install the ESRGAN and/or GFPGAN modules") + log.info("You may need to install the ESRGAN and/or GFPGAN modules") return gfpgan, codeformer, esrgan def make_step_callback(gen, opt, prefix): destination = os.path.join(opt.outdir, "intermediates", prefix) os.makedirs(destination, exist_ok=True) - ialog.info(f"Intermediate images will be written into {destination}") + log.info(f"Intermediate images will be written into {destination}") def callback(state: PipelineIntermediateState): latents = state.latents @@ -1180,11 +1180,11 @@ def retrieve_dream_command(opt, command, completer): try: cmd = dream_cmd_from_png(path) except OSError: - ialog.error(f"{tokens[0]}: file could not be read") + log.error(f"{tokens[0]}: file could not be read") except (KeyError, AttributeError, IndexError): - ialog.error(f"{tokens[0]}: file has no metadata") + log.error(f"{tokens[0]}: file has no metadata") except: - ialog.error(f"{tokens[0]}: file could not be processed") + log.error(f"{tokens[0]}: file could not be processed") if len(cmd) > 0: completer.set_line(cmd) @@ -1193,7 +1193,7 @@ def write_commands(opt, file_path: str, outfilepath: str): try: paths = sorted(list(Path(dir).glob(basename))) except ValueError: - ialog.error(f'"{basename}": unacceptable pattern') + log.error(f'"{basename}": unacceptable pattern') return commands = [] @@ -1202,9 +1202,9 @@ def write_commands(opt, file_path: str, outfilepath: str): try: cmd = dream_cmd_from_png(path) except (KeyError, AttributeError, IndexError): - ialog.error(f"{path}: file has no metadata") + log.error(f"{path}: file has no metadata") except: - ialog.error(f"{path}: file could not be processed") + log.error(f"{path}: file could not be processed") if cmd: commands.append(f"# {path}") commands.append(cmd) @@ -1214,17 +1214,17 @@ def write_commands(opt, file_path: str, outfilepath: str): outfilepath = os.path.join(opt.outdir, basename) with open(outfilepath, "w", encoding="utf-8") as f: f.write("\n".join(commands)) - ialog.info(f"File {outfilepath} with commands created") + log.info(f"File {outfilepath} with commands created") def report_model_error(opt: Namespace, e: Exception): - ialog.warning(f'An error occurred while attempting to initialize the model: "{str(e)}"') - ialog.warning( + log.warning(f'An error occurred while attempting to initialize the model: "{str(e)}"') + log.warning( "This can be caused by a missing or corrupted models file, and can sometimes be fixed by (re)installing the models." ) yes_to_all = os.environ.get("INVOKE_MODEL_RECONFIGURE") if yes_to_all: - ialog.warning( + log.warning( "Reconfiguration is being forced by environment variable INVOKE_MODEL_RECONFIGURE" ) else: @@ -1234,7 +1234,7 @@ def report_model_error(opt: Namespace, e: Exception): ): return - ialog.info("invokeai-configure is launching....\n") + log.info("invokeai-configure is launching....\n") # Match arguments that were set on the CLI # only the arguments accepted by the configuration script are parsed @@ -1251,7 +1251,7 @@ def report_model_error(opt: Namespace, e: Exception): from ..install import invokeai_configure invokeai_configure() - ialog.warning("InvokeAI will now restart") + log.warning("InvokeAI will now restart") sys.argv = previous_args main() # would rather do a os.exec(), but doesn't exist? sys.exit(0) From 0b0e6fe44825aeae86ae834961461c10a89de3ad Mon Sep 17 00:00:00 2001 From: Lincoln Stein Date: Fri, 14 Apr 2023 15:15:14 -0400 Subject: [PATCH 06/68] convert remainder of print() to log.info() --- invokeai/backend/args.py | 18 +-- invokeai/backend/generate.py | 129 +++++++++--------- invokeai/backend/generator/base.py | 5 +- invokeai/backend/generator/embiggen.py | 37 ++--- invokeai/backend/generator/txt2img2img.py | 6 +- invokeai/backend/image_util/patchmatch.py | 9 +- invokeai/backend/image_util/txt2mask.py | 16 +-- .../convert_ckpt_to_diffusers.py | 17 +-- invokeai/backend/prompting/conditioning.py | 17 +-- invokeai/backend/restoration/base.py | 12 +- invokeai/backend/restoration/codeformer.py | 7 +- invokeai/backend/restoration/gfpgan.py | 14 +- invokeai/backend/restoration/outcrop.py | 4 +- invokeai/backend/restoration/realesrgan.py | 15 +- invokeai/backend/safety_checker.py | 9 +- .../backend/stable_diffusion/concepts_lib.py | 23 ++-- .../diffusion/cross_attention_control.py | 10 +- .../diffusion/shared_invokeai_diffusion.py | 24 ++-- .../image_degradation/utils_image.py | 4 +- .../textual_inversion_manager.py | 59 ++++---- invokeai/backend/util/util.py | 31 +++-- invokeai/backend/web/invoke_ai_web_server.py | 55 ++++---- 22 files changed, 262 insertions(+), 259 deletions(-) diff --git a/invokeai/backend/args.py b/invokeai/backend/args.py index b6c2608b20..4a1aea094c 100644 --- a/invokeai/backend/args.py +++ b/invokeai/backend/args.py @@ -96,6 +96,7 @@ from pathlib import Path from typing import List import invokeai.version +import invokeai.backend.util.logging as log from invokeai.backend.image_util import retrieve_metadata from .globals import Globals @@ -189,7 +190,7 @@ class Args(object): print(f"{APP_NAME} {APP_VERSION}") sys.exit(0) - print("* Initializing, be patient...") + log.info("Initializing, be patient...") Globals.root = Path(os.path.abspath(switches.root_dir or Globals.root)) Globals.try_patchmatch = switches.patchmatch @@ -197,14 +198,13 @@ class Args(object): initfile = os.path.expanduser(os.path.join(Globals.root, Globals.initfile)) legacyinit = os.path.expanduser("~/.invokeai") if os.path.exists(initfile): - print( - f">> Initialization file {initfile} found. Loading...", - file=sys.stderr, + log.info( + f"Initialization file {initfile} found. Loading...", ) sysargs.insert(0, f"@{initfile}") elif os.path.exists(legacyinit): - print( - f">> WARNING: Old initialization file found at {legacyinit}. This location is deprecated. Please move it to {Globals.root}/invokeai.init." + log.warning( + f"Old initialization file found at {legacyinit}. This location is deprecated. Please move it to {Globals.root}/invokeai.init." ) sysargs.insert(0, f"@{legacyinit}") Globals.log_tokenization = self._arg_parser.parse_args( @@ -214,7 +214,7 @@ class Args(object): self._arg_switches = self._arg_parser.parse_args(sysargs) return self._arg_switches except Exception as e: - print(f"An exception has occurred: {e}") + log.error(f"An exception has occurred: {e}") return None def parse_cmd(self, cmd_string): @@ -1154,7 +1154,7 @@ class Args(object): def format_metadata(**kwargs): - print("format_metadata() is deprecated. Please use metadata_dumps()") + log.warning("format_metadata() is deprecated. Please use metadata_dumps()") return metadata_dumps(kwargs) @@ -1326,7 +1326,7 @@ def metadata_loads(metadata) -> list: import sys import traceback - print(">> could not read metadata", file=sys.stderr) + log.error("Could not read metadata") print(traceback.format_exc(), file=sys.stderr) return results diff --git a/invokeai/backend/generate.py b/invokeai/backend/generate.py index 1b19a1aa7e..361efe99b4 100644 --- a/invokeai/backend/generate.py +++ b/invokeai/backend/generate.py @@ -27,6 +27,7 @@ from diffusers.utils.import_utils import is_xformers_available from omegaconf import OmegaConf from pathlib import Path +import invokeai.backend.util.logging as log from .args import metadata_from_png from .generator import infill_methods from .globals import Globals, global_cache_dir @@ -195,12 +196,12 @@ class Generate: # device to Generate(). However the device was then ignored, so # it wasn't actually doing anything. This logic could be reinstated. self.device = torch.device(choose_torch_device()) - print(f">> Using device_type {self.device.type}") + log.info(f"Using device_type {self.device.type}") if full_precision: if self.precision != "auto": raise ValueError("Remove --full_precision / -F if using --precision") - print("Please remove deprecated --full_precision / -F") - print("If auto config does not work you can use --precision=float32") + log.warning("Please remove deprecated --full_precision / -F") + log.warning("If auto config does not work you can use --precision=float32") self.precision = "float32" if self.precision == "auto": self.precision = choose_precision(self.device) @@ -208,13 +209,13 @@ class Generate: if is_xformers_available(): if torch.cuda.is_available() and not Globals.disable_xformers: - print(">> xformers memory-efficient attention is available and enabled") + log.info("xformers memory-efficient attention is available and enabled") else: - print( - ">> xformers memory-efficient attention is available but disabled" + log.info( + "xformers memory-efficient attention is available but disabled" ) else: - print(">> xformers not installed") + log.info("xformers not installed") # model caching system for fast switching self.model_manager = ModelManager( @@ -229,8 +230,8 @@ class Generate: fallback = self.model_manager.default_model() or FALLBACK_MODEL_NAME model = model or fallback if not self.model_manager.valid_model(model): - print( - f'** "{model}" is not a known model name; falling back to {fallback}.' + log.warning( + f'"{model}" is not a known model name; falling back to {fallback}.' ) model = None self.model_name = model or fallback @@ -246,10 +247,10 @@ class Generate: # load safety checker if requested if safety_checker: - print(">> Initializing NSFW checker") + log.info("Initializing NSFW checker") self.safety_checker = SafetyChecker(self.device) else: - print(">> NSFW checker is disabled") + log.info("NSFW checker is disabled") def prompt2png(self, prompt, outdir, **kwargs): """ @@ -567,7 +568,7 @@ class Generate: self.clear_cuda_cache() if catch_interrupts: - print("**Interrupted** Partial results will be returned.") + log.warning("Interrupted** Partial results will be returned.") else: raise KeyboardInterrupt except RuntimeError: @@ -575,11 +576,11 @@ class Generate: self.clear_cuda_cache() print(traceback.format_exc(), file=sys.stderr) - print(">> Could not generate image.") + log.info("Could not generate image.") toc = time.time() - print("\n>> Usage stats:") - print(f">> {len(results)} image(s) generated in", "%4.2fs" % (toc - tic)) + log.info("Usage stats:") + log.info(f"{len(results)} image(s) generated in "+"%4.2fs" % (toc - tic)) self.print_cuda_stats() return results @@ -609,16 +610,16 @@ class Generate: def print_cuda_stats(self): if self._has_cuda(): self.gather_cuda_stats() - print( - ">> Max VRAM used for this generation:", - "%4.2fG." % (self.max_memory_allocated / 1e9), - "Current VRAM utilization:", - "%4.2fG" % (self.memory_allocated / 1e9), + log.info( + "Max VRAM used for this generation: "+ + "%4.2fG. " % (self.max_memory_allocated / 1e9)+ + "Current VRAM utilization: "+ + "%4.2fG" % (self.memory_allocated / 1e9) ) - print( - ">> Max VRAM used since script start: ", - "%4.2fG" % (self.session_peakmem / 1e9), + log.info( + "Max VRAM used since script start: " + + "%4.2fG" % (self.session_peakmem / 1e9) ) # this needs to be generalized to all sorts of postprocessors, which should be wrapped @@ -647,7 +648,7 @@ class Generate: seed = random.randrange(0, np.iinfo(np.uint32).max) prompt = opt.prompt or args.prompt or "" - print(f'>> using seed {seed} and prompt "{prompt}" for {image_path}') + log.info(f'using seed {seed} and prompt "{prompt}" for {image_path}') # try to reuse the same filename prefix as the original file. # we take everything up to the first period @@ -696,8 +697,8 @@ class Generate: try: extend_instructions[direction] = int(pixels) except ValueError: - print( - '** invalid extension instruction. Use ..., as in "top 64 left 128 right 64 bottom 64"' + log.warning( + 'invalid extension instruction. Use ..., as in "top 64 left 128 right 64 bottom 64"' ) opt.seed = seed @@ -720,8 +721,8 @@ class Generate: # fetch the metadata from the image generator = self.select_generator(embiggen=True) opt.strength = opt.embiggen_strength or 0.40 - print( - f">> Setting img2img strength to {opt.strength} for happy embiggening" + log.info( + f"Setting img2img strength to {opt.strength} for happy embiggening" ) generator.generate( prompt, @@ -748,12 +749,12 @@ class Generate: return restorer.process(opt, args, image_callback=callback, prefix=prefix) elif tool is None: - print( - "* please provide at least one postprocessing option, such as -G or -U" + log.warning( + "please provide at least one postprocessing option, such as -G or -U" ) return None else: - print(f"* postprocessing tool {tool} is not yet supported") + log.warning(f"postprocessing tool {tool} is not yet supported") return None def select_generator( @@ -797,8 +798,8 @@ class Generate: image = self._load_img(img) if image.width < self.width and image.height < self.height: - print( - f">> WARNING: img2img and inpainting may produce unexpected results with initial images smaller than {self.width}x{self.height} in both dimensions" + log.warning( + f"img2img and inpainting may produce unexpected results with initial images smaller than {self.width}x{self.height} in both dimensions" ) # if image has a transparent area and no mask was provided, then try to generate mask @@ -809,8 +810,8 @@ class Generate: if (image.width * image.height) > ( self.width * self.height ) and self.size_matters: - print( - ">> This input is larger than your defaults. If you run out of memory, please use a smaller image." + log.info( + "This input is larger than your defaults. If you run out of memory, please use a smaller image." ) self.size_matters = False @@ -891,11 +892,11 @@ class Generate: try: model_data = cache.get_model(model_name) except Exception as e: - print(f"** model {model_name} could not be loaded: {str(e)}") + log.warning(f"model {model_name} could not be loaded: {str(e)}") print(traceback.format_exc(), file=sys.stderr) if previous_model_name is None: raise e - print("** trying to reload previous model") + log.warning("trying to reload previous model") model_data = cache.get_model(previous_model_name) # load previous if model_data is None: raise e @@ -962,15 +963,15 @@ class Generate: if self.gfpgan is not None or self.codeformer is not None: if facetool == "gfpgan": if self.gfpgan is None: - print( - ">> GFPGAN not found. Face restoration is disabled." + log.info( + "GFPGAN not found. Face restoration is disabled." ) else: image = self.gfpgan.process(image, strength, seed) if facetool == "codeformer": if self.codeformer is None: - print( - ">> CodeFormer not found. Face restoration is disabled." + log.info( + "CodeFormer not found. Face restoration is disabled." ) else: cf_device = ( @@ -984,7 +985,7 @@ class Generate: fidelity=codeformer_fidelity, ) else: - print(">> Face Restoration is disabled.") + log.info("Face Restoration is disabled.") if upscale is not None: if self.esrgan is not None: if len(upscale) < 2: @@ -997,10 +998,10 @@ class Generate: denoise_str=upscale_denoise_str, ) else: - print(">> ESRGAN is disabled. Image not upscaled.") + log.info("ESRGAN is disabled. Image not upscaled.") except Exception as e: - print( - f">> Error running RealESRGAN or GFPGAN. Your image was not upscaled.\n{e}" + log.info( + f"Error running RealESRGAN or GFPGAN. Your image was not upscaled.\n{e}" ) if image_callback is not None: @@ -1066,17 +1067,17 @@ class Generate: if self.sampler_name in scheduler_map: sampler_class = scheduler_map[self.sampler_name] msg = ( - f">> Setting Sampler to {self.sampler_name} ({sampler_class.__name__})" + f"Setting Sampler to {self.sampler_name} ({sampler_class.__name__})" ) self.sampler = sampler_class.from_config(self.model.scheduler.config) else: msg = ( - f">> Unsupported Sampler: {self.sampler_name} " + f" Unsupported Sampler: {self.sampler_name} "+ f"Defaulting to {default}" ) self.sampler = default - print(msg) + log.info(msg) if not hasattr(self.sampler, "uses_inpainting_model"): # FIXME: terrible kludge! @@ -1085,17 +1086,17 @@ class Generate: def _load_img(self, img) -> Image: if isinstance(img, Image.Image): image = img - print(f">> using provided input image of size {image.width}x{image.height}") + log.info(f"using provided input image of size {image.width}x{image.height}") elif isinstance(img, str): assert os.path.exists(img), f">> {img}: File not found" image = Image.open(img) - print( - f">> loaded input image of size {image.width}x{image.height} from {img}" + log.info( + f"loaded input image of size {image.width}x{image.height} from {img}" ) else: image = Image.open(img) - print(f">> loaded input image of size {image.width}x{image.height}") + log.info(f"loaded input image of size {image.width}x{image.height}") image = ImageOps.exif_transpose(image) return image @@ -1183,14 +1184,14 @@ class Generate: def _transparency_check_and_warning(self, image, mask, force_outpaint=False): if not mask: - print( - ">> Initial image has transparent areas. Will inpaint in these regions." + log.info( + "Initial image has transparent areas. Will inpaint in these regions." ) - if (not force_outpaint) and self._check_for_erasure(image): - print( - ">> WARNING: Colors underneath the transparent region seem to have been erased.\n", - ">> Inpainting will be suboptimal. Please preserve the colors when making\n", - ">> a transparency mask, or provide mask explicitly using --init_mask (-M).", + if (not force_outpaint) and self._check_for_erasure(image): + log.info( + "Colors underneath the transparent region seem to have been erased.\n" + + "Inpainting will be suboptimal. Please preserve the colors when making\n" + + "a transparency mask, or provide mask explicitly using --init_mask (-M)." ) def _squeeze_image(self, image): @@ -1201,11 +1202,11 @@ class Generate: def _fit_image(self, image, max_dimensions): w, h = max_dimensions - print(f">> image will be resized to fit inside a box {w}x{h} in size.") + log.info(f"image will be resized to fit inside a box {w}x{h} in size.") # note that InitImageResizer does the multiple of 64 truncation internally image = InitImageResizer(image).resize(width=w, height=h) - print( - f">> after adjusting image dimensions to be multiples of 64, init image is {image.width}x{image.height}" + log.info( + f"after adjusting image dimensions to be multiples of 64, init image is {image.width}x{image.height}" ) return image @@ -1216,8 +1217,8 @@ class Generate: ) # resize to integer multiple of 64 if h != height or w != width: if log: - print( - f">> Provided width and height must be multiples of 64. Auto-resizing to {w}x{h}" + log.info( + f"Provided width and height must be multiples of 64. Auto-resizing to {w}x{h}" ) height = h width = w diff --git a/invokeai/backend/generator/base.py b/invokeai/backend/generator/base.py index ee56077fa8..00ee61af2d 100644 --- a/invokeai/backend/generator/base.py +++ b/invokeai/backend/generator/base.py @@ -25,6 +25,7 @@ from typing import Callable, List, Iterator, Optional, Type from dataclasses import dataclass, field from diffusers.schedulers import SchedulerMixin as Scheduler +import invokeai.backend.util.logging as log from ..image_util import configure_model_padding from ..util.util import rand_perlin_2d from ..safety_checker import SafetyChecker @@ -372,7 +373,7 @@ class Generator: try: x_T = self.get_noise(width, height) except: - print("** An error occurred while getting initial noise **") + log.error("An error occurred while getting initial noise") print(traceback.format_exc()) # Pass on the seed in case a layer beneath us needs to generate noise on its own. @@ -607,7 +608,7 @@ class Generator: image = self.sample_to_image(sample) dirname = os.path.dirname(filepath) or "." if not os.path.exists(dirname): - print(f"** creating directory {dirname}") + log.info(f"creating directory {dirname}") os.makedirs(dirname, exist_ok=True) image.save(filepath, "PNG") diff --git a/invokeai/backend/generator/embiggen.py b/invokeai/backend/generator/embiggen.py index ce9ef4d1b6..4ac72016b9 100644 --- a/invokeai/backend/generator/embiggen.py +++ b/invokeai/backend/generator/embiggen.py @@ -8,10 +8,11 @@ import torch from PIL import Image from tqdm import trange +import invokeai.backend.util.logging as log + from .base import Generator from .img2img import Img2Img - class Embiggen(Generator): def __init__(self, model, precision): super().__init__(model, precision) @@ -72,22 +73,22 @@ class Embiggen(Generator): embiggen = [1.0] # If not specified, assume no scaling elif embiggen[0] < 0: embiggen[0] = 1.0 - print( - ">> Embiggen scaling factor cannot be negative, fell back to the default of 1.0 !" + log.warning( + "Embiggen scaling factor cannot be negative, fell back to the default of 1.0 !" ) if len(embiggen) < 2: embiggen.append(0.75) elif embiggen[1] > 1.0 or embiggen[1] < 0: embiggen[1] = 0.75 - print( - ">> Embiggen upscaling strength for ESRGAN must be between 0 and 1, fell back to the default of 0.75 !" + log.warning( + "Embiggen upscaling strength for ESRGAN must be between 0 and 1, fell back to the default of 0.75 !" ) if len(embiggen) < 3: embiggen.append(0.25) elif embiggen[2] < 0: embiggen[2] = 0.25 - print( - ">> Overlap size for Embiggen must be a positive ratio between 0 and 1 OR a number of pixels, fell back to the default of 0.25 !" + log.warning( + "Overlap size for Embiggen must be a positive ratio between 0 and 1 OR a number of pixels, fell back to the default of 0.25 !" ) # Convert tiles from their user-freindly count-from-one to count-from-zero, because we need to do modulo math @@ -97,8 +98,8 @@ class Embiggen(Generator): embiggen_tiles.sort() if strength >= 0.5: - print( - f"* WARNING: Embiggen may produce mirror motifs if the strength (-f) is too high (currently {strength}). Try values between 0.35-0.45." + log.warning( + f"Embiggen may produce mirror motifs if the strength (-f) is too high (currently {strength}). Try values between 0.35-0.45." ) # Prep img2img generator, since we wrap over it @@ -121,8 +122,8 @@ class Embiggen(Generator): from ..restoration.realesrgan import ESRGAN esrgan = ESRGAN() - print( - f">> ESRGAN upscaling init image prior to cutting with Embiggen with strength {embiggen[1]}" + log.info( + f"ESRGAN upscaling init image prior to cutting with Embiggen with strength {embiggen[1]}" ) if embiggen[0] > 2: initsuperimage = esrgan.process( @@ -312,10 +313,10 @@ class Embiggen(Generator): def make_image(): # Make main tiles ------------------------------------------------- if embiggen_tiles: - print(f">> Making {len(embiggen_tiles)} Embiggen tiles...") + log.info(f"Making {len(embiggen_tiles)} Embiggen tiles...") else: - print( - f">> Making {(emb_tiles_x * emb_tiles_y)} Embiggen tiles ({emb_tiles_x}x{emb_tiles_y})..." + log.info( + f"Making {(emb_tiles_x * emb_tiles_y)} Embiggen tiles ({emb_tiles_x}x{emb_tiles_y})..." ) emb_tile_store = [] @@ -361,11 +362,11 @@ class Embiggen(Generator): # newinitimage.save(newinitimagepath) if embiggen_tiles: - print( + log.debug( f"Making tile #{tile + 1} ({embiggen_tiles.index(tile) + 1} of {len(embiggen_tiles)} requested)" ) else: - print(f"Starting {tile + 1} of {(emb_tiles_x * emb_tiles_y)} tiles") + log.debug(f"Starting {tile + 1} of {(emb_tiles_x * emb_tiles_y)} tiles") # create a torch tensor from an Image newinitimage = np.array(newinitimage).astype(np.float32) / 255.0 @@ -547,8 +548,8 @@ class Embiggen(Generator): # Layer tile onto final image outputsuperimage.alpha_composite(intileimage, (left, top)) else: - print( - "Error: could not find all Embiggen output tiles in memory? Something must have gone wrong with img2img generation." + log.error( + "Could not find all Embiggen output tiles in memory? Something must have gone wrong with img2img generation." ) # after internal loops and patching up return Embiggen image diff --git a/invokeai/backend/generator/txt2img2img.py b/invokeai/backend/generator/txt2img2img.py index 1e24a8b729..2dfd2c79e9 100644 --- a/invokeai/backend/generator/txt2img2img.py +++ b/invokeai/backend/generator/txt2img2img.py @@ -14,6 +14,8 @@ from ..stable_diffusion.diffusers_pipeline import StableDiffusionGeneratorPipeli from ..stable_diffusion.diffusers_pipeline import ConditioningData from ..stable_diffusion.diffusers_pipeline import trim_to_multiple_of +import invokeai.backend.util.logging as log + class Txt2Img2Img(Generator): def __init__(self, model, precision): super().__init__(model, precision) @@ -77,8 +79,8 @@ class Txt2Img2Img(Generator): # the message below is accurate. init_width = first_pass_latent_output.size()[3] * self.downsampling_factor init_height = first_pass_latent_output.size()[2] * self.downsampling_factor - print( - f"\n>> Interpolating from {init_width}x{init_height} to {width}x{height} using DDIM sampling" + log.info( + f"Interpolating from {init_width}x{init_height} to {width}x{height} using DDIM sampling" ) # resizing diff --git a/invokeai/backend/image_util/patchmatch.py b/invokeai/backend/image_util/patchmatch.py index 8753298f51..3989786c58 100644 --- a/invokeai/backend/image_util/patchmatch.py +++ b/invokeai/backend/image_util/patchmatch.py @@ -5,10 +5,9 @@ wraps the actual patchmatch object. It respects the global be suppressed or deferred """ import numpy as np - +import invokeai.backend.util.logging as log from invokeai.backend.globals import Globals - class PatchMatch: """ Thin class wrapper around the patchmatch function. @@ -28,12 +27,12 @@ class PatchMatch: from patchmatch import patch_match as pm if pm.patchmatch_available: - print(">> Patchmatch initialized") + log.info("Patchmatch initialized") else: - print(">> Patchmatch not loaded (nonfatal)") + log.info("Patchmatch not loaded (nonfatal)") self.patch_match = pm else: - print(">> Patchmatch loading disabled") + log.info("Patchmatch loading disabled") self.tried_load = True @classmethod diff --git a/invokeai/backend/image_util/txt2mask.py b/invokeai/backend/image_util/txt2mask.py index bc7e56d397..a82e56ffd7 100644 --- a/invokeai/backend/image_util/txt2mask.py +++ b/invokeai/backend/image_util/txt2mask.py @@ -30,9 +30,9 @@ work fine. import numpy as np import torch from PIL import Image, ImageOps -from torchvision import transforms from transformers import AutoProcessor, CLIPSegForImageSegmentation +import invokeai.backend.util.logging as log from invokeai.backend.globals import global_cache_dir CLIPSEG_MODEL = "CIDAS/clipseg-rd64-refined" @@ -83,7 +83,7 @@ class Txt2Mask(object): """ def __init__(self, device="cpu", refined=False): - print(">> Initializing clipseg model for text to mask inference") + log.info("Initializing clipseg model for text to mask inference") # BUG: we are not doing anything with the device option at this time self.device = device @@ -101,18 +101,6 @@ class Txt2Mask(object): provided image and returns a SegmentedGrayscale object in which the brighter pixels indicate where the object is inferred to be. """ - transform = transforms.Compose( - [ - transforms.ToTensor(), - transforms.Normalize( - mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225] - ), - transforms.Resize( - (CLIPSEG_SIZE, CLIPSEG_SIZE) - ), # must be multiple of 64... - ] - ) - if type(image) is str: image = Image.open(image).convert("RGB") diff --git a/invokeai/backend/model_management/convert_ckpt_to_diffusers.py b/invokeai/backend/model_management/convert_ckpt_to_diffusers.py index b46586611d..d08f146d8e 100644 --- a/invokeai/backend/model_management/convert_ckpt_to_diffusers.py +++ b/invokeai/backend/model_management/convert_ckpt_to_diffusers.py @@ -25,6 +25,7 @@ from typing import Union import torch from safetensors.torch import load_file +import invokeai.backend.util.logging as log from invokeai.backend.globals import global_cache_dir, global_config_dir from .model_manager import ModelManager, SDLegacyType @@ -372,9 +373,9 @@ def convert_ldm_unet_checkpoint(checkpoint, config, path=None, extract_ema=False unet_key = "model.diffusion_model." # at least a 100 parameters have to start with `model_ema` in order for the checkpoint to be EMA if sum(k.startswith("model_ema") for k in keys) > 100: - print(f" | Checkpoint {path} has both EMA and non-EMA weights.") + log.debug(f"Checkpoint {path} has both EMA and non-EMA weights.") if extract_ema: - print(" | Extracting EMA weights (usually better for inference)") + log.debug("Extracting EMA weights (usually better for inference)") for key in keys: if key.startswith("model.diffusion_model"): flat_ema_key = "model_ema." + "".join(key.split(".")[1:]) @@ -392,8 +393,8 @@ def convert_ldm_unet_checkpoint(checkpoint, config, path=None, extract_ema=False key ) else: - print( - " | Extracting only the non-EMA weights (usually better for fine-tuning)" + log.debug( + "Extracting only the non-EMA weights (usually better for fine-tuning)" ) for key in keys: @@ -1115,7 +1116,7 @@ def load_pipeline_from_original_stable_diffusion_ckpt( if "global_step" in checkpoint: global_step = checkpoint["global_step"] else: - print(" | global_step key not found in model") + log.debug("global_step key not found in model") global_step = None # sometimes there is a state_dict key and sometimes not @@ -1229,15 +1230,15 @@ def load_pipeline_from_original_stable_diffusion_ckpt( # If a replacement VAE path was specified, we'll incorporate that into # the checkpoint model and then convert it if vae_path: - print(f" | Converting VAE {vae_path}") + log.debug(f"Converting VAE {vae_path}") replace_checkpoint_vae(checkpoint,vae_path) # otherwise we use the original VAE, provided that # an externally loaded diffusers VAE was not passed elif not vae: - print(" | Using checkpoint model's original VAE") + log.debug("Using checkpoint model's original VAE") if vae: - print(" | Using replacement diffusers VAE") + log.debug("Using replacement diffusers VAE") else: # convert the original or replacement VAE vae_config = create_vae_diffusers_config( original_config, image_size=image_size diff --git a/invokeai/backend/prompting/conditioning.py b/invokeai/backend/prompting/conditioning.py index 1ddae1e93d..355cba2a6f 100644 --- a/invokeai/backend/prompting/conditioning.py +++ b/invokeai/backend/prompting/conditioning.py @@ -18,6 +18,7 @@ from compel.prompt_parser import ( PromptParser, ) +import invokeai.backend.util.logging as log from invokeai.backend.globals import Globals from ..stable_diffusion import InvokeAIDiffuserComponent @@ -162,8 +163,8 @@ def log_tokenization( negative_prompt: Union[Blend, FlattenedPrompt], tokenizer, ): - print(f"\n>> [TOKENLOG] Parsed Prompt: {positive_prompt}") - print(f"\n>> [TOKENLOG] Parsed Negative Prompt: {negative_prompt}") + log.info(f"[TOKENLOG] Parsed Prompt: {positive_prompt}") + log.info(f"[TOKENLOG] Parsed Negative Prompt: {negative_prompt}") log_tokenization_for_prompt_object(positive_prompt, tokenizer) log_tokenization_for_prompt_object( @@ -237,12 +238,12 @@ def log_tokenization_for_text(text, tokenizer, display_label=None, truncate_if_t usedTokens += 1 if usedTokens > 0: - print(f'\n>> [TOKENLOG] Tokens {display_label or ""} ({usedTokens}):') - print(f"{tokenized}\x1b[0m") + log.info(f'[TOKENLOG] Tokens {display_label or ""} ({usedTokens}):') + log.debug(f"{tokenized}\x1b[0m") if discarded != "": - print(f"\n>> [TOKENLOG] Tokens Discarded ({totalTokens - usedTokens}):") - print(f"{discarded}\x1b[0m") + log.info(f"[TOKENLOG] Tokens Discarded ({totalTokens - usedTokens}):") + log.debug(f"{discarded}\x1b[0m") def try_parse_legacy_blend(text: str, skip_normalize: bool = False) -> Optional[Blend]: @@ -295,8 +296,8 @@ def split_weighted_subprompts(text, skip_normalize=False) -> list: return parsed_prompts weight_sum = sum(map(lambda x: x[1], parsed_prompts)) if weight_sum == 0: - print( - "* Warning: Subprompt weights add up to zero. Discarding and using even weights instead." + log.warning( + "Subprompt weights add up to zero. Discarding and using even weights instead." ) equal_weight = 1 / max(len(parsed_prompts), 1) return [(x[0], equal_weight) for x in parsed_prompts] diff --git a/invokeai/backend/restoration/base.py b/invokeai/backend/restoration/base.py index 0957811fc3..794d7502da 100644 --- a/invokeai/backend/restoration/base.py +++ b/invokeai/backend/restoration/base.py @@ -1,3 +1,5 @@ +import invokeai.backend.util.logging as log + class Restoration: def __init__(self) -> None: pass @@ -8,17 +10,17 @@ class Restoration: # Load GFPGAN gfpgan = self.load_gfpgan(gfpgan_model_path) if gfpgan.gfpgan_model_exists: - print(">> GFPGAN Initialized") + log.info("GFPGAN Initialized") else: - print(">> GFPGAN Disabled") + log.info("GFPGAN Disabled") gfpgan = None # Load CodeFormer codeformer = self.load_codeformer() if codeformer.codeformer_model_exists: - print(">> CodeFormer Initialized") + log.info("CodeFormer Initialized") else: - print(">> CodeFormer Disabled") + log.info("CodeFormer Disabled") codeformer = None return gfpgan, codeformer @@ -39,5 +41,5 @@ class Restoration: from .realesrgan import ESRGAN esrgan = ESRGAN(esrgan_bg_tile) - print(">> ESRGAN Initialized") + log.info("ESRGAN Initialized") return esrgan diff --git a/invokeai/backend/restoration/codeformer.py b/invokeai/backend/restoration/codeformer.py index 94add72b00..db2a4fb1dd 100644 --- a/invokeai/backend/restoration/codeformer.py +++ b/invokeai/backend/restoration/codeformer.py @@ -5,6 +5,7 @@ import warnings import numpy as np import torch +import invokeai.backend.util.logging as log from ..globals import Globals pretrained_model_url = ( @@ -23,12 +24,12 @@ class CodeFormerRestoration: self.codeformer_model_exists = os.path.isfile(self.model_path) if not self.codeformer_model_exists: - print("## NOT FOUND: CodeFormer model not found at " + self.model_path) + log.error("NOT FOUND: CodeFormer model not found at " + self.model_path) sys.path.append(os.path.abspath(codeformer_dir)) def process(self, image, strength, device, seed=None, fidelity=0.75): if seed is not None: - print(f">> CodeFormer - Restoring Faces for image seed:{seed}") + log.info(f"CodeFormer - Restoring Faces for image seed:{seed}") with warnings.catch_warnings(): warnings.filterwarnings("ignore", category=DeprecationWarning) warnings.filterwarnings("ignore", category=UserWarning) @@ -97,7 +98,7 @@ class CodeFormerRestoration: del output torch.cuda.empty_cache() except RuntimeError as error: - print(f"\tFailed inference for CodeFormer: {error}.") + log.error(f"Failed inference for CodeFormer: {error}.") restored_face = cropped_face restored_face = restored_face.astype("uint8") diff --git a/invokeai/backend/restoration/gfpgan.py b/invokeai/backend/restoration/gfpgan.py index d13745d0c6..adcab2424c 100644 --- a/invokeai/backend/restoration/gfpgan.py +++ b/invokeai/backend/restoration/gfpgan.py @@ -6,9 +6,9 @@ import numpy as np import torch from PIL import Image +import invokeai.backend.util.logging as log from invokeai.backend.globals import Globals - class GFPGAN: def __init__(self, gfpgan_model_path="models/gfpgan/GFPGANv1.4.pth") -> None: if not os.path.isabs(gfpgan_model_path): @@ -19,7 +19,7 @@ class GFPGAN: self.gfpgan_model_exists = os.path.isfile(self.model_path) if not self.gfpgan_model_exists: - print("## NOT FOUND: GFPGAN model not found at " + self.model_path) + log.error("NOT FOUND: GFPGAN model not found at " + self.model_path) return None def model_exists(self): @@ -27,7 +27,7 @@ class GFPGAN: def process(self, image, strength: float, seed: str = None): if seed is not None: - print(f">> GFPGAN - Restoring Faces for image seed:{seed}") + log.info(f"GFPGAN - Restoring Faces for image seed:{seed}") with warnings.catch_warnings(): warnings.filterwarnings("ignore", category=DeprecationWarning) @@ -47,14 +47,14 @@ class GFPGAN: except Exception: import traceback - print(">> Error loading GFPGAN:", file=sys.stderr) + log.error("Error loading GFPGAN:", file=sys.stderr) print(traceback.format_exc(), file=sys.stderr) os.chdir(cwd) if self.gfpgan is None: - print(f">> WARNING: GFPGAN not initialized.") - print( - f">> Download https://github.com/TencentARC/GFPGAN/releases/download/v1.3.0/GFPGANv1.4.pth to {self.model_path}" + log.warning("WARNING: GFPGAN not initialized.") + log.warning( + f"Download https://github.com/TencentARC/GFPGAN/releases/download/v1.3.0/GFPGANv1.4.pth to {self.model_path}" ) image = image.convert("RGB") diff --git a/invokeai/backend/restoration/outcrop.py b/invokeai/backend/restoration/outcrop.py index e0f110f71e..bc508b01ea 100644 --- a/invokeai/backend/restoration/outcrop.py +++ b/invokeai/backend/restoration/outcrop.py @@ -1,7 +1,7 @@ import math from PIL import Image - +import invokeai.backend.util.logging as log class Outcrop(object): def __init__( @@ -82,7 +82,7 @@ class Outcrop(object): pixels = extents[direction] # round pixels up to the nearest 64 pixels = math.ceil(pixels / 64) * 64 - print(f">> extending image {direction}ward by {pixels} pixels") + log.info(f"extending image {direction}ward by {pixels} pixels") image = self._rotate(image, direction) image = self._extend(image, pixels) image = self._rotate(image, direction, reverse=True) diff --git a/invokeai/backend/restoration/realesrgan.py b/invokeai/backend/restoration/realesrgan.py index ad6ad556f1..15afb1f92f 100644 --- a/invokeai/backend/restoration/realesrgan.py +++ b/invokeai/backend/restoration/realesrgan.py @@ -6,18 +6,13 @@ import torch from PIL import Image from PIL.Image import Image as ImageType +import invokeai.backend.util.logging as log from invokeai.backend.globals import Globals - class ESRGAN: def __init__(self, bg_tile_size=400) -> None: self.bg_tile_size = bg_tile_size - if not torch.cuda.is_available(): # CPU or MPS on M1 - use_half_precision = False - else: - use_half_precision = True - def load_esrgan_bg_upsampler(self, denoise_str): if not torch.cuda.is_available(): # CPU or MPS on M1 use_half_precision = False @@ -74,16 +69,16 @@ class ESRGAN: import sys import traceback - print(">> Error loading Real-ESRGAN:", file=sys.stderr) + log.error("Error loading Real-ESRGAN:") print(traceback.format_exc(), file=sys.stderr) if upsampler_scale == 0: - print(">> Real-ESRGAN: Invalid scaling option. Image not upscaled.") + log.warning("Real-ESRGAN: Invalid scaling option. Image not upscaled.") return image if seed is not None: - print( - f">> Real-ESRGAN Upscaling seed:{seed}, scale:{upsampler_scale}x, tile:{self.bg_tile_size}, denoise:{denoise_str}" + log.info( + f"Real-ESRGAN Upscaling seed:{seed}, scale:{upsampler_scale}x, tile:{self.bg_tile_size}, denoise:{denoise_str}" ) # ESRGAN outputs images with partial transparency if given RGBA images; convert to RGB image = image.convert("RGB") diff --git a/invokeai/backend/safety_checker.py b/invokeai/backend/safety_checker.py index 2e6c4fd479..97e3387fb4 100644 --- a/invokeai/backend/safety_checker.py +++ b/invokeai/backend/safety_checker.py @@ -14,6 +14,7 @@ from PIL import Image, ImageFilter from transformers import AutoFeatureExtractor import invokeai.assets.web as web_assets +import invokeai.backend.util.logging as log from .globals import global_cache_dir from .util import CPU_DEVICE @@ -40,8 +41,8 @@ class SafetyChecker(object): cache_dir=safety_model_path, ) except Exception: - print( - "** An error was encountered while installing the safety checker:" + log.error( + "An error was encountered while installing the safety checker:" ) print(traceback.format_exc()) @@ -65,8 +66,8 @@ class SafetyChecker(object): ) self.safety_checker.to(CPU_DEVICE) # offload if has_nsfw_concept[0]: - print( - "** An image with potential non-safe content has been detected. A blurred image will be returned. **" + log.warning( + "An image with potential non-safe content has been detected. A blurred image will be returned." ) return self.blur(image) else: diff --git a/invokeai/backend/stable_diffusion/concepts_lib.py b/invokeai/backend/stable_diffusion/concepts_lib.py index 28167a0bd5..b9fb730273 100644 --- a/invokeai/backend/stable_diffusion/concepts_lib.py +++ b/invokeai/backend/stable_diffusion/concepts_lib.py @@ -17,6 +17,7 @@ from huggingface_hub import ( hf_hub_url, ) +import invokeai.backend.util.logging as log from invokeai.backend.globals import Globals @@ -66,11 +67,11 @@ class HuggingFaceConceptsLibrary(object): # when init, add all in dir. when not init, add only concepts added between init and now self.concept_list.extend(list(local_concepts_to_add)) except Exception as e: - print( - f" ** WARNING: Hugging Face textual inversion concepts libraries could not be loaded. The error was {str(e)}." + log.warning( + f"Hugging Face textual inversion concepts libraries could not be loaded. The error was {str(e)}." ) - print( - " ** You may load .bin and .pt file(s) manually using the --embedding_directory argument." + log.warning( + "You may load .bin and .pt file(s) manually using the --embedding_directory argument." ) return self.concept_list @@ -81,7 +82,7 @@ class HuggingFaceConceptsLibrary(object): be downloaded. """ if not concept_name in self.list_concepts(): - print( + log.warning( f"{concept_name} is not a local embedding trigger, nor is it a HuggingFace concept. Generation will continue without the concept." ) return None @@ -219,7 +220,7 @@ class HuggingFaceConceptsLibrary(object): if chunk == 0: bytes += total - print(f">> Downloading {repo_id}...", end="") + log.info(f"Downloading {repo_id}...", end="") try: for file in ( "README.md", @@ -233,22 +234,22 @@ class HuggingFaceConceptsLibrary(object): ) except ul_error.HTTPError as e: if e.code == 404: - print( + log.warning( f"Concept {concept_name} is not known to the Hugging Face library. Generation will continue without the concept." ) else: - print( + log.warning( f"Failed to download {concept_name}/{file} ({str(e)}. Generation will continue without the concept.)" ) os.rmdir(dest) return False except ul_error.URLError as e: - print( - f"ERROR while downloading {concept_name}: {str(e)}. This may reflect a network issue. Generation will continue without the concept." + log.error( + f"an error occurred while downloading {concept_name}: {str(e)}. This may reflect a network issue. Generation will continue without the concept." ) os.rmdir(dest) return False - print("...{:.2f}Kb".format(bytes / 1024)) + log.info("...{:.2f}Kb".format(bytes / 1024)) return succeeded def _concept_id(self, concept_name: str) -> str: diff --git a/invokeai/backend/stable_diffusion/diffusion/cross_attention_control.py b/invokeai/backend/stable_diffusion/diffusion/cross_attention_control.py index f933a11a6f..6aa4fbd759 100644 --- a/invokeai/backend/stable_diffusion/diffusion/cross_attention_control.py +++ b/invokeai/backend/stable_diffusion/diffusion/cross_attention_control.py @@ -14,9 +14,9 @@ from diffusers.models.cross_attention import AttnProcessor from diffusers.models.unet_2d_condition import UNet2DConditionModel from torch import nn +import invokeai.backend.util.logging as log from ...util import torch_dtype - class CrossAttentionType(enum.Enum): SELF = 1 TOKENS = 2 @@ -425,13 +425,13 @@ def get_cross_attention_modules( expected_count = 16 if cross_attention_modules_in_model_count != expected_count: # non-fatal error but .swap() won't work. - print( + log.error( f"Error! CrossAttentionControl found an unexpected number of {cross_attention_class} modules in the model " + f"(expected {expected_count}, found {cross_attention_modules_in_model_count}). Either monkey-patching failed " - + f"or some assumption has changed about the structure of the model itself. Please fix the monkey-patching, " + + "or some assumption has changed about the structure of the model itself. Please fix the monkey-patching, " + f"and/or update the {expected_count} above to an appropriate number, and/or find and inform someone who knows " - + f"what it means. This error is non-fatal, but it is likely that .swap() and attention map display will not " - + f"work properly until it is fixed." + + "what it means. This error is non-fatal, but it is likely that .swap() and attention map display will not " + + "work properly until it is fixed." ) return attention_module_tuples diff --git a/invokeai/backend/stable_diffusion/diffusion/shared_invokeai_diffusion.py b/invokeai/backend/stable_diffusion/diffusion/shared_invokeai_diffusion.py index 7e3ab455b9..33946fe695 100644 --- a/invokeai/backend/stable_diffusion/diffusion/shared_invokeai_diffusion.py +++ b/invokeai/backend/stable_diffusion/diffusion/shared_invokeai_diffusion.py @@ -8,6 +8,7 @@ import torch from diffusers.models.cross_attention import AttnProcessor from typing_extensions import TypeAlias +import invokeai.backend.util.logging as log from invokeai.backend.globals import Globals from .cross_attention_control import ( @@ -262,7 +263,7 @@ class InvokeAIDiffuserComponent: # TODO remove when compvis codepath support is dropped if step_index is None and sigma is None: raise ValueError( - f"Either step_index or sigma is required when doing cross attention control, but both are None." + "Either step_index or sigma is required when doing cross attention control, but both are None." ) percent_through = self.estimate_percent_through(step_index, sigma) return percent_through @@ -466,10 +467,14 @@ class InvokeAIDiffuserComponent: outside = torch.count_nonzero( (latents < -current_threshold) | (latents > current_threshold) ) - print( - f"\nThreshold: %={percent_through} threshold={current_threshold:.3f} (of {threshold:.3f})\n" - f" | min, mean, max = {minval:.3f}, {mean:.3f}, {maxval:.3f}\tstd={std}\n" - f" | {outside / latents.numel() * 100:.2f}% values outside threshold" + log.info( + f"Threshold: %={percent_through} threshold={current_threshold:.3f} (of {threshold:.3f})" + ) + log.debug( + f"min, mean, max = {minval:.3f}, {mean:.3f}, {maxval:.3f}\tstd={std}" + ) + log.debug( + f"{outside / latents.numel() * 100:.2f}% values outside threshold" ) if maxval < current_threshold and minval > -current_threshold: @@ -496,9 +501,11 @@ class InvokeAIDiffuserComponent: ) if self.debug_thresholding: - print( - f" | min, , max = {minval:.3f}, , {maxval:.3f}\t(scaled by {scale})\n" - f" | {num_altered / latents.numel() * 100:.2f}% values altered" + log.debug( + f"min, , max = {minval:.3f}, , {maxval:.3f}\t(scaled by {scale})" + ) + log.debug( + f"{num_altered / latents.numel() * 100:.2f}% values altered" ) return latents @@ -599,7 +606,6 @@ class InvokeAIDiffuserComponent: ) # below is fugly omg - num_actual_conditionings = len(c_or_weighted_c_list) conditionings = [uc] + [c for c, weight in weighted_cond_list] weights = [1] + [weight for c, weight in weighted_cond_list] chunk_count = ceil(len(conditionings) / 2) diff --git a/invokeai/backend/stable_diffusion/image_degradation/utils_image.py b/invokeai/backend/stable_diffusion/image_degradation/utils_image.py index 08505edde0..31f5300949 100644 --- a/invokeai/backend/stable_diffusion/image_degradation/utils_image.py +++ b/invokeai/backend/stable_diffusion/image_degradation/utils_image.py @@ -10,7 +10,7 @@ from torchvision.utils import make_grid # import matplotlib.pyplot as plt # TODO: check with Dominik, also bsrgan.py vs bsrgan_light.py - +import invokeai.backend.util.logging as log os.environ["KMP_DUPLICATE_LIB_OK"] = "TRUE" @@ -191,7 +191,7 @@ def mkdirs(paths): def mkdir_and_rename(path): if os.path.exists(path): new_name = path + "_archived_" + get_timestamp() - print("Path already exists. Rename it to [{:s}]".format(new_name)) + log.error("Path already exists. Rename it to [{:s}]".format(new_name)) os.replace(path, new_name) os.makedirs(path) diff --git a/invokeai/backend/stable_diffusion/textual_inversion_manager.py b/invokeai/backend/stable_diffusion/textual_inversion_manager.py index 2dba2b88d3..1d27c7b813 100644 --- a/invokeai/backend/stable_diffusion/textual_inversion_manager.py +++ b/invokeai/backend/stable_diffusion/textual_inversion_manager.py @@ -10,6 +10,7 @@ from compel.embeddings_provider import BaseTextualInversionManager from picklescan.scanner import scan_file_path from transformers import CLIPTextModel, CLIPTokenizer +import invokeai.backend.util.logging as log from .concepts_lib import HuggingFaceConceptsLibrary @dataclass @@ -59,12 +60,12 @@ class TextualInversionManager(BaseTextualInversionManager): or self.has_textual_inversion_for_trigger_string(concept_name) or self.has_textual_inversion_for_trigger_string(f"<{concept_name}>") ): # in case a token with literal angle brackets encountered - print(f">> Loaded local embedding for trigger {concept_name}") + log.info(f"Loaded local embedding for trigger {concept_name}") continue bin_file = self.hf_concepts_library.get_concept_model_path(concept_name) if not bin_file: continue - print(f">> Loaded remote embedding for trigger {concept_name}") + log.info(f"Loaded remote embedding for trigger {concept_name}") self.load_textual_inversion(bin_file) self.hf_concepts_library.concepts_loaded[concept_name] = True @@ -85,8 +86,8 @@ class TextualInversionManager(BaseTextualInversionManager): embedding_list = self._parse_embedding(str(ckpt_path)) for embedding_info in embedding_list: if (self.text_encoder.get_input_embeddings().weight.data[0].shape[0] != embedding_info.token_dim): - print( - f" ** Notice: {ckpt_path.parents[0].name}/{ckpt_path.name} was trained on a model with an incompatible token dimension: {self.text_encoder.get_input_embeddings().weight.data[0].shape[0]} vs {embedding_info.token_dim}." + log.warning( + f"Notice: {ckpt_path.parents[0].name}/{ckpt_path.name} was trained on a model with an incompatible token dimension: {self.text_encoder.get_input_embeddings().weight.data[0].shape[0]} vs {embedding_info.token_dim}." ) continue @@ -105,8 +106,8 @@ class TextualInversionManager(BaseTextualInversionManager): if ckpt_path.name == "learned_embeds.bin" else f"<{ckpt_path.stem}>" ) - print( - f">> {sourcefile}: Trigger token '{trigger_str}' is already claimed by '{self.trigger_to_sourcefile[trigger_str]}'. Trigger this concept with {replacement_trigger_str}" + log.info( + f"{sourcefile}: Trigger token '{trigger_str}' is already claimed by '{self.trigger_to_sourcefile[trigger_str]}'. Trigger this concept with {replacement_trigger_str}" ) trigger_str = replacement_trigger_str @@ -120,8 +121,8 @@ class TextualInversionManager(BaseTextualInversionManager): self.trigger_to_sourcefile[trigger_str] = sourcefile except ValueError as e: - print(f' | Ignoring incompatible embedding {embedding_info["name"]}') - print(f" | The error was {str(e)}") + log.debug(f'Ignoring incompatible embedding {embedding_info["name"]}') + log.debug(f"The error was {str(e)}") def _add_textual_inversion( self, trigger_str, embedding, defer_injecting_tokens=False @@ -133,8 +134,8 @@ class TextualInversionManager(BaseTextualInversionManager): :return: The token id for the added embedding, either existing or newly-added. """ if trigger_str in [ti.trigger_string for ti in self.textual_inversions]: - print( - f"** TextualInversionManager refusing to overwrite already-loaded token '{trigger_str}'" + log.warning( + f"TextualInversionManager refusing to overwrite already-loaded token '{trigger_str}'" ) return if not self.full_precision: @@ -155,11 +156,11 @@ class TextualInversionManager(BaseTextualInversionManager): except ValueError as e: if str(e).startswith("Warning"): - print(f">> {str(e)}") + log.warning(f"{str(e)}") else: traceback.print_exc() - print( - f"** TextualInversionManager was unable to add a textual inversion with trigger string {trigger_str}." + log.error( + f"TextualInversionManager was unable to add a textual inversion with trigger string {trigger_str}." ) raise @@ -219,16 +220,16 @@ class TextualInversionManager(BaseTextualInversionManager): for ti in self.textual_inversions: if ti.trigger_token_id is None and ti.trigger_string in prompt_string: if ti.embedding_vector_length > 1: - print( - f">> Preparing tokens for textual inversion {ti.trigger_string}..." + log.info( + f"Preparing tokens for textual inversion {ti.trigger_string}..." ) try: self._inject_tokens_and_assign_embeddings(ti) except ValueError as e: - print( - f" | Ignoring incompatible embedding trigger {ti.trigger_string}" + log.debug( + f"Ignoring incompatible embedding trigger {ti.trigger_string}" ) - print(f" | The error was {str(e)}") + log.debug(f"The error was {str(e)}") continue injected_token_ids.append(ti.trigger_token_id) injected_token_ids.extend(ti.pad_token_ids) @@ -306,16 +307,16 @@ class TextualInversionManager(BaseTextualInversionManager): if suffix in [".pt",".ckpt",".bin"]: scan_result = scan_file_path(embedding_file) if scan_result.infected_files > 0: - print( - f" ** Security Issues Found in Model: {scan_result.issues_count}" + log.critical( + f"Security Issues Found in Model: {scan_result.issues_count}" ) - print(" ** For your safety, InvokeAI will not load this embed.") + log.critical("For your safety, InvokeAI will not load this embed.") return list() ckpt = torch.load(embedding_file,map_location="cpu") else: ckpt = safetensors.torch.load_file(embedding_file) except Exception as e: - print(f" ** Notice: unrecognized embedding file format: {embedding_file}: {e}") + log.warning(f"Notice: unrecognized embedding file format: {embedding_file}: {e}") return list() # try to figure out what kind of embedding file it is and parse accordingly @@ -334,7 +335,7 @@ class TextualInversionManager(BaseTextualInversionManager): def _parse_embedding_v1(self, embedding_ckpt: dict, file_path: str)->List[EmbeddingInfo]: basename = Path(file_path).stem - print(f' | Loading v1 embedding file: {basename}') + log.debug(f'Loading v1 embedding file: {basename}') embeddings = list() token_counter = -1 @@ -342,7 +343,7 @@ class TextualInversionManager(BaseTextualInversionManager): if token_counter < 0: trigger = embedding_ckpt["name"] elif token_counter == 0: - trigger = f'' + trigger = '' else: trigger = f'<{basename}-{int(token_counter:=token_counter)}>' token_counter += 1 @@ -365,7 +366,7 @@ class TextualInversionManager(BaseTextualInversionManager): This handles embedding .pt file variant #2. """ basename = Path(file_path).stem - print(f' | Loading v2 embedding file: {basename}') + log.debug(f'Loading v2 embedding file: {basename}') embeddings = list() if isinstance( @@ -384,7 +385,7 @@ class TextualInversionManager(BaseTextualInversionManager): ) embeddings.append(embedding_info) else: - print(f" ** {basename}: Unrecognized embedding format") + log.warning(f"{basename}: Unrecognized embedding format") return embeddings @@ -393,7 +394,7 @@ class TextualInversionManager(BaseTextualInversionManager): Parse 'version 3' of the .pt textual inversion embedding files. """ basename = Path(file_path).stem - print(f' | Loading v3 embedding file: {basename}') + log.debug(f'Loading v3 embedding file: {basename}') embedding = embedding_ckpt['emb_params'] embedding_info = EmbeddingInfo( name = f'<{basename}>', @@ -411,11 +412,11 @@ class TextualInversionManager(BaseTextualInversionManager): basename = Path(filepath).stem short_path = Path(filepath).parents[0].name+'/'+Path(filepath).name - print(f' | Loading v4 embedding file: {short_path}') + log.debug(f'Loading v4 embedding file: {short_path}') embeddings = list() if list(embedding_ckpt.keys()) == 0: - print(f" ** Invalid embeddings file: {short_path}") + log.warning(f"Invalid embeddings file: {short_path}") else: for token,embedding in embedding_ckpt.items(): embedding_info = EmbeddingInfo( diff --git a/invokeai/backend/util/util.py b/invokeai/backend/util/util.py index d5239af834..95403a57e6 100644 --- a/invokeai/backend/util/util.py +++ b/invokeai/backend/util/util.py @@ -18,6 +18,7 @@ import torch from PIL import Image, ImageDraw, ImageFont from tqdm import tqdm +import invokeai.backend.util.logging as log from .devices import torch_dtype @@ -38,7 +39,7 @@ def log_txt_as_img(wh, xc, size=10): try: draw.text((0, 0), lines, fill="black", font=font) except UnicodeEncodeError: - print("Cant encode string for logging. Skipping.") + log.warning("Cant encode string for logging. Skipping.") txt = np.array(txt).transpose(2, 0, 1) / 127.5 - 1.0 txts.append(txt) @@ -80,8 +81,8 @@ def mean_flat(tensor): def count_params(model, verbose=False): total_params = sum(p.numel() for p in model.parameters()) if verbose: - print( - f" | {model.__class__.__name__} has {total_params * 1.e-6:.2f} M params." + log.debug( + f"{model.__class__.__name__} has {total_params * 1.e-6:.2f} M params." ) return total_params @@ -132,8 +133,8 @@ def parallel_data_prefetch( raise ValueError("list expected but function got ndarray.") elif isinstance(data, abc.Iterable): if isinstance(data, dict): - print( - 'WARNING:"data" argument passed to parallel_data_prefetch is a dict: Using only its values and disregarding keys.' + log.warning( + '"data" argument passed to parallel_data_prefetch is a dict: Using only its values and disregarding keys.' ) data = list(data.values()) if target_data_type == "ndarray": @@ -175,7 +176,7 @@ def parallel_data_prefetch( processes += [p] # start processes - print("Start prefetching...") + log.info("Start prefetching...") import time start = time.time() @@ -194,7 +195,7 @@ def parallel_data_prefetch( gather_res[res[0]] = res[1] except Exception as e: - print("Exception: ", e) + log.error("Exception: ", e) for p in processes: p.terminate() @@ -202,7 +203,7 @@ def parallel_data_prefetch( finally: for p in processes: p.join() - print(f"Prefetching complete. [{time.time() - start} sec.]") + log.info(f"Prefetching complete. [{time.time() - start} sec.]") if target_data_type == "ndarray": if not isinstance(gather_res[0], np.ndarray): @@ -318,23 +319,23 @@ def download_with_resume(url: str, dest: Path, access_token: str = None) -> Path resp = requests.get(url, headers=header, stream=True) # new request with range if exist_size > content_length: - print("* corrupt existing file found. re-downloading") + log.warning("corrupt existing file found. re-downloading") os.remove(dest) exist_size = 0 if resp.status_code == 416 or exist_size == content_length: - print(f"* {dest}: complete file found. Skipping.") + log.warning(f"{dest}: complete file found. Skipping.") return dest elif resp.status_code == 206 or exist_size > 0: - print(f"* {dest}: partial file found. Resuming...") + log.warning(f"{dest}: partial file found. Resuming...") elif resp.status_code != 200: - print(f"** An error occurred during downloading {dest}: {resp.reason}") + log.error(f"An error occurred during downloading {dest}: {resp.reason}") else: - print(f"* {dest}: Downloading...") + log.error(f"{dest}: Downloading...") try: if content_length < 2000: - print(f"*** ERROR DOWNLOADING {url}: {resp.text}") + log.error(f"ERROR DOWNLOADING {url}: {resp.text}") return None with open(dest, open_mode) as file, tqdm( @@ -349,7 +350,7 @@ def download_with_resume(url: str, dest: Path, access_token: str = None) -> Path size = file.write(data) bar.update(size) except Exception as e: - print(f"An error occurred while downloading {dest}: {str(e)}") + log.error(f"An error occurred while downloading {dest}: {str(e)}") return None return dest diff --git a/invokeai/backend/web/invoke_ai_web_server.py b/invokeai/backend/web/invoke_ai_web_server.py index 7209e31449..e7c02d212a 100644 --- a/invokeai/backend/web/invoke_ai_web_server.py +++ b/invokeai/backend/web/invoke_ai_web_server.py @@ -19,6 +19,7 @@ from PIL import Image from PIL.Image import Image as ImageType from werkzeug.utils import secure_filename +import invokeai.backend.util.logging as log import invokeai.frontend.web.dist as frontend from .. import Generate @@ -213,7 +214,7 @@ class InvokeAIWebServer: self.load_socketio_listeners(self.socketio) if args.gui: - print(">> Launching Invoke AI GUI") + log.info("Launching Invoke AI GUI") try: from flaskwebgui import FlaskUI @@ -231,17 +232,17 @@ class InvokeAIWebServer: sys.exit(0) else: useSSL = args.certfile or args.keyfile - print(">> Started Invoke AI Web Server") + log.info("Started Invoke AI Web Server") if self.host == "0.0.0.0": - print( + log.info( f"Point your browser at http{'s' if useSSL else ''}://localhost:{self.port} or use the host's DNS name or IP address." ) else: - print( - ">> Default host address now 127.0.0.1 (localhost). Use --host 0.0.0.0 to bind any address." + log.info( + "Default host address now 127.0.0.1 (localhost). Use --host 0.0.0.0 to bind any address." ) - print( - f">> Point your browser at http{'s' if useSSL else ''}://{self.host}:{self.port}" + log.info( + f"Point your browser at http{'s' if useSSL else ''}://{self.host}:{self.port}" ) if not useSSL: self.socketio.run(app=self.app, host=self.host, port=self.port) @@ -290,7 +291,7 @@ class InvokeAIWebServer: def load_socketio_listeners(self, socketio): @socketio.on("requestSystemConfig") def handle_request_capabilities(): - print(">> System config requested") + log.info("System config requested") config = self.get_system_config() config["model_list"] = self.generate.model_manager.list_models() config["infill_methods"] = infill_methods() @@ -330,7 +331,7 @@ class InvokeAIWebServer: if model_name in current_model_list: update = True - print(f">> Adding New Model: {model_name}") + log.info(f"Adding New Model: {model_name}") self.generate.model_manager.add_model( model_name=model_name, @@ -348,14 +349,14 @@ class InvokeAIWebServer: "update": update, }, ) - print(f">> New Model Added: {model_name}") + log.info(f"New Model Added: {model_name}") except Exception as e: self.handle_exceptions(e) @socketio.on("deleteModel") def handle_delete_model(model_name: str): try: - print(f">> Deleting Model: {model_name}") + log.info(f"Deleting Model: {model_name}") self.generate.model_manager.del_model(model_name) self.generate.model_manager.commit(opt.conf) updated_model_list = self.generate.model_manager.list_models() @@ -366,14 +367,14 @@ class InvokeAIWebServer: "model_list": updated_model_list, }, ) - print(f">> Model Deleted: {model_name}") + log.info(f"Model Deleted: {model_name}") except Exception as e: self.handle_exceptions(e) @socketio.on("requestModelChange") def handle_set_model(model_name: str): try: - print(f">> Model change requested: {model_name}") + log.info(f"Model change requested: {model_name}") model = self.generate.set_model(model_name) model_list = self.generate.model_manager.list_models() if model is None: @@ -454,7 +455,7 @@ class InvokeAIWebServer: "update": True, }, ) - print(f">> Model Converted: {model_name}") + log.info(f"Model Converted: {model_name}") except Exception as e: self.handle_exceptions(e) @@ -490,7 +491,7 @@ class InvokeAIWebServer: if vae := self.generate.model_manager.config[models_to_merge[0]].get( "vae", None ): - print(f">> Using configured VAE assigned to {models_to_merge[0]}") + log.info(f"Using configured VAE assigned to {models_to_merge[0]}") merged_model_config.update(vae=vae) self.generate.model_manager.import_diffuser_model( @@ -507,8 +508,8 @@ class InvokeAIWebServer: "update": True, }, ) - print(f">> Models Merged: {models_to_merge}") - print(f">> New Model Added: {model_merge_info['merged_model_name']}") + log.info(f"Models Merged: {models_to_merge}") + log.info(f"New Model Added: {model_merge_info['merged_model_name']}") except Exception as e: self.handle_exceptions(e) @@ -698,7 +699,7 @@ class InvokeAIWebServer: } ) except Exception as e: - print(f">> Unable to load {path}") + log.info(f"Unable to load {path}") socketio.emit( "error", {"message": f"Unable to load {path}: {str(e)}"} ) @@ -735,9 +736,9 @@ class InvokeAIWebServer: printable_parameters["init_mask"][:64] + "..." ) - print(f"\n>> Image Generation Parameters:\n\n{printable_parameters}\n") - print(f">> ESRGAN Parameters: {esrgan_parameters}") - print(f">> Facetool Parameters: {facetool_parameters}") + log.info(f"Image Generation Parameters:\n\n{printable_parameters}\n") + log.info(f"ESRGAN Parameters: {esrgan_parameters}") + log.info(f"Facetool Parameters: {facetool_parameters}") self.generate_images( generation_parameters, @@ -750,8 +751,8 @@ class InvokeAIWebServer: @socketio.on("runPostprocessing") def handle_run_postprocessing(original_image, postprocessing_parameters): try: - print( - f'>> Postprocessing requested for "{original_image["url"]}": {postprocessing_parameters}' + log.info( + f'Postprocessing requested for "{original_image["url"]}": {postprocessing_parameters}' ) progress = Progress() @@ -861,14 +862,14 @@ class InvokeAIWebServer: @socketio.on("cancel") def handle_cancel(): - print(">> Cancel processing requested") + log.info("Cancel processing requested") self.canceled.set() # TODO: I think this needs a safety mechanism. @socketio.on("deleteImage") def handle_delete_image(url, thumbnail, uuid, category): try: - print(f'>> Delete requested "{url}"') + log.info(f'Delete requested "{url}"') from send2trash import send2trash path = self.get_image_path_from_url(url) @@ -1263,7 +1264,7 @@ class InvokeAIWebServer: image, os.path.basename(path), self.thumbnail_image_path ) - print(f'\n\n>> Image generated: "{path}"\n') + log.info(f'Image generated: "{path}"\n') self.write_log_message(f'[Generated] "{path}": {command}') if progress.total_iterations > progress.current_iteration: @@ -1329,7 +1330,7 @@ class InvokeAIWebServer: except Exception as e: # Clear the CUDA cache on an exception self.empty_cuda_cache() - print(e) + log.error(e) self.handle_exceptions(e) def empty_cuda_cache(self): From b164330e3caba567b3a4779a628930b7355cd0bd Mon Sep 17 00:00:00 2001 From: Lincoln Stein Date: Tue, 18 Apr 2023 20:49:00 -0400 Subject: [PATCH 07/68] replaced remaining print statements with log.*() --- invokeai/app/api/dependencies.py | 6 ++--- invokeai/app/api/routers/models.py | 11 ++++---- invokeai/app/cli/commands.py | 3 ++- invokeai/app/cli/completer.py | 5 ++-- invokeai/app/cli_app.py | 7 ++--- invokeai/app/invocations/util/get_model.py | 5 ++-- .../app/services/model_manager_initializer.py | 19 ++++++------- invokeai/app/services/restoration_services.py | 25 ++++++++--------- invokeai/backend/generate.py | 2 +- invokeai/backend/util/logging.py | 3 ++- invokeai/frontend/install/model_install.py | 17 ++++++------ invokeai/frontend/merge/merge_diffusers.py | 27 +++++++++---------- .../frontend/training/textual_inversion.py | 25 ++++++++--------- 13 files changed, 82 insertions(+), 73 deletions(-) diff --git a/invokeai/app/api/dependencies.py b/invokeai/app/api/dependencies.py index 5698d25758..a8d71ad07f 100644 --- a/invokeai/app/api/dependencies.py +++ b/invokeai/app/api/dependencies.py @@ -3,8 +3,9 @@ import os from argparse import Namespace -from ..services.latent_storage import DiskLatentsStorage, ForwardCacheLatentsStorage +import invokeai.backend.util.logging as log +from ..services.latent_storage import DiskLatentsStorage, ForwardCacheLatentsStorage from ...backend import Globals from ..services.model_manager_initializer import get_model_manager from ..services.restoration_services import RestorationServices @@ -47,8 +48,7 @@ class ApiDependencies: Globals.disable_xformers = not config.xformers Globals.ckpt_convert = config.ckpt_convert - # TODO: Use a logger - print(f">> Internet connectivity is {Globals.internet_available}") + log.info(f"Internet connectivity is {Globals.internet_available}") events = FastAPIEventService(event_handler_id) diff --git a/invokeai/app/api/routers/models.py b/invokeai/app/api/routers/models.py index 2de079cd6d..94dca8321e 100644 --- a/invokeai/app/api/routers/models.py +++ b/invokeai/app/api/routers/models.py @@ -4,6 +4,7 @@ import shutil import asyncio from typing import Annotated, Any, List, Literal, Optional, Union +import invokeai.backend.util.logging as log from fastapi.routing import APIRouter, HTTPException from pydantic import BaseModel, Field, parse_obj_as from pathlib import Path @@ -115,16 +116,16 @@ async def delete_model(model_name: str) -> None: model_exists = model_name in model_names # check if model exists - print(f">> Checking for model {model_name}...") + log.info(f"Checking for model {model_name}...") if model_exists: - print(f">> Deleting Model: {model_name}") + log.info(f"Deleting Model: {model_name}") ApiDependencies.invoker.services.model_manager.del_model(model_name, delete_files=True) - print(f">> Model Deleted: {model_name}") + log.info(f"Model Deleted: {model_name}") raise HTTPException(status_code=204, detail=f"Model '{model_name}' deleted successfully") else: - print(f">> Model not found") + log.error(f"Model not found") raise HTTPException(status_code=404, detail=f"Model '{model_name}' not found") @@ -248,4 +249,4 @@ async def delete_model(model_name: str) -> None: # ) # print(f">> Models Merged: {models_to_merge}") # print(f">> New Model Added: {model_merge_info['merged_model_name']}") - # except Exception as e: \ No newline at end of file + # except Exception as e: diff --git a/invokeai/app/cli/commands.py b/invokeai/app/cli/commands.py index 4e9c9aa581..f68dee6315 100644 --- a/invokeai/app/cli/commands.py +++ b/invokeai/app/cli/commands.py @@ -7,6 +7,7 @@ from pydantic import BaseModel, Field import networkx as nx import matplotlib.pyplot as plt +import invokeai.backend.util.logging as log from ..models.image import ImageField from ..services.graph import GraphExecutionState from ..services.invoker import Invoker @@ -183,7 +184,7 @@ class HistoryCommand(BaseCommand): for i in range(min(self.count, len(history))): entry_id = history[-1 - i] entry = context.get_session().graph.get_node(entry_id) - print(f"{entry_id}: {get_invocation_command(entry)}") + log.info(f"{entry_id}: {get_invocation_command(entry)}") class SetDefaultCommand(BaseCommand): diff --git a/invokeai/app/cli/completer.py b/invokeai/app/cli/completer.py index 86d3e100c3..b3e5b983a2 100644 --- a/invokeai/app/cli/completer.py +++ b/invokeai/app/cli/completer.py @@ -10,6 +10,7 @@ import shlex from pathlib import Path from typing import List, Dict, Literal, get_args, get_type_hints, get_origin +import invokeai.backend.util.logging as log from ...backend import ModelManager, Globals from ..invocations.baseinvocation import BaseInvocation from .commands import BaseCommand @@ -160,8 +161,8 @@ def set_autocompleter(model_manager: ModelManager) -> Completer: pass except OSError: # file likely corrupted newname = f"{histfile}.old" - print( - f"## Your history file {histfile} couldn't be loaded and may be corrupted. Renaming it to {newname}" + log.error( + f"Your history file {histfile} couldn't be loaded and may be corrupted. Renaming it to {newname}" ) histfile.replace(Path(newname)) atexit.register(readline.write_history_file, histfile) diff --git a/invokeai/app/cli_app.py b/invokeai/app/cli_app.py index a257825dcc..9dd9842c1a 100644 --- a/invokeai/app/cli_app.py +++ b/invokeai/app/cli_app.py @@ -13,6 +13,7 @@ from typing import ( from pydantic import BaseModel from pydantic.fields import Field +import invokeai.backend.util.logging as log from .services.latent_storage import DiskLatentsStorage, ForwardCacheLatentsStorage from ..backend import Args @@ -125,7 +126,7 @@ def invoke_all(context: CliContext): # Print any errors if context.session.has_error(): for n in context.session.errors: - print( + log.error( f"Error in node {n} (source node {context.session.prepared_source_mapping[n]}): {context.session.errors[n]}" ) @@ -279,12 +280,12 @@ def invoke_cli(): invoke_all(context) except InvalidArgs: - print('Invalid command, use "help" to list commands') + log.warning('Invalid command, use "help" to list commands') continue except SessionError: # Start a new session - print("Session error: creating a new session") + log.warning("Session error: creating a new session") context.session = context.invoker.create_execution_state() except ExitCli: diff --git a/invokeai/app/invocations/util/get_model.py b/invokeai/app/invocations/util/get_model.py index d3484a0b9d..53f42ab0d1 100644 --- a/invokeai/app/invocations/util/get_model.py +++ b/invokeai/app/invocations/util/get_model.py @@ -1,3 +1,4 @@ +import invokeai.backend.util.logging as log from invokeai.app.invocations.baseinvocation import InvocationContext from invokeai.backend.model_management.model_manager import ModelManager @@ -7,5 +8,5 @@ def choose_model(model_manager: ModelManager, model_name: str): if model_manager.valid_model(model_name): return model_manager.get_model(model_name) else: - print(f"* Warning: '{model_name}' is not a valid model name. Using default model instead.") - return model_manager.get_model() \ No newline at end of file + log.warning(f"'{model_name}' is not a valid model name. Using default model instead.") + return model_manager.get_model() diff --git a/invokeai/app/services/model_manager_initializer.py b/invokeai/app/services/model_manager_initializer.py index 3ef79f0b7e..7f1ed28e49 100644 --- a/invokeai/app/services/model_manager_initializer.py +++ b/invokeai/app/services/model_manager_initializer.py @@ -7,6 +7,7 @@ from omegaconf import OmegaConf from pathlib import Path import invokeai.version +import invokeai.backend.util.logging as log from ...backend import ModelManager from ...backend.util import choose_precision, choose_torch_device from ...backend import Globals @@ -20,8 +21,8 @@ def get_model_manager(config: Args) -> ModelManager: config, FileNotFoundError(f"The file {config_file} could not be found.") ) - print(f">> {invokeai.version.__app_name__}, version {invokeai.version.__version__}") - print(f'>> InvokeAI runtime directory is "{Globals.root}"') + log.info(f"{invokeai.version.__app_name__}, version {invokeai.version.__version__}") + log.info(f'InvokeAI runtime directory is "{Globals.root}"') # these two lines prevent a horrible warning message from appearing # when the frozen CLIP tokenizer is imported @@ -66,7 +67,7 @@ def get_model_manager(config: Args) -> ModelManager: except (FileNotFoundError, TypeError, AssertionError) as e: report_model_error(config, e) except (IOError, KeyError) as e: - print(f"{e}. Aborting.") + log.error(f"{e}. Aborting.") sys.exit(-1) # try to autoconvert new models @@ -80,14 +81,14 @@ def get_model_manager(config: Args) -> ModelManager: return model_manager def report_model_error(opt: Namespace, e: Exception): - print(f'** An error occurred while attempting to initialize the model: "{str(e)}"') - print( - "** This can be caused by a missing or corrupted models file, and can sometimes be fixed by (re)installing the models." + log.error(f'An error occurred while attempting to initialize the model: "{str(e)}"') + log.error( + "This can be caused by a missing or corrupted models file, and can sometimes be fixed by (re)installing the models." ) yes_to_all = os.environ.get("INVOKE_MODEL_RECONFIGURE") if yes_to_all: - print( - "** Reconfiguration is being forced by environment variable INVOKE_MODEL_RECONFIGURE" + log.warning + "Reconfiguration is being forced by environment variable INVOKE_MODEL_RECONFIGURE" ) else: response = input( @@ -96,7 +97,7 @@ def report_model_error(opt: Namespace, e: Exception): if response.startswith(("n", "N")): return - print("invokeai-configure is launching....\n") + log.info("invokeai-configure is launching....\n") # Match arguments that were set on the CLI # only the arguments accepted by the configuration script are parsed diff --git a/invokeai/app/services/restoration_services.py b/invokeai/app/services/restoration_services.py index f5fc687c11..5e908c0abe 100644 --- a/invokeai/app/services/restoration_services.py +++ b/invokeai/app/services/restoration_services.py @@ -1,6 +1,7 @@ import sys import traceback import torch +import invokeai.backend.util.logging as log from ...backend.restoration import Restoration from ...backend.util import choose_torch_device, CPU_DEVICE, MPS_DEVICE @@ -20,16 +21,16 @@ class RestorationServices: args.gfpgan_model_path ) else: - print(">> Face restoration disabled") + log.info("Face restoration disabled") if args.esrgan: esrgan = restoration.load_esrgan(args.esrgan_bg_tile) else: - print(">> Upscaling disabled") + log.info("Upscaling disabled") else: - print(">> Face restoration and upscaling disabled") + log.info("Face restoration and upscaling disabled") except (ModuleNotFoundError, ImportError): print(traceback.format_exc(), file=sys.stderr) - print(">> You may need to install the ESRGAN and/or GFPGAN modules") + log.info("You may need to install the ESRGAN and/or GFPGAN modules") self.device = torch.device(choose_torch_device()) self.gfpgan = gfpgan self.codeformer = codeformer @@ -58,15 +59,15 @@ class RestorationServices: if self.gfpgan is not None or self.codeformer is not None: if facetool == "gfpgan": if self.gfpgan is None: - print( - ">> GFPGAN not found. Face restoration is disabled." + log.info( + "GFPGAN not found. Face restoration is disabled." ) else: image = self.gfpgan.process(image, strength, seed) if facetool == "codeformer": if self.codeformer is None: - print( - ">> CodeFormer not found. Face restoration is disabled." + log.info( + "CodeFormer not found. Face restoration is disabled." ) else: cf_device = ( @@ -80,7 +81,7 @@ class RestorationServices: fidelity=codeformer_fidelity, ) else: - print(">> Face Restoration is disabled.") + log.info("Face Restoration is disabled.") if upscale is not None: if self.esrgan is not None: if len(upscale) < 2: @@ -93,10 +94,10 @@ class RestorationServices: denoise_str=upscale_denoise_str, ) else: - print(">> ESRGAN is disabled. Image not upscaled.") + log.info("ESRGAN is disabled. Image not upscaled.") except Exception as e: - print( - f">> Error running RealESRGAN or GFPGAN. Your image was not upscaled.\n{e}" + log.info( + f"Error running RealESRGAN or GFPGAN. Your image was not upscaled.\n{e}" ) if image_callback is not None: diff --git a/invokeai/backend/generate.py b/invokeai/backend/generate.py index 361efe99b4..dfec9df59f 100644 --- a/invokeai/backend/generate.py +++ b/invokeai/backend/generate.py @@ -1088,7 +1088,7 @@ class Generate: image = img log.info(f"using provided input image of size {image.width}x{image.height}") elif isinstance(img, str): - assert os.path.exists(img), f">> {img}: File not found" + assert os.path.exists(img), f"{img}: File not found" image = Image.open(img) log.info( diff --git a/invokeai/backend/util/logging.py b/invokeai/backend/util/logging.py index 6b85b5b288..1f820977ed 100644 --- a/invokeai/backend/util/logging.py +++ b/invokeai/backend/util/logging.py @@ -1,5 +1,6 @@ +# Copyright (c) 2023 Lincoln D. Stein and The InvokeAI Development Team + """invokeai.util.logging -Copyright 2023 The InvokeAI Development Team Logging class for InvokeAI that produces console messages that follow the conventions established in InvokeAI 1.X through 2.X. diff --git a/invokeai/frontend/install/model_install.py b/invokeai/frontend/install/model_install.py index 18ec6d55df..5822349bc6 100644 --- a/invokeai/frontend/install/model_install.py +++ b/invokeai/frontend/install/model_install.py @@ -22,6 +22,7 @@ import torch from npyscreen import widget from omegaconf import OmegaConf +import invokeai.backend.logging as log from invokeai.backend.globals import Globals, global_config_dir from ...backend.config.model_install_backend import ( @@ -455,8 +456,8 @@ def main(): Globals.root = os.path.expanduser(get_root(opt.root) or "") if not global_config_dir().exists(): - print( - ">> Your InvokeAI root directory is not set up. Calling invokeai-configure." + log.info( + "Your InvokeAI root directory is not set up. Calling invokeai-configure." ) from invokeai.frontend.install import invokeai_configure @@ -466,18 +467,18 @@ def main(): try: select_and_download_models(opt) except AssertionError as e: - print(str(e)) + log.error(e) sys.exit(-1) except KeyboardInterrupt: - print("\nGoodbye! Come back soon.") + log.info("Goodbye! Come back soon.") except widget.NotEnoughSpaceForWidget as e: if str(e).startswith("Height of 1 allocated"): - print( - "** Insufficient vertical space for the interface. Please make your window taller and try again" + log.error( + "Insufficient vertical space for the interface. Please make your window taller and try again" ) elif str(e).startswith("addwstr"): - print( - "** Insufficient horizontal space for the interface. Please make your window wider and try again." + log.error( + "Insufficient horizontal space for the interface. Please make your window wider and try again." ) diff --git a/invokeai/frontend/merge/merge_diffusers.py b/invokeai/frontend/merge/merge_diffusers.py index 1538826d54..7c2b621025 100644 --- a/invokeai/frontend/merge/merge_diffusers.py +++ b/invokeai/frontend/merge/merge_diffusers.py @@ -27,6 +27,8 @@ from ...backend.globals import ( global_models_dir, global_set_root, ) + +import invokeai.backend.util.logging as log from ...backend.model_management import ModelManager from ...frontend.install.widgets import FloatTitleSlider @@ -113,7 +115,7 @@ def merge_diffusion_models_and_commit( model_name=merged_model_name, description=f'Merge of models {", ".join(models)}' ) if vae := model_manager.config[models[0]].get("vae", None): - print(f">> Using configured VAE assigned to {models[0]}") + log.info(f"Using configured VAE assigned to {models[0]}") import_args.update(vae=vae) model_manager.import_diffuser_model(dump_path, **import_args) model_manager.commit(config_file) @@ -391,10 +393,8 @@ class mergeModelsForm(npyscreen.FormMultiPageAction): for name in self.model_manager.model_names() if self.model_manager.model_info(name).get("format") == "diffusers" ] - print(model_names) return sorted(model_names) - class Mergeapp(npyscreen.NPSAppManaged): def __init__(self): super().__init__() @@ -414,7 +414,7 @@ def run_gui(args: Namespace): args = mergeapp.merge_arguments merge_diffusion_models_and_commit(**args) - print(f'>> Models merged into new model: "{args["merged_model_name"]}".') + log.info(f'Models merged into new model: "{args["merged_model_name"]}".') def run_cli(args: Namespace): @@ -425,8 +425,8 @@ def run_cli(args: Namespace): if not args.merged_model_name: args.merged_model_name = "+".join(args.models) - print( - f'>> No --merged_model_name provided. Defaulting to "{args.merged_model_name}"' + log.info( + f'No --merged_model_name provided. Defaulting to "{args.merged_model_name}"' ) model_manager = ModelManager(OmegaConf.load(global_config_file())) @@ -435,7 +435,7 @@ def run_cli(args: Namespace): ), f'A model named "{args.merged_model_name}" already exists. Use --clobber to overwrite.' merge_diffusion_models_and_commit(**vars(args)) - print(f'>> Models merged into new model: "{args.merged_model_name}".') + log.info(f'Models merged into new model: "{args.merged_model_name}".') def main(): @@ -455,17 +455,16 @@ def main(): run_cli(args) except widget.NotEnoughSpaceForWidget as e: if str(e).startswith("Height of 1 allocated"): - print( - "** You need to have at least two diffusers models defined in models.yaml in order to merge" + log.error( + "You need to have at least two diffusers models defined in models.yaml in order to merge" ) else: - print( - "** Not enough room for the user interface. Try making this window larger." + log.error( + "Not enough room for the user interface. Try making this window larger." ) sys.exit(-1) - except Exception: - print(">> An error occurred:") - traceback.print_exc() + except Exception as e: + log.error(e) sys.exit(-1) except KeyboardInterrupt: sys.exit(-1) diff --git a/invokeai/frontend/training/textual_inversion.py b/invokeai/frontend/training/textual_inversion.py index e97284da3d..82fe450d93 100755 --- a/invokeai/frontend/training/textual_inversion.py +++ b/invokeai/frontend/training/textual_inversion.py @@ -20,6 +20,7 @@ import npyscreen from npyscreen import widget from omegaconf import OmegaConf +import invokeai.backend.util.logging as log from invokeai.backend.globals import Globals, global_set_root from ...backend.training import do_textual_inversion_training, parse_args @@ -368,14 +369,14 @@ def copy_to_embeddings_folder(args: dict): dest_dir_name = args["placeholder_token"].strip("<>") destination = Path(Globals.root, "embeddings", dest_dir_name) os.makedirs(destination, exist_ok=True) - print(f">> Training completed. Copying learned_embeds.bin into {str(destination)}") + log.info(f"Training completed. Copying learned_embeds.bin into {str(destination)}") shutil.copy(source, destination) if ( input("Delete training logs and intermediate checkpoints? [y] ") or "y" ).startswith(("y", "Y")): shutil.rmtree(Path(args["output_dir"])) else: - print(f'>> Keeping {args["output_dir"]}') + log.info(f'Keeping {args["output_dir"]}') def save_args(args: dict): @@ -422,10 +423,10 @@ def do_front_end(args: Namespace): do_textual_inversion_training(**args) copy_to_embeddings_folder(args) except Exception as e: - print("** An exception occurred during training. The exception was:") - print(str(e)) - print("** DETAILS:") - print(traceback.format_exc()) + log.error("An exception occurred during training. The exception was:") + log.error(str(e)) + log.error("DETAILS:") + log.error(traceback.format_exc()) def main(): @@ -437,21 +438,21 @@ def main(): else: do_textual_inversion_training(**vars(args)) except AssertionError as e: - print(str(e)) + log.error(e) sys.exit(-1) except KeyboardInterrupt: pass except (widget.NotEnoughSpaceForWidget, Exception) as e: if str(e).startswith("Height of 1 allocated"): - print( - "** You need to have at least one diffusers models defined in models.yaml in order to train" + log.error( + "You need to have at least one diffusers models defined in models.yaml in order to train" ) elif str(e).startswith("addwstr"): - print( - "** Not enough window space for the interface. Please make your window larger and try again." + log.error( + "Not enough window space for the interface. Please make your window larger and try again." ) else: - print(f"** An error has occurred: {str(e)}") + log.error(e) sys.exit(-1) From 1e837e3c9d32532a8860c43cb3fcaf05f02e7c13 Mon Sep 17 00:00:00 2001 From: Mary Hipp Rogers Date: Thu, 27 Apr 2023 12:05:35 -0700 Subject: [PATCH 08/68] fix(ui): add formatted neg prompt for linear nodes (#3282) * fix(ui): add formatted neg prompt for linear nodes * remove conditional --------- Co-authored-by: Mary Hipp --- .../nodes/util/linearGraphBuilder/buildImageToImageNode.ts | 3 ++- .../nodes/util/linearGraphBuilder/buildTextToImageNode.ts | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/invokeai/frontend/web/src/features/nodes/util/linearGraphBuilder/buildImageToImageNode.ts b/invokeai/frontend/web/src/features/nodes/util/linearGraphBuilder/buildImageToImageNode.ts index f04f177d5b..1219e969af 100644 --- a/invokeai/frontend/web/src/features/nodes/util/linearGraphBuilder/buildImageToImageNode.ts +++ b/invokeai/frontend/web/src/features/nodes/util/linearGraphBuilder/buildImageToImageNode.ts @@ -16,6 +16,7 @@ export const buildImg2ImgNode = (state: RootState): ImageToImageInvocation => { const { prompt, + negativePrompt, seed, steps, width, @@ -38,7 +39,7 @@ export const buildImg2ImgNode = (state: RootState): ImageToImageInvocation => { const imageToImageNode: ImageToImageInvocation = { id: nodeId, type: 'img2img', - prompt, + prompt: `${prompt} [${negativePrompt}]`, steps, width, height, diff --git a/invokeai/frontend/web/src/features/nodes/util/linearGraphBuilder/buildTextToImageNode.ts b/invokeai/frontend/web/src/features/nodes/util/linearGraphBuilder/buildTextToImageNode.ts index 057d35dbcb..a8c65004c7 100644 --- a/invokeai/frontend/web/src/features/nodes/util/linearGraphBuilder/buildTextToImageNode.ts +++ b/invokeai/frontend/web/src/features/nodes/util/linearGraphBuilder/buildTextToImageNode.ts @@ -10,6 +10,7 @@ export const buildTxt2ImgNode = (state: RootState): TextToImageInvocation => { const { prompt, + negativePrompt, seed, steps, width, @@ -23,7 +24,7 @@ export const buildTxt2ImgNode = (state: RootState): TextToImageInvocation => { const textToImageNode: NonNullable = { id: nodeId, type: 'txt2img', - prompt, + prompt: `${prompt} [${negativePrompt}]`, steps, width, height, From 4453a0d20dfa15dc97330260fb7d6f6cde55015f Mon Sep 17 00:00:00 2001 From: Mary Hipp Date: Thu, 27 Apr 2023 16:13:42 -0400 Subject: [PATCH 09/68] feat(ui): remove toasts for network bc we have status to tell us --- .../frontend/web/src/features/system/store/systemSlice.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/invokeai/frontend/web/src/features/system/store/systemSlice.ts b/invokeai/frontend/web/src/features/system/store/systemSlice.ts index 6f1da80dfe..3291cd96d7 100644 --- a/invokeai/frontend/web/src/features/system/store/systemSlice.ts +++ b/invokeai/frontend/web/src/features/system/store/systemSlice.ts @@ -409,9 +409,6 @@ export const systemSlice = createSlice({ message: `Connected to server`, level: 'info', }); - state.toastQueue.push( - makeToast({ title: i18n.t('toast.connected'), status: 'success' }) - ); }); /** @@ -427,9 +424,6 @@ export const systemSlice = createSlice({ message: `Disconnected from server`, level: 'error', }); - state.toastQueue.push( - makeToast({ title: i18n.t('toast.disconnected'), status: 'error' }) - ); }); /** From ea93cad5ff61dc54bba68bea8b26e51ef7572a84 Mon Sep 17 00:00:00 2001 From: Mary Hipp Date: Thu, 27 Apr 2023 15:23:50 -0400 Subject: [PATCH 10/68] fix(ui): update to match change in route params --- invokeai/frontend/web/src/services/events/middleware.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/invokeai/frontend/web/src/services/events/middleware.ts b/invokeai/frontend/web/src/services/events/middleware.ts index d7ca579f2e..4e2a3fbabc 100644 --- a/invokeai/frontend/web/src/services/events/middleware.ts +++ b/invokeai/frontend/web/src/services/events/middleware.ts @@ -234,7 +234,12 @@ export const socketMiddleware = () => { const imageType = result.image.image_type; dispatch(imageReceived({ imageName, imageType })); - dispatch(thumbnailReceived({ imageName, imageType })); + dispatch( + thumbnailReceived({ + thumbnailName: imageName, + thumbnailType: imageType, + }) + ); } } } From 00a0cb3403f3f1dc3442196b5a5d76ac368e6e2f Mon Sep 17 00:00:00 2001 From: Mary Hipp Date: Thu, 27 Apr 2023 11:02:44 -0400 Subject: [PATCH 11/68] fix(ui): update exported types --- invokeai/frontend/web/index.d.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/invokeai/frontend/web/index.d.ts b/invokeai/frontend/web/index.d.ts index 3006a22d93..686b6a8795 100644 --- a/invokeai/frontend/web/index.d.ts +++ b/invokeai/frontend/web/index.d.ts @@ -2,6 +2,7 @@ import React, { PropsWithChildren } from 'react'; import { IAIPopoverProps } from '../web/src/common/components/IAIPopover'; import { IAIIconButtonProps } from '../web/src/common/components/IAIIconButton'; import { InvokeTabName } from 'features/ui/store/tabMap'; +import { PartialAppConfig } from 'app/invokeai'; export {}; @@ -77,11 +78,8 @@ declare module '@invoke-ai/invoke-ai-ui' { interface InvokeProps extends PropsWithChildren { apiUrl?: string; - disabledPanels?: string[]; - disabledTabs?: InvokeTabName[]; token?: string; - shouldTransformUrls?: boolean; - shouldFetchImages?: boolean; + config?: PartialAppConfig; } declare function Invoke(props: InvokeProps): JSX.Element; From 3e80eaa342c080b579c061e8fe5ff67bbbe8855a Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Mon, 24 Apr 2023 22:07:53 +1000 Subject: [PATCH 12/68] feat(nodes): add resize and scale latents nodes - this resize/scale latents is what is needed for hires fix - also remove unused `seed` from t2l --- invokeai/app/invocations/latent.py | 85 ++++++++++++++++++++++++++++-- 1 file changed, 81 insertions(+), 4 deletions(-) diff --git a/invokeai/app/invocations/latent.py b/invokeai/app/invocations/latent.py index 3d1c925570..0e8e2f7f3f 100644 --- a/invokeai/app/invocations/latent.py +++ b/invokeai/app/invocations/latent.py @@ -146,7 +146,6 @@ class TextToLatentsInvocation(BaseInvocation): # TODO: consider making prompt optional to enable providing prompt through a link # fmt: off prompt: Optional[str] = Field(description="The prompt to generate an image from") - seed: int = Field(default=-1,ge=-1, le=np.iinfo(np.uint32).max, description="The seed to use (-1 for a random seed)", ) noise: Optional[LatentsField] = Field(description="The noise to use") steps: int = Field(default=10, gt=0, description="The number of steps to use to generate the image") width: int = Field(default=512, multiple_of=64, gt=0, description="The width of the resulting image", ) @@ -363,9 +362,87 @@ class LatentsToImageInvocation(BaseInvocation): session_id=context.graph_execution_state_id, node=self ) + torch.cuda.empty_cache() + context.services.images.save(image_type, image_name, image, metadata) return build_image_output( - image_type=image_type, - image_name=image_name, - image=image + image_type=image_type, image_name=image_name, image=image ) + + +LATENTS_INTERPOLATION_MODE = Literal[ + "nearest", "linear", "bilinear", "bicubic", "trilinear", "area", "nearest-exact" +] + + +class ResizeLatentsInvocation(BaseInvocation): + """Resizes latents to explicit width/height.""" + + type: Literal["lresize"] = "lresize" + + # Inputs + latents: Optional[LatentsField] = Field(description="The latents to resize") + width: int = Field(ge=64, multiple_of=8, description="The width to resize to") + height: int = Field(ge=64, multiple_of=8, description="The height to resize to") + downsample: int = Field( + default=8, ge=1, description="The downsampling factor (leave at 8 for SD)" + ) + mode: LATENTS_INTERPOLATION_MODE = Field( + default="bilinear", description="The interpolation mode" + ) + + def invoke(self, context: InvocationContext) -> LatentsOutput: + latents = context.services.latents.get(self.latents.latents_name) + # resizing + resized_latents = torch.nn.functional.interpolate( + latents, + size=( + self.height // self.downsample, + self.width // self.downsample, + ), + mode=self.mode, + ) + + # https://discuss.huggingface.co/t/memory-usage-by-later-pipeline-stages/23699 + torch.cuda.empty_cache() + + name = f"{context.graph_execution_state_id}__{self.id}" + context.services.latents.set(name, resized_latents) + return LatentsOutput(latents=LatentsField(latents_name=name)) + + +class ScaleLatentsInvocation(BaseInvocation): + """Scales latents by a given factor.""" + + type: Literal["lscale"] = "lscale" + + # Inputs + latents: Optional[LatentsField] = Field(description="The latents to resize") + scale: int = Field( + default=2, ge=1, description="The factor by which to scale the latents" + ) + mode: LATENTS_INTERPOLATION_MODE = Field( + default="bilinear", description="The interpolation mode" + ) + + def invoke(self, context: InvocationContext) -> LatentsOutput: + latents = context.services.latents.get(self.latents.latents_name) + + (_, _, h, w) = latents.size() + + # resizing + resized_latents = torch.nn.functional.interpolate( + latents, + size=( + h * self.scale, + w * self.scale, + ), + mode=self.mode, + ) + + # https://discuss.huggingface.co/t/memory-usage-by-later-pipeline-stages/23699 + torch.cuda.empty_cache() + + name = f"{context.graph_execution_state_id}__{self.id}" + context.services.latents.set(name, resized_latents) + return LatentsOutput(latents=LatentsField(latents_name=name)) From c4f4f8b1b8ee3b072565e456b7c3324f224e1242 Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Mon, 24 Apr 2023 22:24:12 +1000 Subject: [PATCH 13/68] fix(nodes): remove unused width and height from t2l --- invokeai/app/invocations/latent.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/invokeai/app/invocations/latent.py b/invokeai/app/invocations/latent.py index 0e8e2f7f3f..a7ed313d17 100644 --- a/invokeai/app/invocations/latent.py +++ b/invokeai/app/invocations/latent.py @@ -148,8 +148,6 @@ class TextToLatentsInvocation(BaseInvocation): prompt: Optional[str] = Field(description="The prompt to generate an image from") noise: Optional[LatentsField] = Field(description="The noise to use") steps: int = Field(default=10, gt=0, description="The number of steps to use to generate the image") - width: int = Field(default=512, multiple_of=64, gt=0, description="The width of the resulting image", ) - height: int = Field(default=512, multiple_of=64, gt=0, description="The height of the resulting image", ) cfg_scale: float = Field(default=7.5, gt=0, description="The Classifier-Free Guidance, higher values may result in a result closer to the prompt", ) scheduler: SAMPLER_NAME_VALUES = Field(default="k_lms", description="The scheduler to use" ) seamless: bool = Field(default=False, description="Whether or not to generate an image that can tile without seams", ) From 0453d60c645de3415612281dc34f15133c5ee06e Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Wed, 26 Apr 2023 21:45:05 +1000 Subject: [PATCH 14/68] fix(nodes): fix slatents and rlatents bugs --- invokeai/app/invocations/latent.py | 37 +++++++++++------------------- 1 file changed, 14 insertions(+), 23 deletions(-) diff --git a/invokeai/app/invocations/latent.py b/invokeai/app/invocations/latent.py index a7ed313d17..ca65b4d9ed 100644 --- a/invokeai/app/invocations/latent.py +++ b/invokeai/app/invocations/latent.py @@ -379,19 +379,16 @@ class ResizeLatentsInvocation(BaseInvocation): type: Literal["lresize"] = "lresize" # Inputs - latents: Optional[LatentsField] = Field(description="The latents to resize") - width: int = Field(ge=64, multiple_of=8, description="The width to resize to") - height: int = Field(ge=64, multiple_of=8, description="The height to resize to") - downsample: int = Field( - default=8, ge=1, description="The downsampling factor (leave at 8 for SD)" - ) - mode: LATENTS_INTERPOLATION_MODE = Field( - default="bilinear", description="The interpolation mode" - ) + latents: Optional[LatentsField] = Field(description="The latents to resize") + width: int = Field(ge=64, multiple_of=8, description="The width to resize to (px)") + height: int = Field(ge=64, multiple_of=8, description="The height to resize to (px)") + downsample: Optional[int] = Field(default=8, ge=1, description="The downsampling factor (leave at 8 for SD)") + mode: Optional[LATENTS_INTERPOLATION_MODE] = Field(default="bilinear", description="The interpolation mode") + antialias: Optional[bool] = Field(default=False, description="Whether or not to antialias (applied in bilinear and bicubic modes only)") def invoke(self, context: InvocationContext) -> LatentsOutput: latents = context.services.latents.get(self.latents.latents_name) - # resizing + resized_latents = torch.nn.functional.interpolate( latents, size=( @@ -399,6 +396,7 @@ class ResizeLatentsInvocation(BaseInvocation): self.width // self.downsample, ), mode=self.mode, + antialias=self.antialias if self.mode in ["bilinear", "bicubic"] else False, ) # https://discuss.huggingface.co/t/memory-usage-by-later-pipeline-stages/23699 @@ -415,27 +413,20 @@ class ScaleLatentsInvocation(BaseInvocation): type: Literal["lscale"] = "lscale" # Inputs - latents: Optional[LatentsField] = Field(description="The latents to resize") - scale: int = Field( - default=2, ge=1, description="The factor by which to scale the latents" - ) - mode: LATENTS_INTERPOLATION_MODE = Field( - default="bilinear", description="The interpolation mode" - ) + latents: Optional[LatentsField] = Field(description="The latents to scale") + scale_factor: float = Field(ge=0, description="The factor by which to scale the latents") + mode: Optional[LATENTS_INTERPOLATION_MODE] = Field(default="bilinear", description="The interpolation mode") + antialias: Optional[bool] = Field(default=False, description="Whether or not to antialias (applied in bilinear and bicubic modes only)") def invoke(self, context: InvocationContext) -> LatentsOutput: latents = context.services.latents.get(self.latents.latents_name) - (_, _, h, w) = latents.size() - # resizing resized_latents = torch.nn.functional.interpolate( latents, - size=( - h * self.scale, - w * self.scale, - ), + scale_factor=self.scale_factor, mode=self.mode, + antialias=self.antialias if self.mode in ["bilinear", "bicubic"] else False, ) # https://discuss.huggingface.co/t/memory-usage-by-later-pipeline-stages/23699 From 4a924c9b54350f640465e3171f5f14593bf9ba7c Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Thu, 27 Apr 2023 09:59:22 +1000 Subject: [PATCH 15/68] feat(nodes): hardcode resize latents downsampling --- invokeai/app/invocations/latent.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/invokeai/app/invocations/latent.py b/invokeai/app/invocations/latent.py index ca65b4d9ed..9dadc79597 100644 --- a/invokeai/app/invocations/latent.py +++ b/invokeai/app/invocations/latent.py @@ -374,7 +374,7 @@ LATENTS_INTERPOLATION_MODE = Literal[ class ResizeLatentsInvocation(BaseInvocation): - """Resizes latents to explicit width/height.""" + """Resizes latents to explicit width/height (in pixels). Provided dimensions are floor-divided by 8.""" type: Literal["lresize"] = "lresize" @@ -382,7 +382,6 @@ class ResizeLatentsInvocation(BaseInvocation): latents: Optional[LatentsField] = Field(description="The latents to resize") width: int = Field(ge=64, multiple_of=8, description="The width to resize to (px)") height: int = Field(ge=64, multiple_of=8, description="The height to resize to (px)") - downsample: Optional[int] = Field(default=8, ge=1, description="The downsampling factor (leave at 8 for SD)") mode: Optional[LATENTS_INTERPOLATION_MODE] = Field(default="bilinear", description="The interpolation mode") antialias: Optional[bool] = Field(default=False, description="Whether or not to antialias (applied in bilinear and bicubic modes only)") @@ -391,10 +390,7 @@ class ResizeLatentsInvocation(BaseInvocation): resized_latents = torch.nn.functional.interpolate( latents, - size=( - self.height // self.downsample, - self.width // self.downsample, - ), + size=(self.height // 8, self.width // 8), mode=self.mode, antialias=self.antialias if self.mode in ["bilinear", "bicubic"] else False, ) @@ -414,7 +410,7 @@ class ScaleLatentsInvocation(BaseInvocation): # Inputs latents: Optional[LatentsField] = Field(description="The latents to scale") - scale_factor: float = Field(ge=0, description="The factor by which to scale the latents") + scale_factor: float = Field(gt=0, description="The factor by which to scale the latents") mode: Optional[LATENTS_INTERPOLATION_MODE] = Field(default="bilinear", description="The interpolation mode") antialias: Optional[bool] = Field(default=False, description="Whether or not to antialias (applied in bilinear and bicubic modes only)") From bfd90968f1aa09c41767a98c0162d514d1e0bca3 Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Fri, 28 Apr 2023 12:28:39 +1000 Subject: [PATCH 16/68] chore(ui): tidy npm structure --- invokeai/frontend/web/index.d.ts | 2 +- .../{component.tsx => app/components/App.tsx} | 24 ++++++------ .../{App.tsx => components/InvokeAIUI.tsx} | 19 ++++++---- .../{ => components}/ThemeLocaleProvider.tsx | 4 +- invokeai/frontend/web/src/app/constants.ts | 17 +-------- .../frontend/web/src/app/socketio/actions.ts | 2 +- .../frontend/web/src/app/socketio/emitters.ts | 4 +- .../web/src/app/socketio/listeners.ts | 4 +- .../web/src/app/socketio/middleware.ts | 2 +- .../web/src/{ => app/store}/persistor.ts | 2 +- .../frontend/web/src/app/{ => store}/store.ts | 2 +- .../web/src/app/{ => store}/storeHooks.ts | 2 +- .../web/src/app/{ => store}/storeUtils.ts | 2 +- .../web/src/app/{ => types}/invokeai.d.ts | 0 invokeai/frontend/web/src/app/utils.ts | 25 ------------ .../src/common/components/GuidePopover.tsx | 2 +- .../common/components/ImageToImageOverlay.tsx | 6 +-- .../components/ImageToImageSettingsHeader.tsx | 4 +- .../src/common/components/ImageUploader.tsx | 2 +- .../web/src/common/hooks/useGlobalHotkeys.ts | 4 +- .../src/common/util/getPromptAndNegative.ts | 2 +- .../frontend/web/src/common/util/getUrl.ts | 4 +- .../web/src/common/util/promptToString.ts | 2 +- .../web/src/common/util/seedWeightPairs.ts | 2 +- invokeai/frontend/web/src/exports.tsx | 38 ++++++++++--------- .../ClearCanvasHistoryButtonModal.tsx | 2 +- .../features/canvas/components/IAICanvas.tsx | 2 +- .../IAICanvasBoundingBoxOverlay.tsx | 2 +- .../canvas/components/IAICanvasGrid.tsx | 4 +- .../components/IAICanvasIntermediateImage.tsx | 4 +- .../components/IAICanvasMaskCompositer.tsx | 2 +- .../canvas/components/IAICanvasMaskLines.tsx | 2 +- .../components/IAICanvasObjectRenderer.tsx | 2 +- .../canvas/components/IAICanvasResizer.tsx | 2 +- .../components/IAICanvasStagingArea.tsx | 2 +- .../IAICanvasStagingAreaToolbar.tsx | 2 +- .../canvas/components/IAICanvasStatusText.tsx | 2 +- .../IAICanvasStatusTextCursorPos.tsx | 2 +- .../components/IAICanvasToolPreview.tsx | 2 +- .../IAICanvasToolbar/IAICanvasBoundingBox.tsx | 2 +- .../IAICanvasToolbar/IAICanvasMaskOptions.tsx | 2 +- .../IAICanvasToolbar/IAICanvasRedoButton.tsx | 2 +- .../IAICanvasSettingsButtonPopover.tsx | 2 +- .../IAICanvasToolChooserOptions.tsx | 2 +- .../IAICanvasToolbar/IAICanvasToolbar.tsx | 2 +- .../IAICanvasToolbar/IAICanvasUndoButton.tsx | 2 +- .../canvas/hooks/useCanvasDragMove.ts | 2 +- .../features/canvas/hooks/useCanvasHotkeys.ts | 2 +- .../canvas/hooks/useCanvasMouseDown.ts | 2 +- .../canvas/hooks/useCanvasMouseMove.ts | 2 +- .../canvas/hooks/useCanvasMouseOut.ts | 2 +- .../features/canvas/hooks/useCanvasMouseUp.ts | 2 +- .../features/canvas/hooks/useCanvasZoom.ts | 2 +- .../canvas/hooks/useColorUnderCursor.ts | 2 +- .../features/canvas/store/canvasSelectors.ts | 2 +- .../src/features/canvas/store/canvasSlice.ts | 2 +- .../src/features/canvas/store/canvasTypes.ts | 2 +- .../store/thunks/mergeAndUploadCanvas.ts | 4 +- .../canvas/store/thunks/requestCanvasScale.ts | 2 +- .../components/CurrentImageButtons.tsx | 2 +- .../components/CurrentImageDisplay.tsx | 2 +- .../components/CurrentImagePreview.tsx | 2 +- .../gallery/components/DeleteImageModal.tsx | 2 +- .../gallery/components/HoverableImage.tsx | 4 +- .../gallery/components/ImageGallery.tsx | 2 +- .../components/ImageGalleryContent.tsx | 4 +- .../gallery/components/ImageGalleryPanel.tsx | 2 +- .../ImageMetadataViewer.tsx | 4 +- .../OLD_ImageMetadataViewer.tsx | 4 +- .../components/NextPrevImageButtons.tsx | 2 +- .../gallery/hooks/useGetImageByName.ts | 2 +- .../gallery/hooks/useGetImageByUuid.ts | 2 +- .../gallery/store/gallerySelectors.ts | 2 +- .../features/gallery/store/gallerySlice.ts | 2 +- .../features/gallery/store/resultsSlice.ts | 4 +- .../features/gallery/store/uploadsSlice.ts | 4 +- .../features/lightbox/components/Lightbox.tsx | 4 +- .../lightbox/components/ReactPanZoomImage.tsx | 2 +- .../lightbox/store/lightboxSelectors.ts | 2 +- .../features/nodes/components/AddNodeMenu.tsx | 6 +-- .../src/features/nodes/components/Flow.tsx | 4 +- .../components/IAINode/IAINodeInputs.tsx | 4 +- .../components/IAINode/IAINodeOutputs.tsx | 4 +- .../nodes/components/InvocationComponent.tsx | 4 +- .../nodes/components/NodeGraphOverlay.tsx | 4 +- .../nodes/components/ViewportControls.tsx | 4 +- .../fields/BooleanInputFieldComponent.tsx | 2 +- .../fields/EnumInputFieldComponent.tsx | 2 +- .../fields/ImageInputFieldComponent.tsx | 2 +- .../fields/ModelInputFieldComponent.tsx | 4 +- .../fields/NumberInputFieldComponent.tsx | 2 +- .../fields/StringInputFieldComponent.tsx | 2 +- .../nodes/components/panels/MinimapPanel.tsx | 4 +- .../components/panels/TopCenterPanel.tsx | 2 +- .../nodes/components/panels/TopRightPanel.tsx | 4 +- .../nodes/components/search/NodeSearch.tsx | 4 +- .../nodes/hooks/useBuildInvocation.ts | 4 +- .../selectors/invocationTemplatesSelector.ts | 2 +- .../buildImageToImageNode.ts | 4 +- .../linearGraphBuilder/buildLinearGraph.ts | 2 +- .../util/linearGraphBuilder/buildRangeNode.ts | 2 +- .../buildTextToImageNode.ts | 2 +- .../util/nodesGraphBuilder/buildNodesGraph.ts | 2 +- .../BoundingBox/BoundingBoxSettings.tsx | 2 +- .../Canvas/InfillAndScalingSettings.tsx | 2 +- .../Canvas/SeamCorrection/SeamBlur.tsx | 4 +- .../Canvas/SeamCorrection/SeamSize.tsx | 4 +- .../Canvas/SeamCorrection/SeamSteps.tsx | 4 +- .../Canvas/SeamCorrection/SeamStrength.tsx | 4 +- .../FaceRestore/CodeformerFidelity.tsx | 4 +- .../FaceRestore/FaceRestoreSettings.tsx | 4 +- .../FaceRestore/FaceRestoreStrength.tsx | 4 +- .../FaceRestore/FaceRestoreToggle.tsx | 4 +- .../FaceRestore/FaceRestoreType.tsx | 4 +- .../ImageToImage/ImageFit.tsx | 4 +- .../ImageToImage/ImageToImageStrength.tsx | 2 +- .../ImageToImage/ImageToImageToggle.tsx | 4 +- .../ImageToImage/InitialImagePreview.tsx | 4 +- .../Output/HiresSettings.tsx | 4 +- .../Output/SeamlessSettings.tsx | 4 +- .../Output/SymmetrySettings.tsx | 4 +- .../Output/SymmetryToggle.tsx | 4 +- .../AdvancedParameters/Seed/Perlin.tsx | 4 +- .../AdvancedParameters/Seed/RandomizeSeed.tsx | 4 +- .../AdvancedParameters/Seed/Seed.tsx | 4 +- .../AdvancedParameters/Seed/ShuffleSeed.tsx | 6 +-- .../AdvancedParameters/Seed/Threshold.tsx | 4 +- .../Upscale/UpscaleDenoisingStrength.tsx | 4 +- .../Upscale/UpscaleScale.tsx | 4 +- .../Upscale/UpscaleStrength.tsx | 4 +- .../Upscale/UpscaleToggle.tsx | 4 +- .../Variations/GenerateVariations.tsx | 4 +- .../Variations/SeedWeights.tsx | 4 +- .../Variations/VariationAmount.tsx | 4 +- .../components/AnimatedImageToImagePanel.tsx | 4 +- .../ImageDimensions/DimensionsSettings.tsx | 4 +- .../MainParameters/HeightSlider.tsx | 2 +- .../MainParameters/MainCFGScale.tsx | 2 +- .../components/MainParameters/MainHeight.tsx | 4 +- .../MainParameters/MainIterations.tsx | 2 +- .../components/MainParameters/MainSampler.tsx | 8 ++-- .../MainParameters/MainSettings.tsx | 6 +-- .../components/MainParameters/MainSteps.tsx | 2 +- .../components/MainParameters/MainWidth.tsx | 4 +- .../components/MainParameters/WidthSlider.tsx | 2 +- .../components/ParametersAccordion.tsx | 2 +- .../ProcessButtons/CancelButton.tsx | 2 +- .../ProcessButtons/InvokeButton.tsx | 2 +- .../components/ProcessButtons/Loopback.tsx | 2 +- .../ProcessButtons/ProcessButtons.tsx | 2 +- .../PromptInput/NegativePromptInput.tsx | 4 +- .../components/PromptInput/PromptInput.tsx | 4 +- .../features/parameters/hooks/usePrompt.ts | 4 +- .../parameters/store/generationSelectors.ts | 2 +- .../parameters/store/generationSlice.ts | 2 +- .../store/postprocessingSelectors.ts | 2 +- .../components/ClearTempFolderButtonModal.tsx | 2 +- .../features/system/components/Console.tsx | 2 +- .../components/InvokeAILogoComponent.tsx | 4 +- .../ModelManager/AddCheckpointModel.tsx | 6 +-- .../ModelManager/AddDiffusersModel.tsx | 6 +-- .../components/ModelManager/AddModel.tsx | 4 +- .../ModelManager/CheckpointModelEdit.tsx | 6 +-- .../ModelManager/DiffusersModelEdit.tsx | 6 +-- .../components/ModelManager/MergeModels.tsx | 6 +-- .../components/ModelManager/ModelConvert.tsx | 4 +- .../components/ModelManager/ModelList.tsx | 2 +- .../components/ModelManager/ModelListItem.tsx | 6 +-- .../ModelManager/ModelManagerModal.tsx | 4 +- .../components/ModelManager/SearchModels.tsx | 6 +-- .../system/components/ModelSelect.tsx | 4 +- .../system/components/ProgressBar.tsx | 2 +- .../SettingsModal/SettingsModal.tsx | 6 +-- .../features/system/components/SiteHeader.tsx | 2 +- .../system/components/StatusIndicator.tsx | 2 +- .../system/components/ThemeChanger.tsx | 4 +- .../features/system/hooks/useFeatureStatus.ts | 6 +-- .../system/hooks/useIsApplicationReady.ts | 4 +- .../features/system/hooks/useIsTabDisabled.ts | 4 +- .../features/system/hooks/useToastWatcher.ts | 2 +- .../features/system/store/configSelectors.ts | 2 +- .../src/features/system/store/configSlice.ts | 2 +- .../features/system/store/modelSelectors.ts | 2 +- .../src/features/system/store/modelSlice.ts | 2 +- .../features/system/store/systemSelectors.ts | 2 +- .../src/features/system/store/systemSlice.ts | 2 +- .../ui/components/FloatingGalleryButton.tsx | 2 +- .../FloatingParametersPanelButtons.tsx | 2 +- .../src/features/ui/components/InvokeTabs.tsx | 4 +- .../features/ui/components/InvokeWorkarea.tsx | 2 +- .../ui/components/ParametersPanel.tsx | 2 +- .../components/PinParametersPanelButton.tsx | 2 +- .../ui/components/common/ParametersSlide.tsx | 2 +- .../tabs/Generate/GenerateWorkspace.tsx | 4 +- .../UnifiedCanvasContentBeta.tsx | 2 +- .../UnifiedCanvasBrushSize.tsx | 4 +- .../UnifiedCanvasClearMask.tsx | 2 +- .../UnifiedCanvasColorPicker.tsx | 2 +- .../UnifiedCanvasDarkenOutsideSelection.tsx | 4 +- .../UnifiedCanvasEnableMask.tsx | 4 +- .../UnifiedCanvasLimitStrokesToBox.tsx | 4 +- .../UnifiedCanvasPreserveMask.tsx | 4 +- .../UnifiedCanvasSettings.tsx | 2 +- .../UnifiedCanvasShowGrid.tsx | 4 +- .../UnifiedCanvasSnapToGrid.tsx | 4 +- .../UnifiedCanvasToolSettingsBeta.tsx | 2 +- .../UnifiedCanvasCopyToClipboard.tsx | 4 +- .../UnifiedCanvasDownloadImage.tsx | 4 +- .../UnifiedCanvasFileUploader.tsx | 2 +- .../UnifiedCanvasLayerSelect.tsx | 2 +- .../UnifiedCanvasMergeVisible.tsx | 4 +- .../UnifiedCanvasMoveTool.tsx | 4 +- .../UnifiedCanvasProcessingButtons.tsx | 2 +- .../UnifiedCanvasResetCanvas.tsx | 2 +- .../UnifiedCanvasResetView.tsx | 2 +- .../UnifiedCanvasSaveToGallery.tsx | 4 +- .../UnifiedCanvasToolSelect.tsx | 2 +- .../UnifiedCanvas/UnifiedCanvasContent.tsx | 2 +- .../UnifiedCanvas/UnifiedCanvasWorkarea.tsx | 8 ++-- .../web/src/features/ui/store/hotkeysSlice.ts | 2 +- .../web/src/features/ui/store/uiSelectors.ts | 2 +- invokeai/frontend/web/src/main.tsx | 4 +- .../web/src/services/events/middleware.ts | 2 +- .../web/src/services/thunks/gallery.ts | 2 +- .../frontend/web/src/services/thunks/image.ts | 2 +- .../frontend/web/src/services/thunks/model.ts | 2 +- .../web/src/services/thunks/session.ts | 2 +- .../services/util/deserializeImageField.ts | 2 +- .../services/util/deserializeImageResponse.ts | 2 +- invokeai/frontend/web/src/theme/theme.ts | 2 +- 230 files changed, 386 insertions(+), 419 deletions(-) rename invokeai/frontend/web/src/{component.tsx => app/components/App.tsx} (74%) rename invokeai/frontend/web/src/app/{App.tsx => components/InvokeAIUI.tsx} (92%) rename invokeai/frontend/web/src/app/{ => components}/ThemeLocaleProvider.tsx (93%) rename invokeai/frontend/web/src/{ => app/store}/persistor.ts (69%) rename invokeai/frontend/web/src/app/{ => store}/store.ts (98%) rename invokeai/frontend/web/src/app/{ => store}/storeHooks.ts (83%) rename invokeai/frontend/web/src/app/{ => store}/storeUtils.ts (82%) rename invokeai/frontend/web/src/app/{ => types}/invokeai.d.ts (100%) delete mode 100644 invokeai/frontend/web/src/app/utils.ts diff --git a/invokeai/frontend/web/index.d.ts b/invokeai/frontend/web/index.d.ts index 686b6a8795..72b3e139de 100644 --- a/invokeai/frontend/web/index.d.ts +++ b/invokeai/frontend/web/index.d.ts @@ -2,7 +2,7 @@ import React, { PropsWithChildren } from 'react'; import { IAIPopoverProps } from '../web/src/common/components/IAIPopover'; import { IAIIconButtonProps } from '../web/src/common/components/IAIIconButton'; import { InvokeTabName } from 'features/ui/store/tabMap'; -import { PartialAppConfig } from 'app/invokeai'; +import { PartialAppConfig } from 'app/types/invokeai'; export {}; diff --git a/invokeai/frontend/web/src/component.tsx b/invokeai/frontend/web/src/app/components/App.tsx similarity index 74% rename from invokeai/frontend/web/src/component.tsx rename to invokeai/frontend/web/src/app/components/App.tsx index ae962b4ba1..8dfdc9f183 100644 --- a/invokeai/frontend/web/src/component.tsx +++ b/invokeai/frontend/web/src/app/components/App.tsx @@ -1,8 +1,8 @@ -import React, { lazy, PropsWithChildren, useEffect } from 'react'; +import React, { lazy, memo, PropsWithChildren, useEffect } from 'react'; import { Provider } from 'react-redux'; import { PersistGate } from 'redux-persist/integration/react'; -import { buildMiddleware, store } from './app/store'; -import { persistor } from './persistor'; +import { buildMiddleware, store } from 'app/store/store'; +import { persistor } from '../store/persistor'; import { OpenAPI } from 'services/api'; import '@fontsource/inter/100.css'; import '@fontsource/inter/200.css'; @@ -14,14 +14,14 @@ import '@fontsource/inter/700.css'; import '@fontsource/inter/800.css'; import '@fontsource/inter/900.css'; -import Loading from './common/components/Loading/Loading'; +import Loading from '../../common/components/Loading/Loading'; import { addMiddleware, resetMiddlewares } from 'redux-dynamic-middlewares'; -import { PartialAppConfig } from 'app/invokeai'; +import { PartialAppConfig } from 'app/types/invokeai'; -import './i18n'; +import '../../i18n'; -const App = lazy(() => import('./app/App')); -const ThemeLocaleProvider = lazy(() => import('./app/ThemeLocaleProvider')); +const InvokeAIUI = lazy(() => import('./InvokeAIUI')); +const ThemeLocaleProvider = lazy(() => import('./ThemeLocaleProvider')); interface Props extends PropsWithChildren { apiUrl?: string; @@ -29,7 +29,7 @@ interface Props extends PropsWithChildren { config?: PartialAppConfig; } -export default function Component({ apiUrl, token, config, children }: Props) { +const App = ({ apiUrl, token, config, children }: Props) => { useEffect(() => { // configure API client token if (token) { @@ -59,11 +59,13 @@ export default function Component({ apiUrl, token, config, children }: Props) { } persistor={persistor}> }> - {children} + {children} ); -} +}; + +export default memo(App); diff --git a/invokeai/frontend/web/src/app/App.tsx b/invokeai/frontend/web/src/app/components/InvokeAIUI.tsx similarity index 92% rename from invokeai/frontend/web/src/app/App.tsx rename to invokeai/frontend/web/src/app/components/InvokeAIUI.tsx index f30bdc0eb3..b491265ef5 100644 --- a/invokeai/frontend/web/src/app/App.tsx +++ b/invokeai/frontend/web/src/app/components/InvokeAIUI.tsx @@ -3,7 +3,6 @@ import Console from 'features/system/components/Console'; import ProgressBar from 'features/system/components/ProgressBar'; import SiteHeader from 'features/system/components/SiteHeader'; import InvokeTabs from 'features/ui/components/InvokeTabs'; -import { keepGUIAlive } from './utils'; import useToastWatcher from 'features/system/hooks/useToastWatcher'; @@ -13,23 +12,27 @@ import { Box, Flex, Grid, Portal, useColorMode } from '@chakra-ui/react'; import { APP_HEIGHT, APP_WIDTH } from 'theme/util/constants'; import ImageGalleryPanel from 'features/gallery/components/ImageGalleryPanel'; import Lightbox from 'features/lightbox/components/Lightbox'; -import { useAppDispatch, useAppSelector } from './storeHooks'; -import { PropsWithChildren, useCallback, useEffect, useState } from 'react'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; +import { + memo, + PropsWithChildren, + useCallback, + useEffect, + useState, +} from 'react'; import { motion, AnimatePresence } from 'framer-motion'; import Loading from 'common/components/Loading/Loading'; import { useIsApplicationReady } from 'features/system/hooks/useIsApplicationReady'; -import { PartialAppConfig } from './invokeai'; +import { PartialAppConfig } from 'app/types/invokeai'; import { useGlobalHotkeys } from 'common/hooks/useGlobalHotkeys'; import { configChanged } from 'features/system/store/configSlice'; import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus'; -keepGUIAlive(); - interface Props extends PropsWithChildren { config?: PartialAppConfig; } -const App = ({ config = {}, children }: Props) => { +const InvokeAIUI = ({ config = {}, children }: Props) => { useToastWatcher(); useGlobalHotkeys(); @@ -121,4 +124,4 @@ const App = ({ config = {}, children }: Props) => { ); }; -export default App; +export default memo(InvokeAIUI); diff --git a/invokeai/frontend/web/src/app/ThemeLocaleProvider.tsx b/invokeai/frontend/web/src/app/components/ThemeLocaleProvider.tsx similarity index 93% rename from invokeai/frontend/web/src/app/ThemeLocaleProvider.tsx rename to invokeai/frontend/web/src/app/components/ThemeLocaleProvider.tsx index e7054edcc4..e574456e37 100644 --- a/invokeai/frontend/web/src/app/ThemeLocaleProvider.tsx +++ b/invokeai/frontend/web/src/app/components/ThemeLocaleProvider.tsx @@ -2,8 +2,8 @@ import { ChakraProvider, extendTheme } from '@chakra-ui/react'; import { ReactNode, useEffect } from 'react'; import { useTranslation } from 'react-i18next'; import { theme as invokeAITheme } from 'theme/theme'; -import { RootState } from './store'; -import { useAppSelector } from './storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppSelector } from 'app/store/storeHooks'; import { greenTeaThemeColors } from 'theme/colors/greenTea'; import { invokeAIThemeColors } from 'theme/colors/invokeAI'; diff --git a/invokeai/frontend/web/src/app/constants.ts b/invokeai/frontend/web/src/app/constants.ts index b9cd5839df..083f57f26f 100644 --- a/invokeai/frontend/web/src/app/constants.ts +++ b/invokeai/frontend/web/src/app/constants.ts @@ -2,22 +2,7 @@ import { InProgressImageType } from 'features/system/store/systemSlice'; -// Valid samplers -export const SAMPLERS: Array = [ - 'ddim', - 'plms', - 'k_lms', - 'k_dpm_2', - 'k_dpm_2_a', - 'k_dpmpp_2', - 'k_dpmpp_2_a', - 'k_euler', - 'k_euler_a', - 'k_heun', -]; - -// Valid Diffusers Samplers -export const DIFFUSERS_SAMPLERS: Array = [ +export const DIFFUSERS_SCHEDULERS: Array = [ 'ddim', 'plms', 'k_lms', diff --git a/invokeai/frontend/web/src/app/socketio/actions.ts b/invokeai/frontend/web/src/app/socketio/actions.ts index 4907595c75..923c1f59b0 100644 --- a/invokeai/frontend/web/src/app/socketio/actions.ts +++ b/invokeai/frontend/web/src/app/socketio/actions.ts @@ -1,5 +1,5 @@ import { createAction } from '@reduxjs/toolkit'; -import * as InvokeAI from 'app/invokeai'; +import * as InvokeAI from 'app/types/invokeai'; import { GalleryCategory } from 'features/gallery/store/gallerySlice'; import { InvokeTabName } from 'features/ui/store/tabMap'; diff --git a/invokeai/frontend/web/src/app/socketio/emitters.ts b/invokeai/frontend/web/src/app/socketio/emitters.ts index cd25319aee..5c9057cac3 100644 --- a/invokeai/frontend/web/src/app/socketio/emitters.ts +++ b/invokeai/frontend/web/src/app/socketio/emitters.ts @@ -1,6 +1,6 @@ import { AnyAction, Dispatch, MiddlewareAPI } from '@reduxjs/toolkit'; -import * as InvokeAI from 'app/invokeai'; -import type { RootState } from 'app/store'; +import * as InvokeAI from 'app/types/invokeai'; +import type { RootState } from 'app/store/store'; import { frontendToBackendParameters, FrontendToBackendParametersConfig, diff --git a/invokeai/frontend/web/src/app/socketio/listeners.ts b/invokeai/frontend/web/src/app/socketio/listeners.ts index dc6c35d862..39d4b4ec23 100644 --- a/invokeai/frontend/web/src/app/socketio/listeners.ts +++ b/invokeai/frontend/web/src/app/socketio/listeners.ts @@ -3,7 +3,7 @@ import dateFormat from 'dateformat'; import i18n from 'i18n'; import { v4 as uuidv4 } from 'uuid'; -import * as InvokeAI from 'app/invokeai'; +import * as InvokeAI from 'app/types/invokeai'; import { addLogEntry, @@ -30,7 +30,7 @@ import { setIntermediateImage, } from 'features/gallery/store/gallerySlice'; -import type { RootState } from 'app/store'; +import type { RootState } from 'app/store/store'; import { addImageToStagingArea } from 'features/canvas/store/canvasSlice'; import { clearInitialImage, diff --git a/invokeai/frontend/web/src/app/socketio/middleware.ts b/invokeai/frontend/web/src/app/socketio/middleware.ts index 46dafc7656..74752dc980 100644 --- a/invokeai/frontend/web/src/app/socketio/middleware.ts +++ b/invokeai/frontend/web/src/app/socketio/middleware.ts @@ -4,7 +4,7 @@ import { io } from 'socket.io-client'; import makeSocketIOEmitters from './emitters'; import makeSocketIOListeners from './listeners'; -import * as InvokeAI from 'app/invokeai'; +import * as InvokeAI from 'app/types/invokeai'; /** * Creates a socketio middleware to handle communication with server. diff --git a/invokeai/frontend/web/src/persistor.ts b/invokeai/frontend/web/src/app/store/persistor.ts similarity index 69% rename from invokeai/frontend/web/src/persistor.ts rename to invokeai/frontend/web/src/app/store/persistor.ts index ee860da3f3..85dc934943 100644 --- a/invokeai/frontend/web/src/persistor.ts +++ b/invokeai/frontend/web/src/app/store/persistor.ts @@ -1,4 +1,4 @@ -import { store } from 'app/store'; +import { store } from 'app/store/store'; import { persistStore } from 'redux-persist'; export const persistor = persistStore(store); diff --git a/invokeai/frontend/web/src/app/store.ts b/invokeai/frontend/web/src/app/store/store.ts similarity index 98% rename from invokeai/frontend/web/src/app/store.ts rename to invokeai/frontend/web/src/app/store/store.ts index 3b9ab2eea1..1c1d16de50 100644 --- a/invokeai/frontend/web/src/app/store.ts +++ b/invokeai/frontend/web/src/app/store/store.ts @@ -19,7 +19,7 @@ import hotkeysReducer from 'features/ui/store/hotkeysSlice'; import modelsReducer from 'features/system/store/modelSlice'; import nodesReducer from 'features/nodes/store/nodesSlice'; -import { socketioMiddleware } from './socketio/middleware'; +import { socketioMiddleware } from '../socketio/middleware'; import { socketMiddleware } from 'services/events/middleware'; import { canvasDenylist } from 'features/canvas/store/canvasPersistDenylist'; import { galleryDenylist } from 'features/gallery/store/galleryPersistDenylist'; diff --git a/invokeai/frontend/web/src/app/storeHooks.ts b/invokeai/frontend/web/src/app/store/storeHooks.ts similarity index 83% rename from invokeai/frontend/web/src/app/storeHooks.ts rename to invokeai/frontend/web/src/app/store/storeHooks.ts index 391929d74b..387bc7ea68 100644 --- a/invokeai/frontend/web/src/app/storeHooks.ts +++ b/invokeai/frontend/web/src/app/store/storeHooks.ts @@ -1,5 +1,5 @@ import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux'; -import { AppDispatch, RootState } from './store'; +import { AppDispatch, RootState } from 'app/store/store'; // Use throughout your app instead of plain `useDispatch` and `useSelector` export const useAppDispatch: () => AppDispatch = useDispatch; diff --git a/invokeai/frontend/web/src/app/storeUtils.ts b/invokeai/frontend/web/src/app/store/storeUtils.ts similarity index 82% rename from invokeai/frontend/web/src/app/storeUtils.ts rename to invokeai/frontend/web/src/app/store/storeUtils.ts index 851c0ba09d..1ccaad9f89 100644 --- a/invokeai/frontend/web/src/app/storeUtils.ts +++ b/invokeai/frontend/web/src/app/store/storeUtils.ts @@ -1,5 +1,5 @@ import { createAsyncThunk } from '@reduxjs/toolkit'; -import { AppDispatch, RootState } from './store'; +import { AppDispatch, RootState } from 'app/store/store'; // https://redux-toolkit.js.org/usage/usage-with-typescript#defining-a-pre-typed-createasyncthunk export const createAppAsyncThunk = createAsyncThunk.withTypes<{ diff --git a/invokeai/frontend/web/src/app/invokeai.d.ts b/invokeai/frontend/web/src/app/types/invokeai.d.ts similarity index 100% rename from invokeai/frontend/web/src/app/invokeai.d.ts rename to invokeai/frontend/web/src/app/types/invokeai.d.ts diff --git a/invokeai/frontend/web/src/app/utils.ts b/invokeai/frontend/web/src/app/utils.ts deleted file mode 100644 index 6bc959f2f7..0000000000 --- a/invokeai/frontend/web/src/app/utils.ts +++ /dev/null @@ -1,25 +0,0 @@ -export function keepGUIAlive() { - async function getRequest(url = '') { - const response = await fetch(url, { - method: 'GET', - cache: 'no-cache', - }); - return response; - } - - const keepAliveServer = () => { - const url = document.location; - const route = '/flaskwebgui-keep-server-alive'; - getRequest(url + route).then((data) => { - return data; - }); - }; - - if (!import.meta.env.NODE_ENV || import.meta.env.NODE_ENV === 'production') { - document.addEventListener('DOMContentLoaded', () => { - const intervalRequest = 3 * 1000; - keepAliveServer(); - setInterval(keepAliveServer, intervalRequest); - }); - } -} diff --git a/invokeai/frontend/web/src/common/components/GuidePopover.tsx b/invokeai/frontend/web/src/common/components/GuidePopover.tsx index 7fa0709321..1cfb60a830 100644 --- a/invokeai/frontend/web/src/common/components/GuidePopover.tsx +++ b/invokeai/frontend/web/src/common/components/GuidePopover.tsx @@ -8,7 +8,7 @@ import { } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; import { Feature, useFeatureHelpInfo } from 'app/features'; -import { useAppSelector } from 'app/storeHooks'; +import { useAppSelector } from 'app/store/storeHooks'; import { systemSelector } from 'features/system/store/systemSelectors'; import { SystemState } from 'features/system/store/systemSlice'; import { memo, ReactElement } from 'react'; diff --git a/invokeai/frontend/web/src/common/components/ImageToImageOverlay.tsx b/invokeai/frontend/web/src/common/components/ImageToImageOverlay.tsx index 27ce11d3b3..a78ced06ea 100644 --- a/invokeai/frontend/web/src/common/components/ImageToImageOverlay.tsx +++ b/invokeai/frontend/web/src/common/components/ImageToImageOverlay.tsx @@ -1,12 +1,12 @@ import { Badge, Box, ButtonGroup, Flex } from '@chakra-ui/react'; -import { RootState } from 'app/store'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { clearInitialImage } from 'features/parameters/store/generationSlice'; import { useCallback } from 'react'; import IAIIconButton from 'common/components/IAIIconButton'; import { FaUndo, FaUpload } from 'react-icons/fa'; import { useTranslation } from 'react-i18next'; -import { Image } from 'app/invokeai'; +import { Image } from 'app/types/invokeai'; type ImageToImageOverlayProps = { setIsLoaded: (isLoaded: boolean) => void; diff --git a/invokeai/frontend/web/src/common/components/ImageToImageSettingsHeader.tsx b/invokeai/frontend/web/src/common/components/ImageToImageSettingsHeader.tsx index 0b58b82185..bbd39c439f 100644 --- a/invokeai/frontend/web/src/common/components/ImageToImageSettingsHeader.tsx +++ b/invokeai/frontend/web/src/common/components/ImageToImageSettingsHeader.tsx @@ -20,8 +20,8 @@ import IAIIconButton from 'common/components/IAIIconButton'; import { useTranslation } from 'react-i18next'; import { FaUndo, FaUpload } from 'react-icons/fa'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; -import { RootState } from 'app/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; +import { RootState } from 'app/store/store'; import { useCallback } from 'react'; import { clearInitialImage } from 'features/parameters/store/generationSlice'; diff --git a/invokeai/frontend/web/src/common/components/ImageUploader.tsx b/invokeai/frontend/web/src/common/components/ImageUploader.tsx index beaa5f02d2..8ff88c7ecf 100644 --- a/invokeai/frontend/web/src/common/components/ImageUploader.tsx +++ b/invokeai/frontend/web/src/common/components/ImageUploader.tsx @@ -1,6 +1,6 @@ import { Box, useToast } from '@chakra-ui/react'; import { ImageUploaderTriggerContext } from 'app/contexts/ImageUploaderTriggerContext'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import useImageUploader from 'common/hooks/useImageUploader'; import { activeTabNameSelector } from 'features/ui/store/uiSelectors'; import { ResourceKey } from 'i18next'; diff --git a/invokeai/frontend/web/src/common/hooks/useGlobalHotkeys.ts b/invokeai/frontend/web/src/common/hooks/useGlobalHotkeys.ts index e13215c3f7..46dff1f933 100644 --- a/invokeai/frontend/web/src/common/hooks/useGlobalHotkeys.ts +++ b/invokeai/frontend/web/src/common/hooks/useGlobalHotkeys.ts @@ -1,6 +1,6 @@ import { createSelector } from '@reduxjs/toolkit'; -import { RootState } from 'app/store'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { shiftKeyPressed } from 'features/ui/store/hotkeysSlice'; import { isEqual } from 'lodash'; import { isHotkeyPressed, useHotkeys } from 'react-hotkeys-hook'; diff --git a/invokeai/frontend/web/src/common/util/getPromptAndNegative.ts b/invokeai/frontend/web/src/common/util/getPromptAndNegative.ts index 7400e63bfc..4683d44428 100644 --- a/invokeai/frontend/web/src/common/util/getPromptAndNegative.ts +++ b/invokeai/frontend/web/src/common/util/getPromptAndNegative.ts @@ -1,4 +1,4 @@ -import * as InvokeAI from 'app/invokeai'; +import * as InvokeAI from 'app/types/invokeai'; import promptToString from './promptToString'; export function getPromptAndNegative(inputPrompt: InvokeAI.Prompt) { diff --git a/invokeai/frontend/web/src/common/util/getUrl.ts b/invokeai/frontend/web/src/common/util/getUrl.ts index a684c4041b..956e3428dc 100644 --- a/invokeai/frontend/web/src/common/util/getUrl.ts +++ b/invokeai/frontend/web/src/common/util/getUrl.ts @@ -1,5 +1,5 @@ -import { RootState } from 'app/store'; -import { useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppSelector } from 'app/store/storeHooks'; import { OpenAPI } from 'services/api'; export const getUrlAlt = (url: string, shouldTransformUrls: boolean) => { diff --git a/invokeai/frontend/web/src/common/util/promptToString.ts b/invokeai/frontend/web/src/common/util/promptToString.ts index 5121e25eef..cb86af2988 100644 --- a/invokeai/frontend/web/src/common/util/promptToString.ts +++ b/invokeai/frontend/web/src/common/util/promptToString.ts @@ -1,4 +1,4 @@ -import * as InvokeAI from 'app/invokeai'; +import * as InvokeAI from 'app/types/invokeai'; const promptToString = (prompt: InvokeAI.Prompt): string => { if (typeof prompt === 'string') { diff --git a/invokeai/frontend/web/src/common/util/seedWeightPairs.ts b/invokeai/frontend/web/src/common/util/seedWeightPairs.ts index e35e69ac9a..3a8af5c11d 100644 --- a/invokeai/frontend/web/src/common/util/seedWeightPairs.ts +++ b/invokeai/frontend/web/src/common/util/seedWeightPairs.ts @@ -1,4 +1,4 @@ -import * as InvokeAI from 'app/invokeai'; +import * as InvokeAI from 'app/types/invokeai'; export const stringToSeedWeights = ( string: string diff --git a/invokeai/frontend/web/src/exports.tsx b/invokeai/frontend/web/src/exports.tsx index ffab33ead7..617a1fd271 100644 --- a/invokeai/frontend/web/src/exports.tsx +++ b/invokeai/frontend/web/src/exports.tsx @@ -1,20 +1,22 @@ -import Component from './component'; +// import App from './app/components/App'; -import InvokeAiLogoComponent from './features/system/components/InvokeAILogoComponent'; -import ThemeChanger from './features/system/components/ThemeChanger'; -import IAIPopover from './common/components/IAIPopover'; -import IAIIconButton from './common/components/IAIIconButton'; -import SettingsModal from './features/system/components/SettingsModal/SettingsModal'; -import StatusIndicator from './features/system/components/StatusIndicator'; -import ModelSelect from 'features/system/components/ModelSelect'; +// import InvokeAiLogoComponent from './features/system/components/InvokeAILogoComponent'; +// import ThemeChanger from './features/system/components/ThemeChanger'; +// import IAIPopover from './common/components/IAIPopover'; +// import IAIIconButton from './common/components/IAIIconButton'; +// import SettingsModal from './features/system/components/SettingsModal/SettingsModal'; +// import StatusIndicator from './features/system/components/StatusIndicator'; +// import ModelSelect from 'features/system/components/ModelSelect'; -export default Component; -export { - InvokeAiLogoComponent, - ThemeChanger, - IAIPopover, - IAIIconButton, - SettingsModal, - StatusIndicator, - ModelSelect, -}; +// export default App; +// export { +// InvokeAiLogoComponent, +// ThemeChanger, +// IAIPopover, +// IAIIconButton, +// SettingsModal, +// StatusIndicator, +// ModelSelect, +// }; + +export default {}; diff --git a/invokeai/frontend/web/src/features/canvas/components/ClearCanvasHistoryButtonModal.tsx b/invokeai/frontend/web/src/features/canvas/components/ClearCanvasHistoryButtonModal.tsx index 46b4227589..49a13c401c 100644 --- a/invokeai/frontend/web/src/features/canvas/components/ClearCanvasHistoryButtonModal.tsx +++ b/invokeai/frontend/web/src/features/canvas/components/ClearCanvasHistoryButtonModal.tsx @@ -1,4 +1,4 @@ -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIAlertDialog from 'common/components/IAIAlertDialog'; import IAIButton from 'common/components/IAIButton'; import { clearCanvasHistory } from 'features/canvas/store/canvasSlice'; diff --git a/invokeai/frontend/web/src/features/canvas/components/IAICanvas.tsx b/invokeai/frontend/web/src/features/canvas/components/IAICanvas.tsx index 657f407b5d..634a72f81c 100644 --- a/invokeai/frontend/web/src/features/canvas/components/IAICanvas.tsx +++ b/invokeai/frontend/web/src/features/canvas/components/IAICanvas.tsx @@ -1,6 +1,6 @@ import { Box, chakra, Flex } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; -import { useAppSelector } from 'app/storeHooks'; +import { useAppSelector } from 'app/store/storeHooks'; import { canvasSelector, isStagingSelector, diff --git a/invokeai/frontend/web/src/features/canvas/components/IAICanvasBoundingBoxOverlay.tsx b/invokeai/frontend/web/src/features/canvas/components/IAICanvasBoundingBoxOverlay.tsx index cfdbddb1e2..b6406a1945 100644 --- a/invokeai/frontend/web/src/features/canvas/components/IAICanvasBoundingBoxOverlay.tsx +++ b/invokeai/frontend/web/src/features/canvas/components/IAICanvasBoundingBoxOverlay.tsx @@ -1,5 +1,5 @@ import { createSelector } from '@reduxjs/toolkit'; -import { useAppSelector } from 'app/storeHooks'; +import { useAppSelector } from 'app/store/storeHooks'; import { isEqual } from 'lodash'; import { Group, Rect } from 'react-konva'; diff --git a/invokeai/frontend/web/src/features/canvas/components/IAICanvasGrid.tsx b/invokeai/frontend/web/src/features/canvas/components/IAICanvasGrid.tsx index 26fb6f7823..6bd926f852 100644 --- a/invokeai/frontend/web/src/features/canvas/components/IAICanvasGrid.tsx +++ b/invokeai/frontend/web/src/features/canvas/components/IAICanvasGrid.tsx @@ -2,8 +2,8 @@ import { useToken } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; -import { RootState } from 'app/store'; -import { useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppSelector } from 'app/store/storeHooks'; import { canvasSelector } from 'features/canvas/store/canvasSelectors'; import { isEqual, range } from 'lodash'; diff --git a/invokeai/frontend/web/src/features/canvas/components/IAICanvasIntermediateImage.tsx b/invokeai/frontend/web/src/features/canvas/components/IAICanvasIntermediateImage.tsx index cb7ab5fee8..071d303939 100644 --- a/invokeai/frontend/web/src/features/canvas/components/IAICanvasIntermediateImage.tsx +++ b/invokeai/frontend/web/src/features/canvas/components/IAICanvasIntermediateImage.tsx @@ -1,6 +1,6 @@ import { createSelector } from '@reduxjs/toolkit'; -import { RootState } from 'app/store'; -import { useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppSelector } from 'app/store/storeHooks'; import { useGetUrl } from 'common/util/getUrl'; import { GalleryState } from 'features/gallery/store/gallerySlice'; import { ImageConfig } from 'konva/lib/shapes/Image'; diff --git a/invokeai/frontend/web/src/features/canvas/components/IAICanvasMaskCompositer.tsx b/invokeai/frontend/web/src/features/canvas/components/IAICanvasMaskCompositer.tsx index 5417e101f8..1c2a15c600 100644 --- a/invokeai/frontend/web/src/features/canvas/components/IAICanvasMaskCompositer.tsx +++ b/invokeai/frontend/web/src/features/canvas/components/IAICanvasMaskCompositer.tsx @@ -1,5 +1,5 @@ import { createSelector } from '@reduxjs/toolkit'; -import { useAppSelector } from 'app/storeHooks'; +import { useAppSelector } from 'app/store/storeHooks'; import { canvasSelector } from 'features/canvas/store/canvasSelectors'; import { RectConfig } from 'konva/lib/shapes/Rect'; import { Rect } from 'react-konva'; diff --git a/invokeai/frontend/web/src/features/canvas/components/IAICanvasMaskLines.tsx b/invokeai/frontend/web/src/features/canvas/components/IAICanvasMaskLines.tsx index 0ff1101626..e1bf26f4ba 100644 --- a/invokeai/frontend/web/src/features/canvas/components/IAICanvasMaskLines.tsx +++ b/invokeai/frontend/web/src/features/canvas/components/IAICanvasMaskLines.tsx @@ -1,5 +1,5 @@ import { createSelector } from '@reduxjs/toolkit'; -import { useAppSelector } from 'app/storeHooks'; +import { useAppSelector } from 'app/store/storeHooks'; import { canvasSelector } from 'features/canvas/store/canvasSelectors'; import { GroupConfig } from 'konva/lib/Group'; import { isEqual } from 'lodash'; diff --git a/invokeai/frontend/web/src/features/canvas/components/IAICanvasObjectRenderer.tsx b/invokeai/frontend/web/src/features/canvas/components/IAICanvasObjectRenderer.tsx index 1d2852eef6..6d1598a21b 100644 --- a/invokeai/frontend/web/src/features/canvas/components/IAICanvasObjectRenderer.tsx +++ b/invokeai/frontend/web/src/features/canvas/components/IAICanvasObjectRenderer.tsx @@ -1,5 +1,5 @@ import { createSelector } from '@reduxjs/toolkit'; -import { useAppSelector } from 'app/storeHooks'; +import { useAppSelector } from 'app/store/storeHooks'; import { useGetUrl } from 'common/util/getUrl'; import { canvasSelector } from 'features/canvas/store/canvasSelectors'; import { rgbaColorToString } from 'features/canvas/util/colorToString'; diff --git a/invokeai/frontend/web/src/features/canvas/components/IAICanvasResizer.tsx b/invokeai/frontend/web/src/features/canvas/components/IAICanvasResizer.tsx index 3062abae91..013d689182 100644 --- a/invokeai/frontend/web/src/features/canvas/components/IAICanvasResizer.tsx +++ b/invokeai/frontend/web/src/features/canvas/components/IAICanvasResizer.tsx @@ -1,6 +1,6 @@ import { Flex, Spinner } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { canvasSelector, initialCanvasImageSelector, diff --git a/invokeai/frontend/web/src/features/canvas/components/IAICanvasStagingArea.tsx b/invokeai/frontend/web/src/features/canvas/components/IAICanvasStagingArea.tsx index 1a84aa88bb..c373141f6f 100644 --- a/invokeai/frontend/web/src/features/canvas/components/IAICanvasStagingArea.tsx +++ b/invokeai/frontend/web/src/features/canvas/components/IAICanvasStagingArea.tsx @@ -1,5 +1,5 @@ import { createSelector } from '@reduxjs/toolkit'; -import { useAppSelector } from 'app/storeHooks'; +import { useAppSelector } from 'app/store/storeHooks'; import { useGetUrl } from 'common/util/getUrl'; import { canvasSelector } from 'features/canvas/store/canvasSelectors'; import { GroupConfig } from 'konva/lib/Group'; diff --git a/invokeai/frontend/web/src/features/canvas/components/IAICanvasStagingAreaToolbar.tsx b/invokeai/frontend/web/src/features/canvas/components/IAICanvasStagingAreaToolbar.tsx index 74d6382308..e74081b2f4 100644 --- a/invokeai/frontend/web/src/features/canvas/components/IAICanvasStagingAreaToolbar.tsx +++ b/invokeai/frontend/web/src/features/canvas/components/IAICanvasStagingAreaToolbar.tsx @@ -1,7 +1,7 @@ import { ButtonGroup, Flex } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; import { saveStagingAreaImageToGallery } from 'app/socketio/actions'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIIconButton from 'common/components/IAIIconButton'; import { canvasSelector } from 'features/canvas/store/canvasSelectors'; import { diff --git a/invokeai/frontend/web/src/features/canvas/components/IAICanvasStatusText.tsx b/invokeai/frontend/web/src/features/canvas/components/IAICanvasStatusText.tsx index 72f532217f..a6d32081c4 100644 --- a/invokeai/frontend/web/src/features/canvas/components/IAICanvasStatusText.tsx +++ b/invokeai/frontend/web/src/features/canvas/components/IAICanvasStatusText.tsx @@ -1,6 +1,6 @@ import { Box, Flex } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; -import { useAppSelector } from 'app/storeHooks'; +import { useAppSelector } from 'app/store/storeHooks'; import { canvasSelector } from 'features/canvas/store/canvasSelectors'; import { isEqual } from 'lodash'; diff --git a/invokeai/frontend/web/src/features/canvas/components/IAICanvasStatusText/IAICanvasStatusTextCursorPos.tsx b/invokeai/frontend/web/src/features/canvas/components/IAICanvasStatusText/IAICanvasStatusTextCursorPos.tsx index 2570290393..b5d6e068e2 100644 --- a/invokeai/frontend/web/src/features/canvas/components/IAICanvasStatusText/IAICanvasStatusTextCursorPos.tsx +++ b/invokeai/frontend/web/src/features/canvas/components/IAICanvasStatusText/IAICanvasStatusTextCursorPos.tsx @@ -1,6 +1,6 @@ import { Box } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; -import { useAppSelector } from 'app/storeHooks'; +import { useAppSelector } from 'app/store/storeHooks'; import { canvasSelector } from 'features/canvas/store/canvasSelectors'; import roundToHundreth from 'features/canvas/util/roundToHundreth'; import { isEqual } from 'lodash'; diff --git a/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolPreview.tsx b/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolPreview.tsx index 04ec21e57c..9aeab9b211 100644 --- a/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolPreview.tsx +++ b/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolPreview.tsx @@ -1,5 +1,5 @@ import { createSelector } from '@reduxjs/toolkit'; -import { useAppSelector } from 'app/storeHooks'; +import { useAppSelector } from 'app/store/storeHooks'; import { canvasSelector } from 'features/canvas/store/canvasSelectors'; import { rgbaColorToString } from 'features/canvas/util/colorToString'; import { GroupConfig } from 'konva/lib/Group'; diff --git a/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasBoundingBox.tsx b/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasBoundingBox.tsx index 58577f999f..7e648ae6f3 100644 --- a/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasBoundingBox.tsx +++ b/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasBoundingBox.tsx @@ -1,5 +1,5 @@ import { createSelector } from '@reduxjs/toolkit'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { roundDownToMultiple, roundToMultiple, diff --git a/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasMaskOptions.tsx b/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasMaskOptions.tsx index 70b919f4f6..639733722d 100644 --- a/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasMaskOptions.tsx +++ b/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasMaskOptions.tsx @@ -1,6 +1,6 @@ import { ButtonGroup, Flex } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIButton from 'common/components/IAIButton'; import IAICheckbox from 'common/components/IAICheckbox'; import IAIColorPicker from 'common/components/IAIColorPicker'; diff --git a/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasRedoButton.tsx b/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasRedoButton.tsx index bae875f34d..31d60bf455 100644 --- a/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasRedoButton.tsx +++ b/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasRedoButton.tsx @@ -1,5 +1,5 @@ import { createSelector } from '@reduxjs/toolkit'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIIconButton from 'common/components/IAIIconButton'; import { canvasSelector } from 'features/canvas/store/canvasSelectors'; import { activeTabNameSelector } from 'features/ui/store/uiSelectors'; diff --git a/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasSettingsButtonPopover.tsx b/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasSettingsButtonPopover.tsx index f7ed8929c7..6d2bd64afc 100644 --- a/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasSettingsButtonPopover.tsx +++ b/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasSettingsButtonPopover.tsx @@ -1,6 +1,6 @@ import { Flex } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAICheckbox from 'common/components/IAICheckbox'; import IAIIconButton from 'common/components/IAIIconButton'; import IAIPopover from 'common/components/IAIPopover'; diff --git a/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasToolChooserOptions.tsx b/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasToolChooserOptions.tsx index b8ca929c85..a6c059b28d 100644 --- a/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasToolChooserOptions.tsx +++ b/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasToolChooserOptions.tsx @@ -1,6 +1,6 @@ import { ButtonGroup, Flex } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIColorPicker from 'common/components/IAIColorPicker'; import IAIIconButton from 'common/components/IAIIconButton'; import IAIPopover from 'common/components/IAIPopover'; diff --git a/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasToolbar.tsx b/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasToolbar.tsx index 4e53039e38..1fc9a699d5 100644 --- a/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasToolbar.tsx +++ b/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasToolbar.tsx @@ -1,6 +1,6 @@ import { ButtonGroup, Flex } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIIconButton from 'common/components/IAIIconButton'; import IAISelect from 'common/components/IAISelect'; import useImageUploader from 'common/hooks/useImageUploader'; diff --git a/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasUndoButton.tsx b/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasUndoButton.tsx index e5a69f70e9..9642e5fb86 100644 --- a/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasUndoButton.tsx +++ b/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasUndoButton.tsx @@ -1,5 +1,5 @@ import { createSelector } from '@reduxjs/toolkit'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIIconButton from 'common/components/IAIIconButton'; import { canvasSelector } from 'features/canvas/store/canvasSelectors'; import { useHotkeys } from 'react-hotkeys-hook'; diff --git a/invokeai/frontend/web/src/features/canvas/hooks/useCanvasDragMove.ts b/invokeai/frontend/web/src/features/canvas/hooks/useCanvasDragMove.ts index 6a14e4ebc9..35342d5279 100644 --- a/invokeai/frontend/web/src/features/canvas/hooks/useCanvasDragMove.ts +++ b/invokeai/frontend/web/src/features/canvas/hooks/useCanvasDragMove.ts @@ -1,5 +1,5 @@ import { createSelector } from '@reduxjs/toolkit'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { canvasSelector, isStagingSelector, diff --git a/invokeai/frontend/web/src/features/canvas/hooks/useCanvasHotkeys.ts b/invokeai/frontend/web/src/features/canvas/hooks/useCanvasHotkeys.ts index d082da3ae9..9816be91cb 100644 --- a/invokeai/frontend/web/src/features/canvas/hooks/useCanvasHotkeys.ts +++ b/invokeai/frontend/web/src/features/canvas/hooks/useCanvasHotkeys.ts @@ -1,5 +1,5 @@ import { createSelector } from '@reduxjs/toolkit'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { canvasSelector, isStagingSelector, diff --git a/invokeai/frontend/web/src/features/canvas/hooks/useCanvasMouseDown.ts b/invokeai/frontend/web/src/features/canvas/hooks/useCanvasMouseDown.ts index a64faefafc..0c0e95a569 100644 --- a/invokeai/frontend/web/src/features/canvas/hooks/useCanvasMouseDown.ts +++ b/invokeai/frontend/web/src/features/canvas/hooks/useCanvasMouseDown.ts @@ -1,5 +1,5 @@ import { createSelector } from '@reduxjs/toolkit'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { canvasSelector, isStagingSelector, diff --git a/invokeai/frontend/web/src/features/canvas/hooks/useCanvasMouseMove.ts b/invokeai/frontend/web/src/features/canvas/hooks/useCanvasMouseMove.ts index 2adb02fd6d..cd083020ad 100644 --- a/invokeai/frontend/web/src/features/canvas/hooks/useCanvasMouseMove.ts +++ b/invokeai/frontend/web/src/features/canvas/hooks/useCanvasMouseMove.ts @@ -1,5 +1,5 @@ import { createSelector } from '@reduxjs/toolkit'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { canvasSelector, isStagingSelector, diff --git a/invokeai/frontend/web/src/features/canvas/hooks/useCanvasMouseOut.ts b/invokeai/frontend/web/src/features/canvas/hooks/useCanvasMouseOut.ts index edea9cfff1..fcb3b3223f 100644 --- a/invokeai/frontend/web/src/features/canvas/hooks/useCanvasMouseOut.ts +++ b/invokeai/frontend/web/src/features/canvas/hooks/useCanvasMouseOut.ts @@ -1,4 +1,4 @@ -import { useAppDispatch } from 'app/storeHooks'; +import { useAppDispatch } from 'app/store/storeHooks'; import { mouseLeftCanvas } from 'features/canvas/store/canvasSlice'; import { useCallback } from 'react'; diff --git a/invokeai/frontend/web/src/features/canvas/hooks/useCanvasMouseUp.ts b/invokeai/frontend/web/src/features/canvas/hooks/useCanvasMouseUp.ts index 0284f42a79..6ca47ac126 100644 --- a/invokeai/frontend/web/src/features/canvas/hooks/useCanvasMouseUp.ts +++ b/invokeai/frontend/web/src/features/canvas/hooks/useCanvasMouseUp.ts @@ -1,5 +1,5 @@ import { createSelector } from '@reduxjs/toolkit'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { canvasSelector, isStagingSelector, diff --git a/invokeai/frontend/web/src/features/canvas/hooks/useCanvasZoom.ts b/invokeai/frontend/web/src/features/canvas/hooks/useCanvasZoom.ts index 14f9d37d7d..3861b2151b 100644 --- a/invokeai/frontend/web/src/features/canvas/hooks/useCanvasZoom.ts +++ b/invokeai/frontend/web/src/features/canvas/hooks/useCanvasZoom.ts @@ -1,5 +1,5 @@ import { createSelector } from '@reduxjs/toolkit'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { canvasSelector } from 'features/canvas/store/canvasSelectors'; import { setStageCoordinates, diff --git a/invokeai/frontend/web/src/features/canvas/hooks/useColorUnderCursor.ts b/invokeai/frontend/web/src/features/canvas/hooks/useColorUnderCursor.ts index 00f7a2b46a..1356b24416 100644 --- a/invokeai/frontend/web/src/features/canvas/hooks/useColorUnderCursor.ts +++ b/invokeai/frontend/web/src/features/canvas/hooks/useColorUnderCursor.ts @@ -1,4 +1,4 @@ -import { useAppDispatch } from 'app/storeHooks'; +import { useAppDispatch } from 'app/store/storeHooks'; import Konva from 'konva'; import { commitColorPickerColor, diff --git a/invokeai/frontend/web/src/features/canvas/store/canvasSelectors.ts b/invokeai/frontend/web/src/features/canvas/store/canvasSelectors.ts index 3f81f71fad..dbcdde00d5 100644 --- a/invokeai/frontend/web/src/features/canvas/store/canvasSelectors.ts +++ b/invokeai/frontend/web/src/features/canvas/store/canvasSelectors.ts @@ -1,5 +1,5 @@ import { createSelector } from '@reduxjs/toolkit'; -import { RootState } from 'app/store'; +import { RootState } from 'app/store/store'; import { systemSelector } from 'features/system/store/systemSelectors'; import { activeTabNameSelector } from 'features/ui/store/uiSelectors'; import { CanvasImage, CanvasState, isCanvasBaseImage } from './canvasTypes'; diff --git a/invokeai/frontend/web/src/features/canvas/store/canvasSlice.ts b/invokeai/frontend/web/src/features/canvas/store/canvasSlice.ts index 34688ef659..e277ccdef2 100644 --- a/invokeai/frontend/web/src/features/canvas/store/canvasSlice.ts +++ b/invokeai/frontend/web/src/features/canvas/store/canvasSlice.ts @@ -1,6 +1,6 @@ import type { PayloadAction } from '@reduxjs/toolkit'; import { createSlice } from '@reduxjs/toolkit'; -import * as InvokeAI from 'app/invokeai'; +import * as InvokeAI from 'app/types/invokeai'; import { roundDownToMultiple, roundToMultiple, diff --git a/invokeai/frontend/web/src/features/canvas/store/canvasTypes.ts b/invokeai/frontend/web/src/features/canvas/store/canvasTypes.ts index 95cf573c3b..2eec0e9bed 100644 --- a/invokeai/frontend/web/src/features/canvas/store/canvasTypes.ts +++ b/invokeai/frontend/web/src/features/canvas/store/canvasTypes.ts @@ -1,4 +1,4 @@ -import * as InvokeAI from 'app/invokeai'; +import * as InvokeAI from 'app/types/invokeai'; import { IRect, Vector2d } from 'konva/lib/types'; import { RgbaColor } from 'react-colorful'; diff --git a/invokeai/frontend/web/src/features/canvas/store/thunks/mergeAndUploadCanvas.ts b/invokeai/frontend/web/src/features/canvas/store/thunks/mergeAndUploadCanvas.ts index a1a7bd3989..d9feba63d3 100644 --- a/invokeai/frontend/web/src/features/canvas/store/thunks/mergeAndUploadCanvas.ts +++ b/invokeai/frontend/web/src/features/canvas/store/thunks/mergeAndUploadCanvas.ts @@ -1,6 +1,6 @@ import { AnyAction, ThunkAction } from '@reduxjs/toolkit'; -import * as InvokeAI from 'app/invokeai'; -import { RootState } from 'app/store'; +import * as InvokeAI from 'app/types/invokeai'; +import { RootState } from 'app/store/store'; import { addImage } from 'features/gallery/store/gallerySlice'; import { addToast, diff --git a/invokeai/frontend/web/src/features/canvas/store/thunks/requestCanvasScale.ts b/invokeai/frontend/web/src/features/canvas/store/thunks/requestCanvasScale.ts index d592c3c14c..e6efbb979b 100644 --- a/invokeai/frontend/web/src/features/canvas/store/thunks/requestCanvasScale.ts +++ b/invokeai/frontend/web/src/features/canvas/store/thunks/requestCanvasScale.ts @@ -1,4 +1,4 @@ -import { AppDispatch, AppGetState } from 'app/store'; +import { AppDispatch, AppGetState } from 'app/store/store'; import { activeTabNameSelector } from 'features/ui/store/uiSelectors'; import { debounce } from 'lodash'; import { setDoesCanvasNeedScaling } from '../canvasSlice'; diff --git a/invokeai/frontend/web/src/features/gallery/components/CurrentImageButtons.tsx b/invokeai/frontend/web/src/features/gallery/components/CurrentImageButtons.tsx index 462982b91d..10b6d55ec7 100644 --- a/invokeai/frontend/web/src/features/gallery/components/CurrentImageButtons.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/CurrentImageButtons.tsx @@ -11,7 +11,7 @@ import { useToast, } from '@chakra-ui/react'; import { runESRGAN, runFacetool } from 'app/socketio/actions'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIButton from 'common/components/IAIButton'; import IAIIconButton from 'common/components/IAIIconButton'; import IAIPopover from 'common/components/IAIPopover'; diff --git a/invokeai/frontend/web/src/features/gallery/components/CurrentImageDisplay.tsx b/invokeai/frontend/web/src/features/gallery/components/CurrentImageDisplay.tsx index bba9666ffa..ee849a95d2 100644 --- a/invokeai/frontend/web/src/features/gallery/components/CurrentImageDisplay.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/CurrentImageDisplay.tsx @@ -1,6 +1,6 @@ import { Flex, Icon } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; -import { useAppSelector } from 'app/storeHooks'; +import { useAppSelector } from 'app/store/storeHooks'; import { systemSelector } from 'features/system/store/systemSelectors'; import { isEqual } from 'lodash'; diff --git a/invokeai/frontend/web/src/features/gallery/components/CurrentImagePreview.tsx b/invokeai/frontend/web/src/features/gallery/components/CurrentImagePreview.tsx index 67b5fc8b16..8ee0829190 100644 --- a/invokeai/frontend/web/src/features/gallery/components/CurrentImagePreview.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/CurrentImagePreview.tsx @@ -1,6 +1,6 @@ import { Box, Flex, Image } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; -import { useAppSelector } from 'app/storeHooks'; +import { useAppSelector } from 'app/store/storeHooks'; import { useGetUrl } from 'common/util/getUrl'; import { systemSelector } from 'features/system/store/systemSelectors'; import { uiSelector } from 'features/ui/store/uiSelectors'; diff --git a/invokeai/frontend/web/src/features/gallery/components/DeleteImageModal.tsx b/invokeai/frontend/web/src/features/gallery/components/DeleteImageModal.tsx index 35effd95be..1f74706ede 100644 --- a/invokeai/frontend/web/src/features/gallery/components/DeleteImageModal.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/DeleteImageModal.tsx @@ -9,7 +9,7 @@ import { Text, } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIButton from 'common/components/IAIButton'; import IAISwitch from 'common/components/IAISwitch'; import { configSelector } from 'features/system/store/configSelectors'; diff --git a/invokeai/frontend/web/src/features/gallery/components/HoverableImage.tsx b/invokeai/frontend/web/src/features/gallery/components/HoverableImage.tsx index 659b59c91d..491ca371d3 100644 --- a/invokeai/frontend/web/src/features/gallery/components/HoverableImage.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/HoverableImage.tsx @@ -10,7 +10,7 @@ import { useTheme, useToast, } from '@chakra-ui/react'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { imageSelected, setCurrentImage, @@ -32,7 +32,7 @@ import { } from 'react-icons/fa'; import DeleteImageModal from './DeleteImageModal'; import { ContextMenu } from 'chakra-ui-contextmenu'; -import * as InvokeAI from 'app/invokeai'; +import * as InvokeAI from 'app/types/invokeai'; import { resizeAndScaleCanvas, setInitialCanvasImage, diff --git a/invokeai/frontend/web/src/features/gallery/components/ImageGallery.tsx b/invokeai/frontend/web/src/features/gallery/components/ImageGallery.tsx index dbd621aa83..b3998649a5 100644 --- a/invokeai/frontend/web/src/features/gallery/components/ImageGallery.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/ImageGallery.tsx @@ -10,7 +10,7 @@ // useTheme, // } from '@chakra-ui/react'; // import { requestImages } from 'app/socketio/actions'; -// import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +// import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; // import IAIButton from 'common/components/IAIButton'; // import IAICheckbox from 'common/components/IAICheckbox'; // import IAIIconButton from 'common/components/IAIIconButton'; diff --git a/invokeai/frontend/web/src/features/gallery/components/ImageGalleryContent.tsx b/invokeai/frontend/web/src/features/gallery/components/ImageGalleryContent.tsx index 327326a403..1b57dbea78 100644 --- a/invokeai/frontend/web/src/features/gallery/components/ImageGalleryContent.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/ImageGalleryContent.tsx @@ -1,6 +1,6 @@ import { ButtonGroup, Flex, Grid, Icon, Image, Text } from '@chakra-ui/react'; import { requestImages } from 'app/socketio/actions'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIButton from 'common/components/IAIButton'; import IAICheckbox from 'common/components/IAICheckbox'; import IAIIconButton from 'common/components/IAIIconButton'; @@ -36,7 +36,7 @@ import { } from 'services/thunks/gallery'; import { selectUploadsAll, uploadsAdapter } from '../store/uploadsSlice'; import { createSelector } from '@reduxjs/toolkit'; -import { RootState } from 'app/store'; +import { RootState } from 'app/store/store'; const GALLERY_SHOW_BUTTONS_MIN_WIDTH = 290; diff --git a/invokeai/frontend/web/src/features/gallery/components/ImageGalleryPanel.tsx b/invokeai/frontend/web/src/features/gallery/components/ImageGalleryPanel.tsx index 2a557240ef..2a48a7a5dc 100644 --- a/invokeai/frontend/web/src/features/gallery/components/ImageGalleryPanel.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/ImageGalleryPanel.tsx @@ -1,4 +1,4 @@ -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { gallerySelector } from 'features/gallery/store/gallerySelectors'; import { selectNextImage, diff --git a/invokeai/frontend/web/src/features/gallery/components/ImageMetaDataViewer/ImageMetadataViewer.tsx b/invokeai/frontend/web/src/features/gallery/components/ImageMetaDataViewer/ImageMetadataViewer.tsx index 1909dc56a7..073521344d 100644 --- a/invokeai/frontend/web/src/features/gallery/components/ImageMetaDataViewer/ImageMetadataViewer.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/ImageMetaDataViewer/ImageMetadataViewer.tsx @@ -9,8 +9,8 @@ import { Text, Tooltip, } from '@chakra-ui/react'; -import * as InvokeAI from 'app/invokeai'; -import { useAppDispatch } from 'app/storeHooks'; +import * as InvokeAI from 'app/types/invokeai'; +import { useAppDispatch } from 'app/store/storeHooks'; import { useGetUrl } from 'common/util/getUrl'; import promptToString from 'common/util/promptToString'; import { seedWeightsToString } from 'common/util/seedWeightPairs'; diff --git a/invokeai/frontend/web/src/features/gallery/components/ImageMetaDataViewer/OLD_ImageMetadataViewer.tsx b/invokeai/frontend/web/src/features/gallery/components/ImageMetaDataViewer/OLD_ImageMetadataViewer.tsx index 3339140a52..c76ee7f078 100644 --- a/invokeai/frontend/web/src/features/gallery/components/ImageMetaDataViewer/OLD_ImageMetadataViewer.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/ImageMetaDataViewer/OLD_ImageMetadataViewer.tsx @@ -9,8 +9,8 @@ import { Text, Tooltip, } from '@chakra-ui/react'; -import * as InvokeAI from 'app/invokeai'; -import { useAppDispatch } from 'app/storeHooks'; +import * as InvokeAI from 'app/types/invokeai'; +import { useAppDispatch } from 'app/store/storeHooks'; import { useGetUrl } from 'common/util/getUrl'; import promptToString from 'common/util/promptToString'; import { seedWeightsToString } from 'common/util/seedWeightPairs'; diff --git a/invokeai/frontend/web/src/features/gallery/components/NextPrevImageButtons.tsx b/invokeai/frontend/web/src/features/gallery/components/NextPrevImageButtons.tsx index 2da7579fd9..eb94a5b25e 100644 --- a/invokeai/frontend/web/src/features/gallery/components/NextPrevImageButtons.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/NextPrevImageButtons.tsx @@ -1,6 +1,6 @@ import { ChakraProps, Flex, Grid, IconButton } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { isEqual } from 'lodash'; import { useState } from 'react'; import { useTranslation } from 'react-i18next'; diff --git a/invokeai/frontend/web/src/features/gallery/hooks/useGetImageByName.ts b/invokeai/frontend/web/src/features/gallery/hooks/useGetImageByName.ts index b662cf02c1..d15c3fb51f 100644 --- a/invokeai/frontend/web/src/features/gallery/hooks/useGetImageByName.ts +++ b/invokeai/frontend/web/src/features/gallery/hooks/useGetImageByName.ts @@ -1,5 +1,5 @@ import { createSelector } from '@reduxjs/toolkit'; -import { useAppSelector } from 'app/storeHooks'; +import { useAppSelector } from 'app/store/storeHooks'; import { ImageType } from 'services/api'; import { selectResultsEntities } from '../store/resultsSlice'; import { selectUploadsEntities } from '../store/uploadsSlice'; diff --git a/invokeai/frontend/web/src/features/gallery/hooks/useGetImageByUuid.ts b/invokeai/frontend/web/src/features/gallery/hooks/useGetImageByUuid.ts index 1c7c43ac70..27b2635e31 100644 --- a/invokeai/frontend/web/src/features/gallery/hooks/useGetImageByUuid.ts +++ b/invokeai/frontend/web/src/features/gallery/hooks/useGetImageByUuid.ts @@ -1,5 +1,5 @@ import { createSelector } from '@reduxjs/toolkit'; -import { useAppSelector } from 'app/storeHooks'; +import { useAppSelector } from 'app/store/storeHooks'; import { gallerySelector } from '../store/gallerySelectors'; const selector = createSelector(gallerySelector, (gallery) => ({ diff --git a/invokeai/frontend/web/src/features/gallery/store/gallerySelectors.ts b/invokeai/frontend/web/src/features/gallery/store/gallerySelectors.ts index 48ef22fd14..73b0a2ef0b 100644 --- a/invokeai/frontend/web/src/features/gallery/store/gallerySelectors.ts +++ b/invokeai/frontend/web/src/features/gallery/store/gallerySelectors.ts @@ -1,5 +1,5 @@ import { createSelector } from '@reduxjs/toolkit'; -import { RootState } from 'app/store'; +import { RootState } from 'app/store/store'; import { lightboxSelector } from 'features/lightbox/store/lightboxSelectors'; import { configSelector } from 'features/system/store/configSelectors'; import { systemSelector } from 'features/system/store/systemSelectors'; diff --git a/invokeai/frontend/web/src/features/gallery/store/gallerySlice.ts b/invokeai/frontend/web/src/features/gallery/store/gallerySlice.ts index d0336379fc..5cecf778b6 100644 --- a/invokeai/frontend/web/src/features/gallery/store/gallerySlice.ts +++ b/invokeai/frontend/web/src/features/gallery/store/gallerySlice.ts @@ -1,6 +1,6 @@ import type { PayloadAction } from '@reduxjs/toolkit'; import { createSlice } from '@reduxjs/toolkit'; -import * as InvokeAI from 'app/invokeai'; +import * as InvokeAI from 'app/types/invokeai'; import { invocationComplete } from 'services/events/actions'; import { InvokeTabName } from 'features/ui/store/tabMap'; import { IRect } from 'konva/lib/types'; diff --git a/invokeai/frontend/web/src/features/gallery/store/resultsSlice.ts b/invokeai/frontend/web/src/features/gallery/store/resultsSlice.ts index e4b89144f4..73da68c031 100644 --- a/invokeai/frontend/web/src/features/gallery/store/resultsSlice.ts +++ b/invokeai/frontend/web/src/features/gallery/store/resultsSlice.ts @@ -1,8 +1,8 @@ import { createEntityAdapter, createSlice } from '@reduxjs/toolkit'; -import { Image } from 'app/invokeai'; +import { Image } from 'app/types/invokeai'; import { invocationComplete } from 'services/events/actions'; -import { RootState } from 'app/store'; +import { RootState } from 'app/store/store'; import { receivedResultImagesPage, IMAGES_PER_PAGE, diff --git a/invokeai/frontend/web/src/features/gallery/store/uploadsSlice.ts b/invokeai/frontend/web/src/features/gallery/store/uploadsSlice.ts index e2d21d3afd..04d321d7d9 100644 --- a/invokeai/frontend/web/src/features/gallery/store/uploadsSlice.ts +++ b/invokeai/frontend/web/src/features/gallery/store/uploadsSlice.ts @@ -1,7 +1,7 @@ import { createEntityAdapter, createSlice } from '@reduxjs/toolkit'; -import { Image } from 'app/invokeai'; +import { Image } from 'app/types/invokeai'; -import { RootState } from 'app/store'; +import { RootState } from 'app/store/store'; import { receivedUploadImagesPage, IMAGES_PER_PAGE, diff --git a/invokeai/frontend/web/src/features/lightbox/components/Lightbox.tsx b/invokeai/frontend/web/src/features/lightbox/components/Lightbox.tsx index 9ca4196fa3..4fa70e4a53 100644 --- a/invokeai/frontend/web/src/features/lightbox/components/Lightbox.tsx +++ b/invokeai/frontend/web/src/features/lightbox/components/Lightbox.tsx @@ -1,7 +1,7 @@ import { Box, Flex } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; -import { RootState } from 'app/store'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIIconButton from 'common/components/IAIIconButton'; import CurrentImageButtons from 'features/gallery/components/CurrentImageButtons'; import ImageMetadataViewer from 'features/gallery/components/ImageMetaDataViewer/ImageMetadataViewer'; diff --git a/invokeai/frontend/web/src/features/lightbox/components/ReactPanZoomImage.tsx b/invokeai/frontend/web/src/features/lightbox/components/ReactPanZoomImage.tsx index 660b07d75f..1eea014dfd 100644 --- a/invokeai/frontend/web/src/features/lightbox/components/ReactPanZoomImage.tsx +++ b/invokeai/frontend/web/src/features/lightbox/components/ReactPanZoomImage.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import { TransformComponent, useTransformContext } from 'react-zoom-pan-pinch'; -import * as InvokeAI from 'app/invokeai'; +import * as InvokeAI from 'app/types/invokeai'; import { useGetUrl } from 'common/util/getUrl'; type ReactPanZoomProps = { diff --git a/invokeai/frontend/web/src/features/lightbox/store/lightboxSelectors.ts b/invokeai/frontend/web/src/features/lightbox/store/lightboxSelectors.ts index 10ee245866..afaf1ae398 100644 --- a/invokeai/frontend/web/src/features/lightbox/store/lightboxSelectors.ts +++ b/invokeai/frontend/web/src/features/lightbox/store/lightboxSelectors.ts @@ -1,5 +1,5 @@ import { createSelector } from '@reduxjs/toolkit'; -import { RootState } from 'app/store'; +import { RootState } from 'app/store/store'; import { isEqual } from 'lodash'; export const lightboxSelector = createSelector( diff --git a/invokeai/frontend/web/src/features/nodes/components/AddNodeMenu.tsx b/invokeai/frontend/web/src/features/nodes/components/AddNodeMenu.tsx index 5acd0c0530..8fb14c7a23 100644 --- a/invokeai/frontend/web/src/features/nodes/components/AddNodeMenu.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/AddNodeMenu.tsx @@ -11,15 +11,15 @@ import { IconButton, } from '@chakra-ui/react'; import { FaEllipsisV, FaPlus } from 'react-icons/fa'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { nodeAdded } from '../store/nodesSlice'; import { cloneDeep, map } from 'lodash'; -import { RootState } from 'app/store'; +import { RootState } from 'app/store/store'; import { useBuildInvocation } from '../hooks/useBuildInvocation'; import { addToast } from 'features/system/store/systemSlice'; import { makeToast } from 'features/system/hooks/useToastWatcher'; -import { IAIIconButton } from 'exports'; import { AnyInvocationType } from 'services/events/types'; +import IAIIconButton from 'common/components/IAIIconButton'; const AddNodeMenu = () => { const dispatch = useAppDispatch(); diff --git a/invokeai/frontend/web/src/features/nodes/components/Flow.tsx b/invokeai/frontend/web/src/features/nodes/components/Flow.tsx index 5c433ad488..4554f334c2 100644 --- a/invokeai/frontend/web/src/features/nodes/components/Flow.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/Flow.tsx @@ -7,8 +7,8 @@ import { OnConnectStart, OnConnectEnd, } from 'reactflow'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; -import { RootState } from 'app/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; +import { RootState } from 'app/store/store'; import { connectionEnded, connectionMade, diff --git a/invokeai/frontend/web/src/features/nodes/components/IAINode/IAINodeInputs.tsx b/invokeai/frontend/web/src/features/nodes/components/IAINode/IAINodeInputs.tsx index 6d47cad919..ee8a21ec86 100644 --- a/invokeai/frontend/web/src/features/nodes/components/IAINode/IAINodeInputs.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/IAINode/IAINodeInputs.tsx @@ -5,8 +5,8 @@ import { } from 'features/nodes/types/types'; import { memo, ReactNode, useCallback } from 'react'; import { map } from 'lodash'; -import { useAppSelector } from 'app/storeHooks'; -import { RootState } from 'app/store'; +import { useAppSelector } from 'app/store/storeHooks'; +import { RootState } from 'app/store/store'; import { Box, Flex, diff --git a/invokeai/frontend/web/src/features/nodes/components/IAINode/IAINodeOutputs.tsx b/invokeai/frontend/web/src/features/nodes/components/IAINode/IAINodeOutputs.tsx index 38a3a169b8..e4eaa27bc9 100644 --- a/invokeai/frontend/web/src/features/nodes/components/IAINode/IAINodeOutputs.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/IAINode/IAINodeOutputs.tsx @@ -5,8 +5,8 @@ import { } from 'features/nodes/types/types'; import { memo, ReactNode, useCallback } from 'react'; import { map } from 'lodash'; -import { useAppSelector } from 'app/storeHooks'; -import { RootState } from 'app/store'; +import { useAppSelector } from 'app/store/storeHooks'; +import { RootState } from 'app/store/store'; import { Box, Flex, FormControl, FormLabel, HStack } from '@chakra-ui/react'; import FieldHandle from '../FieldHandle'; import { useIsValidConnection } from 'features/nodes/hooks/useIsValidConnection'; diff --git a/invokeai/frontend/web/src/features/nodes/components/InvocationComponent.tsx b/invokeai/frontend/web/src/features/nodes/components/InvocationComponent.tsx index e6d54a72c5..909fd4b556 100644 --- a/invokeai/frontend/web/src/features/nodes/components/InvocationComponent.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/InvocationComponent.tsx @@ -8,10 +8,10 @@ import IAINodeOutputs from './IAINode/IAINodeOutputs'; import IAINodeInputs from './IAINode/IAINodeInputs'; import IAINodeHeader from './IAINode/IAINodeHeader'; import IAINodeResizer from './IAINode/IAINodeResizer'; -import { RootState } from 'app/store'; +import { RootState } from 'app/store/store'; import { AnyInvocationType } from 'services/events/types'; import { createSelector } from '@reduxjs/toolkit'; -import { useAppSelector } from 'app/storeHooks'; +import { useAppSelector } from 'app/store/storeHooks'; import { NODE_MIN_WIDTH } from 'app/constants'; type InvocationComponentWrapperProps = PropsWithChildren & { diff --git a/invokeai/frontend/web/src/features/nodes/components/NodeGraphOverlay.tsx b/invokeai/frontend/web/src/features/nodes/components/NodeGraphOverlay.tsx index 88a125e542..90c8e1396f 100644 --- a/invokeai/frontend/web/src/features/nodes/components/NodeGraphOverlay.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/NodeGraphOverlay.tsx @@ -1,6 +1,6 @@ import { Box } from '@chakra-ui/react'; -import { RootState } from 'app/store'; -import { useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppSelector } from 'app/store/storeHooks'; import { memo } from 'react'; import { buildNodesGraph } from '../util/nodesGraphBuilder/buildNodesGraph'; diff --git a/invokeai/frontend/web/src/features/nodes/components/ViewportControls.tsx b/invokeai/frontend/web/src/features/nodes/components/ViewportControls.tsx index 249e8d4c78..5f688722de 100644 --- a/invokeai/frontend/web/src/features/nodes/components/ViewportControls.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/ViewportControls.tsx @@ -1,6 +1,6 @@ import { ButtonGroup } from '@chakra-ui/react'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; -import { IAIIconButton } from 'exports'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; +import IAIIconButton from 'common/components/IAIIconButton'; import { memo, useCallback } from 'react'; import { FaCode, FaExpand, FaMinus, FaPlus } from 'react-icons/fa'; import { useReactFlow } from 'reactflow'; diff --git a/invokeai/frontend/web/src/features/nodes/components/fields/BooleanInputFieldComponent.tsx b/invokeai/frontend/web/src/features/nodes/components/fields/BooleanInputFieldComponent.tsx index ceb2364e46..52a60253ba 100644 --- a/invokeai/frontend/web/src/features/nodes/components/fields/BooleanInputFieldComponent.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/fields/BooleanInputFieldComponent.tsx @@ -1,5 +1,5 @@ import { Switch } from '@chakra-ui/react'; -import { useAppDispatch } from 'app/storeHooks'; +import { useAppDispatch } from 'app/store/storeHooks'; import { fieldValueChanged } from 'features/nodes/store/nodesSlice'; import { BooleanInputFieldTemplate, diff --git a/invokeai/frontend/web/src/features/nodes/components/fields/EnumInputFieldComponent.tsx b/invokeai/frontend/web/src/features/nodes/components/fields/EnumInputFieldComponent.tsx index 15602e7cad..5f26bc4f2a 100644 --- a/invokeai/frontend/web/src/features/nodes/components/fields/EnumInputFieldComponent.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/fields/EnumInputFieldComponent.tsx @@ -1,5 +1,5 @@ import { Select } from '@chakra-ui/react'; -import { useAppDispatch } from 'app/storeHooks'; +import { useAppDispatch } from 'app/store/storeHooks'; import { fieldValueChanged } from 'features/nodes/store/nodesSlice'; import { EnumInputFieldTemplate, diff --git a/invokeai/frontend/web/src/features/nodes/components/fields/ImageInputFieldComponent.tsx b/invokeai/frontend/web/src/features/nodes/components/fields/ImageInputFieldComponent.tsx index 1dc0296139..74967c20d8 100644 --- a/invokeai/frontend/web/src/features/nodes/components/fields/ImageInputFieldComponent.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/fields/ImageInputFieldComponent.tsx @@ -1,5 +1,5 @@ import { Box, Image, Icon, Flex } from '@chakra-ui/react'; -import { useAppDispatch } from 'app/storeHooks'; +import { useAppDispatch } from 'app/store/storeHooks'; import SelectImagePlaceholder from 'common/components/SelectImagePlaceholder'; import { useGetUrl } from 'common/util/getUrl'; import useGetImageByNameAndType from 'features/gallery/hooks/useGetImageByName'; diff --git a/invokeai/frontend/web/src/features/nodes/components/fields/ModelInputFieldComponent.tsx b/invokeai/frontend/web/src/features/nodes/components/fields/ModelInputFieldComponent.tsx index 14f2816e1c..6861520eb5 100644 --- a/invokeai/frontend/web/src/features/nodes/components/fields/ModelInputFieldComponent.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/fields/ModelInputFieldComponent.tsx @@ -1,7 +1,7 @@ import { Select } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; -import { RootState } from 'app/store'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { fieldValueChanged } from 'features/nodes/store/nodesSlice'; import { ModelInputFieldTemplate, diff --git a/invokeai/frontend/web/src/features/nodes/components/fields/NumberInputFieldComponent.tsx b/invokeai/frontend/web/src/features/nodes/components/fields/NumberInputFieldComponent.tsx index ad59667419..f5df8989f5 100644 --- a/invokeai/frontend/web/src/features/nodes/components/fields/NumberInputFieldComponent.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/fields/NumberInputFieldComponent.tsx @@ -5,7 +5,7 @@ import { NumberInputField, NumberInputStepper, } from '@chakra-ui/react'; -import { useAppDispatch } from 'app/storeHooks'; +import { useAppDispatch } from 'app/store/storeHooks'; import { fieldValueChanged } from 'features/nodes/store/nodesSlice'; import { FloatInputFieldTemplate, diff --git a/invokeai/frontend/web/src/features/nodes/components/fields/StringInputFieldComponent.tsx b/invokeai/frontend/web/src/features/nodes/components/fields/StringInputFieldComponent.tsx index f371e8e58d..58a201062b 100644 --- a/invokeai/frontend/web/src/features/nodes/components/fields/StringInputFieldComponent.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/fields/StringInputFieldComponent.tsx @@ -1,5 +1,5 @@ import { Input } from '@chakra-ui/react'; -import { useAppDispatch } from 'app/storeHooks'; +import { useAppDispatch } from 'app/store/storeHooks'; import { fieldValueChanged } from 'features/nodes/store/nodesSlice'; import { StringInputFieldTemplate, diff --git a/invokeai/frontend/web/src/features/nodes/components/panels/MinimapPanel.tsx b/invokeai/frontend/web/src/features/nodes/components/panels/MinimapPanel.tsx index 33c5605310..2d76e2911f 100644 --- a/invokeai/frontend/web/src/features/nodes/components/panels/MinimapPanel.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/panels/MinimapPanel.tsx @@ -1,5 +1,5 @@ -import { RootState } from 'app/store'; -import { useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppSelector } from 'app/store/storeHooks'; import { CSSProperties, memo } from 'react'; import { MiniMap } from 'reactflow'; diff --git a/invokeai/frontend/web/src/features/nodes/components/panels/TopCenterPanel.tsx b/invokeai/frontend/web/src/features/nodes/components/panels/TopCenterPanel.tsx index 1d007e3657..4bb7abf982 100644 --- a/invokeai/frontend/web/src/features/nodes/components/panels/TopCenterPanel.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/panels/TopCenterPanel.tsx @@ -1,5 +1,5 @@ import { HStack } from '@chakra-ui/react'; -import { useAppDispatch } from 'app/storeHooks'; +import { useAppDispatch } from 'app/store/storeHooks'; import IAIButton from 'common/components/IAIButton'; import { memo, useCallback } from 'react'; import { Panel } from 'reactflow'; diff --git a/invokeai/frontend/web/src/features/nodes/components/panels/TopRightPanel.tsx b/invokeai/frontend/web/src/features/nodes/components/panels/TopRightPanel.tsx index 7e51e3e00e..3fe8c49880 100644 --- a/invokeai/frontend/web/src/features/nodes/components/panels/TopRightPanel.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/panels/TopRightPanel.tsx @@ -1,5 +1,5 @@ -import { RootState } from 'app/store'; -import { useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppSelector } from 'app/store/storeHooks'; import { memo } from 'react'; import { Panel } from 'reactflow'; import FieldTypeLegend from '../FieldTypeLegend'; diff --git a/invokeai/frontend/web/src/features/nodes/components/search/NodeSearch.tsx b/invokeai/frontend/web/src/features/nodes/components/search/NodeSearch.tsx index c301a1a863..eaf665f0ec 100644 --- a/invokeai/frontend/web/src/features/nodes/components/search/NodeSearch.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/search/NodeSearch.tsx @@ -1,6 +1,6 @@ import { Box, Flex } from '@chakra-ui/layout'; -import { RootState } from 'app/store'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIInput from 'common/components/IAIInput'; import { Panel } from 'reactflow'; import { map } from 'lodash'; diff --git a/invokeai/frontend/web/src/features/nodes/hooks/useBuildInvocation.ts b/invokeai/frontend/web/src/features/nodes/hooks/useBuildInvocation.ts index a44f703364..7620113829 100644 --- a/invokeai/frontend/web/src/features/nodes/hooks/useBuildInvocation.ts +++ b/invokeai/frontend/web/src/features/nodes/hooks/useBuildInvocation.ts @@ -1,6 +1,6 @@ import { createSelector } from '@reduxjs/toolkit'; -import { RootState } from 'app/store'; -import { useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppSelector } from 'app/store/storeHooks'; import { reduce } from 'lodash'; import { useCallback } from 'react'; import { Node, useReactFlow } from 'reactflow'; diff --git a/invokeai/frontend/web/src/features/nodes/store/selectors/invocationTemplatesSelector.ts b/invokeai/frontend/web/src/features/nodes/store/selectors/invocationTemplatesSelector.ts index 0ffc4ac5bb..803cdbfb74 100644 --- a/invokeai/frontend/web/src/features/nodes/store/selectors/invocationTemplatesSelector.ts +++ b/invokeai/frontend/web/src/features/nodes/store/selectors/invocationTemplatesSelector.ts @@ -1,5 +1,5 @@ import { createSelector } from '@reduxjs/toolkit'; -import { RootState } from 'app/store'; +import { RootState } from 'app/store/store'; export const invocationTemplatesSelector = createSelector( (state: RootState) => state.nodes, diff --git a/invokeai/frontend/web/src/features/nodes/util/linearGraphBuilder/buildImageToImageNode.ts b/invokeai/frontend/web/src/features/nodes/util/linearGraphBuilder/buildImageToImageNode.ts index 1219e969af..f9213dfeae 100644 --- a/invokeai/frontend/web/src/features/nodes/util/linearGraphBuilder/buildImageToImageNode.ts +++ b/invokeai/frontend/web/src/features/nodes/util/linearGraphBuilder/buildImageToImageNode.ts @@ -1,11 +1,11 @@ import { v4 as uuidv4 } from 'uuid'; -import { RootState } from 'app/store'; +import { RootState } from 'app/store/store'; import { Edge, ImageToImageInvocation, TextToImageInvocation, } from 'services/api'; -import { _Image } from 'app/invokeai'; +import { _Image } from 'app/types/invokeai'; import { initialImageSelector } from 'features/parameters/store/generationSelectors'; export const buildImg2ImgNode = (state: RootState): ImageToImageInvocation => { diff --git a/invokeai/frontend/web/src/features/nodes/util/linearGraphBuilder/buildLinearGraph.ts b/invokeai/frontend/web/src/features/nodes/util/linearGraphBuilder/buildLinearGraph.ts index 9667dfa2b3..3e638c8239 100644 --- a/invokeai/frontend/web/src/features/nodes/util/linearGraphBuilder/buildLinearGraph.ts +++ b/invokeai/frontend/web/src/features/nodes/util/linearGraphBuilder/buildLinearGraph.ts @@ -1,4 +1,4 @@ -import { RootState } from 'app/store'; +import { RootState } from 'app/store/store'; import { Graph } from 'services/api'; import { buildImg2ImgNode } from './buildImageToImageNode'; import { buildTxt2ImgNode } from './buildTextToImageNode'; diff --git a/invokeai/frontend/web/src/features/nodes/util/linearGraphBuilder/buildRangeNode.ts b/invokeai/frontend/web/src/features/nodes/util/linearGraphBuilder/buildRangeNode.ts index 1f87ec785e..735c0ef726 100644 --- a/invokeai/frontend/web/src/features/nodes/util/linearGraphBuilder/buildRangeNode.ts +++ b/invokeai/frontend/web/src/features/nodes/util/linearGraphBuilder/buildRangeNode.ts @@ -1,6 +1,6 @@ import { v4 as uuidv4 } from 'uuid'; -import { RootState } from 'app/store'; +import { RootState } from 'app/store/store'; import { RandomRangeInvocation, RangeInvocation } from 'services/api'; export const buildRangeNode = ( diff --git a/invokeai/frontend/web/src/features/nodes/util/linearGraphBuilder/buildTextToImageNode.ts b/invokeai/frontend/web/src/features/nodes/util/linearGraphBuilder/buildTextToImageNode.ts index a8c65004c7..08952bcfb1 100644 --- a/invokeai/frontend/web/src/features/nodes/util/linearGraphBuilder/buildTextToImageNode.ts +++ b/invokeai/frontend/web/src/features/nodes/util/linearGraphBuilder/buildTextToImageNode.ts @@ -1,5 +1,5 @@ import { v4 as uuidv4 } from 'uuid'; -import { RootState } from 'app/store'; +import { RootState } from 'app/store/store'; import { TextToImageInvocation } from 'services/api'; export const buildTxt2ImgNode = (state: RootState): TextToImageInvocation => { diff --git a/invokeai/frontend/web/src/features/nodes/util/nodesGraphBuilder/buildNodesGraph.ts b/invokeai/frontend/web/src/features/nodes/util/nodesGraphBuilder/buildNodesGraph.ts index 848615277d..c473695ade 100644 --- a/invokeai/frontend/web/src/features/nodes/util/nodesGraphBuilder/buildNodesGraph.ts +++ b/invokeai/frontend/web/src/features/nodes/util/nodesGraphBuilder/buildNodesGraph.ts @@ -1,7 +1,7 @@ import { Graph } from 'services/api'; import { v4 as uuidv4 } from 'uuid'; import { reduce } from 'lodash'; -import { RootState } from 'app/store'; +import { RootState } from 'app/store/store'; import { AnyInvocation } from 'services/events/types'; /** diff --git a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Canvas/BoundingBox/BoundingBoxSettings.tsx b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Canvas/BoundingBox/BoundingBoxSettings.tsx index 67740cbc02..6e753b002a 100644 --- a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Canvas/BoundingBox/BoundingBoxSettings.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Canvas/BoundingBox/BoundingBoxSettings.tsx @@ -1,6 +1,6 @@ import { Box, VStack } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAISlider from 'common/components/IAISlider'; import { canvasSelector } from 'features/canvas/store/canvasSelectors'; import { setBoundingBoxDimensions } from 'features/canvas/store/canvasSlice'; diff --git a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Canvas/InfillAndScalingSettings.tsx b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Canvas/InfillAndScalingSettings.tsx index 866038c993..d58ff4746b 100644 --- a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Canvas/InfillAndScalingSettings.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Canvas/InfillAndScalingSettings.tsx @@ -1,6 +1,6 @@ import { VStack } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAISelect from 'common/components/IAISelect'; import IAISlider from 'common/components/IAISlider'; import { canvasSelector } from 'features/canvas/store/canvasSelectors'; diff --git a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Canvas/SeamCorrection/SeamBlur.tsx b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Canvas/SeamCorrection/SeamBlur.tsx index 1f5237615a..693313e606 100644 --- a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Canvas/SeamCorrection/SeamBlur.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Canvas/SeamCorrection/SeamBlur.tsx @@ -1,5 +1,5 @@ -import type { RootState } from 'app/store'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import type { RootState } from 'app/store/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAISlider from 'common/components/IAISlider'; import { setSeamBlur } from 'features/parameters/store/generationSlice'; import { useTranslation } from 'react-i18next'; diff --git a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Canvas/SeamCorrection/SeamSize.tsx b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Canvas/SeamCorrection/SeamSize.tsx index 25d14e5eac..02403ac5ec 100644 --- a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Canvas/SeamCorrection/SeamSize.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Canvas/SeamCorrection/SeamSize.tsx @@ -1,5 +1,5 @@ -import type { RootState } from 'app/store'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import type { RootState } from 'app/store/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAISlider from 'common/components/IAISlider'; import { setSeamSize } from 'features/parameters/store/generationSlice'; import { useTranslation } from 'react-i18next'; diff --git a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Canvas/SeamCorrection/SeamSteps.tsx b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Canvas/SeamCorrection/SeamSteps.tsx index ff58ff6837..0319b26820 100644 --- a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Canvas/SeamCorrection/SeamSteps.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Canvas/SeamCorrection/SeamSteps.tsx @@ -1,5 +1,5 @@ -import type { RootState } from 'app/store'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import type { RootState } from 'app/store/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAISlider from 'common/components/IAISlider'; import { setSeamSteps } from 'features/parameters/store/generationSlice'; import { useTranslation } from 'react-i18next'; diff --git a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Canvas/SeamCorrection/SeamStrength.tsx b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Canvas/SeamCorrection/SeamStrength.tsx index 0fa37b69b0..7d447cfda1 100644 --- a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Canvas/SeamCorrection/SeamStrength.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Canvas/SeamCorrection/SeamStrength.tsx @@ -1,5 +1,5 @@ -import { RootState } from 'app/store'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAISlider from 'common/components/IAISlider'; import { setSeamStrength } from 'features/parameters/store/generationSlice'; import { useTranslation } from 'react-i18next'; diff --git a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/FaceRestore/CodeformerFidelity.tsx b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/FaceRestore/CodeformerFidelity.tsx index 5558c39da7..f154477932 100644 --- a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/FaceRestore/CodeformerFidelity.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/FaceRestore/CodeformerFidelity.tsx @@ -1,5 +1,5 @@ -import type { RootState } from 'app/store'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import type { RootState } from 'app/store/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAISlider from 'common/components/IAISlider'; import { setCodeformerFidelity } from 'features/parameters/store/postprocessingSlice'; import { useTranslation } from 'react-i18next'; diff --git a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/FaceRestore/FaceRestoreSettings.tsx b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/FaceRestore/FaceRestoreSettings.tsx index 357e6cbcc9..f4d5ca07bc 100644 --- a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/FaceRestore/FaceRestoreSettings.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/FaceRestore/FaceRestoreSettings.tsx @@ -1,6 +1,6 @@ import { VStack } from '@chakra-ui/react'; -import { useAppSelector } from 'app/storeHooks'; -import type { RootState } from 'app/store'; +import { useAppSelector } from 'app/store/storeHooks'; +import type { RootState } from 'app/store/store'; import FaceRestoreType from './FaceRestoreType'; import FaceRestoreStrength from './FaceRestoreStrength'; import CodeformerFidelity from './CodeformerFidelity'; diff --git a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/FaceRestore/FaceRestoreStrength.tsx b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/FaceRestore/FaceRestoreStrength.tsx index 4bc730e085..eeb5417c6e 100644 --- a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/FaceRestore/FaceRestoreStrength.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/FaceRestore/FaceRestoreStrength.tsx @@ -1,5 +1,5 @@ -import { RootState } from 'app/store'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAISlider from 'common/components/IAISlider'; import { setFacetoolStrength } from 'features/parameters/store/postprocessingSlice'; import { useTranslation } from 'react-i18next'; diff --git a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/FaceRestore/FaceRestoreToggle.tsx b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/FaceRestore/FaceRestoreToggle.tsx index 2514eac8b0..a314c0ad73 100644 --- a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/FaceRestore/FaceRestoreToggle.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/FaceRestore/FaceRestoreToggle.tsx @@ -1,5 +1,5 @@ -import { RootState } from 'app/store'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAISwitch from 'common/components/IAISwitch'; import { setShouldRunFacetool } from 'features/parameters/store/postprocessingSlice'; import { ChangeEvent } from 'react'; diff --git a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/FaceRestore/FaceRestoreType.tsx b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/FaceRestore/FaceRestoreType.tsx index 85231c381f..aa4231eb4b 100644 --- a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/FaceRestore/FaceRestoreType.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/FaceRestore/FaceRestoreType.tsx @@ -1,6 +1,6 @@ import { FACETOOL_TYPES } from 'app/constants'; -import { RootState } from 'app/store'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAISelect from 'common/components/IAISelect'; import { FacetoolType, diff --git a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/ImageToImage/ImageFit.tsx b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/ImageToImage/ImageFit.tsx index f127afeda3..f479def1ab 100644 --- a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/ImageToImage/ImageFit.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/ImageToImage/ImageFit.tsx @@ -1,5 +1,5 @@ -import { RootState } from 'app/store'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAISwitch from 'common/components/IAISwitch'; import { setShouldFitToWidthHeight } from 'features/parameters/store/generationSlice'; import { ChangeEvent } from 'react'; diff --git a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/ImageToImage/ImageToImageStrength.tsx b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/ImageToImage/ImageToImageStrength.tsx index 18f5caf652..284aa9a5c0 100644 --- a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/ImageToImage/ImageToImageStrength.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/ImageToImage/ImageToImageStrength.tsx @@ -1,5 +1,5 @@ import { createSelector } from '@reduxjs/toolkit'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAISlider from 'common/components/IAISlider'; import { generationSelector } from 'features/parameters/store/generationSelectors'; import { setImg2imgStrength } from 'features/parameters/store/generationSlice'; diff --git a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/ImageToImage/ImageToImageToggle.tsx b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/ImageToImage/ImageToImageToggle.tsx index 07d100be96..89da0ae8b0 100644 --- a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/ImageToImage/ImageToImageToggle.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/ImageToImage/ImageToImageToggle.tsx @@ -1,6 +1,6 @@ import { Flex } from '@chakra-ui/react'; -import { RootState } from 'app/store'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAISwitch from 'common/components/IAISwitch'; import { isImageToImageEnabledChanged } from 'features/parameters/store/generationSlice'; import { ChangeEvent } from 'react'; diff --git a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/ImageToImage/InitialImagePreview.tsx b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/ImageToImage/InitialImagePreview.tsx index 19eae13ca6..d8d79edc7f 100644 --- a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/ImageToImage/InitialImagePreview.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/ImageToImage/InitialImagePreview.tsx @@ -1,7 +1,7 @@ import { Box, Flex, Image, Spinner, Text } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; -import { RootState } from 'app/store'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import SelectImagePlaceholder from 'common/components/SelectImagePlaceholder'; import { useGetUrl } from 'common/util/getUrl'; import useGetImageByNameAndType from 'features/gallery/hooks/useGetImageByName'; diff --git a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Output/HiresSettings.tsx b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Output/HiresSettings.tsx index 172acaab68..35b1e9d044 100644 --- a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Output/HiresSettings.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Output/HiresSettings.tsx @@ -1,6 +1,6 @@ import { createSelector } from '@reduxjs/toolkit'; -import type { RootState } from 'app/store'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import type { RootState } from 'app/store/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAISlider from 'common/components/IAISlider'; import IAISwitch from 'common/components/IAISwitch'; import { postprocessingSelector } from 'features/parameters/store/postprocessingSelectors'; diff --git a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Output/SeamlessSettings.tsx b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Output/SeamlessSettings.tsx index ddd6a4b24b..fb333c6f00 100644 --- a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Output/SeamlessSettings.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Output/SeamlessSettings.tsx @@ -1,5 +1,5 @@ -import { RootState } from 'app/store'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAISwitch from 'common/components/IAISwitch'; import { setSeamless } from 'features/parameters/store/generationSlice'; import { ChangeEvent } from 'react'; diff --git a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Output/SymmetrySettings.tsx b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Output/SymmetrySettings.tsx index e23385d0bc..21e014b715 100644 --- a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Output/SymmetrySettings.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Output/SymmetrySettings.tsx @@ -1,6 +1,6 @@ import { VStack } from '@chakra-ui/react'; -import { RootState } from 'app/store'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAISlider from 'common/components/IAISlider'; import { setHorizontalSymmetrySteps, diff --git a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Output/SymmetryToggle.tsx b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Output/SymmetryToggle.tsx index 9446271a0e..c155336c1e 100644 --- a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Output/SymmetryToggle.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Output/SymmetryToggle.tsx @@ -1,5 +1,5 @@ -import { RootState } from 'app/store'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAISwitch from 'common/components/IAISwitch'; import { setShouldUseSymmetry } from 'features/parameters/store/generationSlice'; diff --git a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Seed/Perlin.tsx b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Seed/Perlin.tsx index c340acac32..d2f4ea4249 100644 --- a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Seed/Perlin.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Seed/Perlin.tsx @@ -1,5 +1,5 @@ -import { RootState } from 'app/store'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAISlider from 'common/components/IAISlider'; import { setPerlin } from 'features/parameters/store/generationSlice'; import { useTranslation } from 'react-i18next'; diff --git a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Seed/RandomizeSeed.tsx b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Seed/RandomizeSeed.tsx index 576ac61aba..ea60124f74 100644 --- a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Seed/RandomizeSeed.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Seed/RandomizeSeed.tsx @@ -1,7 +1,7 @@ import { ChangeEvent, memo } from 'react'; -import { RootState } from 'app/store'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAISwitch from 'common/components/IAISwitch'; import { setShouldRandomizeSeed } from 'features/parameters/store/generationSlice'; import { useTranslation } from 'react-i18next'; diff --git a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Seed/Seed.tsx b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Seed/Seed.tsx index 7aac200b26..96c929a462 100644 --- a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Seed/Seed.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Seed/Seed.tsx @@ -1,7 +1,7 @@ import { HStack } from '@chakra-ui/react'; import { NUMPY_RAND_MAX, NUMPY_RAND_MIN } from 'app/constants'; -import { RootState } from 'app/store'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAINumberInput from 'common/components/IAINumberInput'; import { setSeed } from 'features/parameters/store/generationSlice'; import { useTranslation } from 'react-i18next'; diff --git a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Seed/ShuffleSeed.tsx b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Seed/ShuffleSeed.tsx index 675640050b..f2d222de7c 100644 --- a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Seed/ShuffleSeed.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Seed/ShuffleSeed.tsx @@ -1,9 +1,9 @@ import { Button } from '@chakra-ui/react'; import { NUMPY_RAND_MAX, NUMPY_RAND_MIN } from 'app/constants'; -import { RootState } from 'app/store'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; +import IAIIconButton from 'common/components/IAIIconButton'; import randomInt from 'common/util/randomInt'; -import { IAIIconButton } from 'exports'; import { setSeed } from 'features/parameters/store/generationSlice'; import { useTranslation } from 'react-i18next'; import { FaRandom } from 'react-icons/fa'; diff --git a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Seed/Threshold.tsx b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Seed/Threshold.tsx index dbcf201d04..14ca46b53c 100644 --- a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Seed/Threshold.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Seed/Threshold.tsx @@ -1,5 +1,5 @@ -import { RootState } from 'app/store'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAISlider from 'common/components/IAISlider'; import { setThreshold } from 'features/parameters/store/generationSlice'; import { useTranslation } from 'react-i18next'; diff --git a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Upscale/UpscaleDenoisingStrength.tsx b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Upscale/UpscaleDenoisingStrength.tsx index 0cb5a12524..7abcd55c03 100644 --- a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Upscale/UpscaleDenoisingStrength.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Upscale/UpscaleDenoisingStrength.tsx @@ -1,5 +1,5 @@ -import { RootState } from 'app/store'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAISlider from 'common/components/IAISlider'; import { setUpscalingDenoising } from 'features/parameters/store/postprocessingSlice'; import { useTranslation } from 'react-i18next'; diff --git a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Upscale/UpscaleScale.tsx b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Upscale/UpscaleScale.tsx index 9bbc7f4b65..180b90f021 100644 --- a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Upscale/UpscaleScale.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Upscale/UpscaleScale.tsx @@ -1,6 +1,6 @@ import { UPSCALING_LEVELS } from 'app/constants'; -import type { RootState } from 'app/store'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import type { RootState } from 'app/store/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAISelect from 'common/components/IAISelect'; import { setUpscalingLevel, diff --git a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Upscale/UpscaleStrength.tsx b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Upscale/UpscaleStrength.tsx index 819c4fda57..68f61cf1e0 100644 --- a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Upscale/UpscaleStrength.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Upscale/UpscaleStrength.tsx @@ -1,5 +1,5 @@ -import type { RootState } from 'app/store'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import type { RootState } from 'app/store/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAISlider from 'common/components/IAISlider'; import { setUpscalingStrength } from 'features/parameters/store/postprocessingSlice'; import { useTranslation } from 'react-i18next'; diff --git a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Upscale/UpscaleToggle.tsx b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Upscale/UpscaleToggle.tsx index bcd4c0d8b2..172a9f2de9 100644 --- a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Upscale/UpscaleToggle.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Upscale/UpscaleToggle.tsx @@ -1,5 +1,5 @@ -import { RootState } from 'app/store'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAISwitch from 'common/components/IAISwitch'; import { setShouldRunESRGAN } from 'features/parameters/store/postprocessingSlice'; import { ChangeEvent } from 'react'; diff --git a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Variations/GenerateVariations.tsx b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Variations/GenerateVariations.tsx index 90c872d4a7..ec9a8ae276 100644 --- a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Variations/GenerateVariations.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Variations/GenerateVariations.tsx @@ -1,5 +1,5 @@ -import { RootState } from 'app/store'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAISwitch from 'common/components/IAISwitch'; import { setShouldGenerateVariations } from 'features/parameters/store/generationSlice'; import { ChangeEvent } from 'react'; diff --git a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Variations/SeedWeights.tsx b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Variations/SeedWeights.tsx index 01fddf157f..7f8b096757 100644 --- a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Variations/SeedWeights.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Variations/SeedWeights.tsx @@ -1,5 +1,5 @@ -import { RootState } from 'app/store'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIInput from 'common/components/IAIInput'; import { validateSeedWeights } from 'common/util/seedWeightPairs'; import { setSeedWeights } from 'features/parameters/store/generationSlice'; diff --git a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Variations/VariationAmount.tsx b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Variations/VariationAmount.tsx index 27a39757f9..21b5001d6a 100644 --- a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Variations/VariationAmount.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Variations/VariationAmount.tsx @@ -1,5 +1,5 @@ -import { RootState } from 'app/store'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAISlider from 'common/components/IAISlider'; import { setVariationAmount } from 'features/parameters/store/generationSlice'; import { useTranslation } from 'react-i18next'; diff --git a/invokeai/frontend/web/src/features/parameters/components/AnimatedImageToImagePanel.tsx b/invokeai/frontend/web/src/features/parameters/components/AnimatedImageToImagePanel.tsx index d1e07220ae..a15759cd1f 100644 --- a/invokeai/frontend/web/src/features/parameters/components/AnimatedImageToImagePanel.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/AnimatedImageToImagePanel.tsx @@ -2,8 +2,8 @@ import { memo, useState } from 'react'; import { AnimatePresence, motion } from 'framer-motion'; import ImageToImageSettings from 'features/parameters/components/AdvancedParameters/ImageToImage/ImageToImageSettings'; -import { useAppSelector } from 'app/storeHooks'; -import { RootState } from 'app/store'; +import { useAppSelector } from 'app/store/storeHooks'; +import { RootState } from 'app/store/store'; import { Box } from '@chakra-ui/react'; const AnimatedImageToImagePanel = () => { diff --git a/invokeai/frontend/web/src/features/parameters/components/ImageDimensions/DimensionsSettings.tsx b/invokeai/frontend/web/src/features/parameters/components/ImageDimensions/DimensionsSettings.tsx index b6b1e206b6..a187eecd83 100644 --- a/invokeai/frontend/web/src/features/parameters/components/ImageDimensions/DimensionsSettings.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/ImageDimensions/DimensionsSettings.tsx @@ -1,7 +1,7 @@ import { Box, Flex, FormControl, FormLabel, Select } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; -import { RootState } from 'app/store'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAISlider from 'common/components/IAISlider'; import { setWidth } from 'features/parameters/store/generationSlice'; import { memo, useState } from 'react'; diff --git a/invokeai/frontend/web/src/features/parameters/components/MainParameters/HeightSlider.tsx b/invokeai/frontend/web/src/features/parameters/components/MainParameters/HeightSlider.tsx index ac9a483d21..2609ae0e40 100644 --- a/invokeai/frontend/web/src/features/parameters/components/MainParameters/HeightSlider.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/MainParameters/HeightSlider.tsx @@ -1,5 +1,5 @@ import { createSelector } from '@reduxjs/toolkit'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAISlider from 'common/components/IAISlider'; import { generationSelector } from 'features/parameters/store/generationSelectors'; import { setHeight } from 'features/parameters/store/generationSlice'; diff --git a/invokeai/frontend/web/src/features/parameters/components/MainParameters/MainCFGScale.tsx b/invokeai/frontend/web/src/features/parameters/components/MainParameters/MainCFGScale.tsx index bc3cbcc48e..928cccafd1 100644 --- a/invokeai/frontend/web/src/features/parameters/components/MainParameters/MainCFGScale.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/MainParameters/MainCFGScale.tsx @@ -1,5 +1,5 @@ import { createSelector } from '@reduxjs/toolkit'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAINumberInput from 'common/components/IAINumberInput'; import IAISlider from 'common/components/IAISlider'; import { generationSelector } from 'features/parameters/store/generationSelectors'; diff --git a/invokeai/frontend/web/src/features/parameters/components/MainParameters/MainHeight.tsx b/invokeai/frontend/web/src/features/parameters/components/MainParameters/MainHeight.tsx index 744e3a0967..e3a312f706 100644 --- a/invokeai/frontend/web/src/features/parameters/components/MainParameters/MainHeight.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/MainParameters/MainHeight.tsx @@ -1,6 +1,6 @@ import { HEIGHTS } from 'app/constants'; -import { RootState } from 'app/store'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAISelect from 'common/components/IAISelect'; import IAISlider from 'common/components/IAISlider'; import { setHeight } from 'features/parameters/store/generationSlice'; diff --git a/invokeai/frontend/web/src/features/parameters/components/MainParameters/MainIterations.tsx b/invokeai/frontend/web/src/features/parameters/components/MainParameters/MainIterations.tsx index fe95b0d5ca..d1d142d7ff 100644 --- a/invokeai/frontend/web/src/features/parameters/components/MainParameters/MainIterations.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/MainParameters/MainIterations.tsx @@ -1,5 +1,5 @@ import { createSelector } from '@reduxjs/toolkit'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAINumberInput from 'common/components/IAINumberInput'; import IAISlider from 'common/components/IAISlider'; import { generationSelector } from 'features/parameters/store/generationSelectors'; diff --git a/invokeai/frontend/web/src/features/parameters/components/MainParameters/MainSampler.tsx b/invokeai/frontend/web/src/features/parameters/components/MainParameters/MainSampler.tsx index d9b7bd6611..b71ff20e01 100644 --- a/invokeai/frontend/web/src/features/parameters/components/MainParameters/MainSampler.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/MainParameters/MainSampler.tsx @@ -1,6 +1,6 @@ -import { DIFFUSERS_SAMPLERS } from 'app/constants'; -import { RootState } from 'app/store'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { DIFFUSERS_SCHEDULERS } from 'app/constants'; +import { RootState } from 'app/store/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAISelect from 'common/components/IAISelect'; import { setSampler } from 'features/parameters/store/generationSlice'; import { ChangeEvent, memo, useCallback } from 'react'; @@ -23,7 +23,7 @@ const Scheduler = () => { label={t('parameters.sampler')} value={sampler} onChange={handleChange} - validValues={DIFFUSERS_SAMPLERS} + validValues={DIFFUSERS_SCHEDULERS} minWidth={36} /> ); diff --git a/invokeai/frontend/web/src/features/parameters/components/MainParameters/MainSettings.tsx b/invokeai/frontend/web/src/features/parameters/components/MainParameters/MainSettings.tsx index dbd95a196b..db2701e0c9 100644 --- a/invokeai/frontend/web/src/features/parameters/components/MainParameters/MainSettings.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/MainParameters/MainSettings.tsx @@ -1,7 +1,7 @@ import { Box, Flex, VStack } from '@chakra-ui/react'; -import { RootState } from 'app/store'; -import { useAppSelector } from 'app/storeHooks'; -import { ModelSelect } from 'exports'; +import { RootState } from 'app/store/store'; +import { useAppSelector } from 'app/store/storeHooks'; +import ModelSelect from 'features/system/components/ModelSelect'; import { memo } from 'react'; import HeightSlider from './HeightSlider'; import MainCFGScale from './MainCFGScale'; diff --git a/invokeai/frontend/web/src/features/parameters/components/MainParameters/MainSteps.tsx b/invokeai/frontend/web/src/features/parameters/components/MainParameters/MainSteps.tsx index 9a68e14ad3..43e399848e 100644 --- a/invokeai/frontend/web/src/features/parameters/components/MainParameters/MainSteps.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/MainParameters/MainSteps.tsx @@ -1,5 +1,5 @@ import { createSelector } from '@reduxjs/toolkit'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAINumberInput from 'common/components/IAINumberInput'; import IAISlider from 'common/components/IAISlider'; diff --git a/invokeai/frontend/web/src/features/parameters/components/MainParameters/MainWidth.tsx b/invokeai/frontend/web/src/features/parameters/components/MainParameters/MainWidth.tsx index 81942b83f9..7a8534147c 100644 --- a/invokeai/frontend/web/src/features/parameters/components/MainParameters/MainWidth.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/MainParameters/MainWidth.tsx @@ -1,6 +1,6 @@ import { WIDTHS } from 'app/constants'; -import { RootState } from 'app/store'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAISelect from 'common/components/IAISelect'; import IAISlider from 'common/components/IAISlider'; import { setWidth } from 'features/parameters/store/generationSlice'; diff --git a/invokeai/frontend/web/src/features/parameters/components/MainParameters/WidthSlider.tsx b/invokeai/frontend/web/src/features/parameters/components/MainParameters/WidthSlider.tsx index 9c2c2d571e..92fdf20a30 100644 --- a/invokeai/frontend/web/src/features/parameters/components/MainParameters/WidthSlider.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/MainParameters/WidthSlider.tsx @@ -1,5 +1,5 @@ import { createSelector } from '@reduxjs/toolkit'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAISlider from 'common/components/IAISlider'; import { generationSelector } from 'features/parameters/store/generationSelectors'; import { setWidth } from 'features/parameters/store/generationSlice'; diff --git a/invokeai/frontend/web/src/features/parameters/components/ParametersAccordion.tsx b/invokeai/frontend/web/src/features/parameters/components/ParametersAccordion.tsx index d697e3e130..50c5bb62e9 100644 --- a/invokeai/frontend/web/src/features/parameters/components/ParametersAccordion.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/ParametersAccordion.tsx @@ -1,7 +1,7 @@ import { Accordion } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; import { Feature } from 'app/features'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { tabMap } from 'features/ui/store/tabMap'; import { uiSelector } from 'features/ui/store/uiSelectors'; import { openAccordionItemsChanged } from 'features/ui/store/uiSlice'; diff --git a/invokeai/frontend/web/src/features/parameters/components/ProcessButtons/CancelButton.tsx b/invokeai/frontend/web/src/features/parameters/components/ProcessButtons/CancelButton.tsx index 2fb81ae9a0..69567e5e1e 100644 --- a/invokeai/frontend/web/src/features/parameters/components/ProcessButtons/CancelButton.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/ProcessButtons/CancelButton.tsx @@ -1,5 +1,5 @@ import { createSelector } from '@reduxjs/toolkit'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIIconButton, { IAIIconButtonProps, } from 'common/components/IAIIconButton'; diff --git a/invokeai/frontend/web/src/features/parameters/components/ProcessButtons/InvokeButton.tsx b/invokeai/frontend/web/src/features/parameters/components/ProcessButtons/InvokeButton.tsx index ab1953dcc6..e028fe4f8d 100644 --- a/invokeai/frontend/web/src/features/parameters/components/ProcessButtons/InvokeButton.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/ProcessButtons/InvokeButton.tsx @@ -1,7 +1,7 @@ import { Box } from '@chakra-ui/react'; import { readinessSelector } from 'app/selectors/readinessSelector'; import { generateImage } from 'app/socketio/actions'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIButton, { IAIButtonProps } from 'common/components/IAIButton'; import IAIIconButton, { IAIIconButtonProps, diff --git a/invokeai/frontend/web/src/features/parameters/components/ProcessButtons/Loopback.tsx b/invokeai/frontend/web/src/features/parameters/components/ProcessButtons/Loopback.tsx index 09cc991653..3bd405d1ce 100644 --- a/invokeai/frontend/web/src/features/parameters/components/ProcessButtons/Loopback.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/ProcessButtons/Loopback.tsx @@ -1,5 +1,5 @@ import { createSelector } from '@reduxjs/toolkit'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIIconButton from 'common/components/IAIIconButton'; import { postprocessingSelector } from 'features/parameters/store/postprocessingSelectors'; import { setShouldLoopback } from 'features/parameters/store/postprocessingSlice'; diff --git a/invokeai/frontend/web/src/features/parameters/components/ProcessButtons/ProcessButtons.tsx b/invokeai/frontend/web/src/features/parameters/components/ProcessButtons/ProcessButtons.tsx index e4b3798548..e0ebba9f0d 100644 --- a/invokeai/frontend/web/src/features/parameters/components/ProcessButtons/ProcessButtons.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/ProcessButtons/ProcessButtons.tsx @@ -1,5 +1,5 @@ import { Flex } from '@chakra-ui/react'; -import { useAppSelector } from 'app/storeHooks'; +import { useAppSelector } from 'app/store/storeHooks'; import { activeTabNameSelector } from 'features/ui/store/uiSelectors'; import CancelButton from './CancelButton'; import InvokeButton from './InvokeButton'; diff --git a/invokeai/frontend/web/src/features/parameters/components/PromptInput/NegativePromptInput.tsx b/invokeai/frontend/web/src/features/parameters/components/PromptInput/NegativePromptInput.tsx index da22fa5594..ea3f12db42 100644 --- a/invokeai/frontend/web/src/features/parameters/components/PromptInput/NegativePromptInput.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/PromptInput/NegativePromptInput.tsx @@ -1,6 +1,6 @@ import { FormControl, Textarea } from '@chakra-ui/react'; -import type { RootState } from 'app/store'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import type { RootState } from 'app/store/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { setNegativePrompt } from 'features/parameters/store/generationSlice'; import { useTranslation } from 'react-i18next'; diff --git a/invokeai/frontend/web/src/features/parameters/components/PromptInput/PromptInput.tsx b/invokeai/frontend/web/src/features/parameters/components/PromptInput/PromptInput.tsx index 69efddf106..a04a073986 100644 --- a/invokeai/frontend/web/src/features/parameters/components/PromptInput/PromptInput.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/PromptInput/PromptInput.tsx @@ -1,7 +1,7 @@ import { Box, FormControl, Textarea } from '@chakra-ui/react'; import { generateImage } from 'app/socketio/actions'; -import { RootState } from 'app/store'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { ChangeEvent, KeyboardEvent, useRef } from 'react'; import { createSelector } from '@reduxjs/toolkit'; diff --git a/invokeai/frontend/web/src/features/parameters/hooks/usePrompt.ts b/invokeai/frontend/web/src/features/parameters/hooks/usePrompt.ts index 310f9a9209..02293c6ace 100644 --- a/invokeai/frontend/web/src/features/parameters/hooks/usePrompt.ts +++ b/invokeai/frontend/web/src/features/parameters/hooks/usePrompt.ts @@ -1,8 +1,8 @@ import { getPromptAndNegative } from 'common/util/getPromptAndNegative'; -import * as InvokeAI from 'app/invokeai'; +import * as InvokeAI from 'app/types/invokeai'; import promptToString from 'common/util/promptToString'; -import { useAppDispatch } from 'app/storeHooks'; +import { useAppDispatch } from 'app/store/storeHooks'; import { setNegativePrompt, setPrompt } from '../store/generationSlice'; // TECHDEBT: We have two metadata prompt formats and need to handle recalling either of them. diff --git a/invokeai/frontend/web/src/features/parameters/store/generationSelectors.ts b/invokeai/frontend/web/src/features/parameters/store/generationSelectors.ts index 39550c5ad6..eb3cb7a7d8 100644 --- a/invokeai/frontend/web/src/features/parameters/store/generationSelectors.ts +++ b/invokeai/frontend/web/src/features/parameters/store/generationSelectors.ts @@ -1,5 +1,5 @@ import { createSelector } from '@reduxjs/toolkit'; -import { RootState } from 'app/store'; +import { RootState } from 'app/store/store'; import { gallerySelector } from 'features/gallery/store/gallerySelectors'; import { selectResultsById, diff --git a/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts b/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts index e4a92f0b10..7dabfae07f 100644 --- a/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts +++ b/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts @@ -1,6 +1,6 @@ import type { PayloadAction } from '@reduxjs/toolkit'; import { createSlice } from '@reduxjs/toolkit'; -import * as InvokeAI from 'app/invokeai'; +import * as InvokeAI from 'app/types/invokeai'; import { getPromptAndNegative } from 'common/util/getPromptAndNegative'; import promptToString from 'common/util/promptToString'; import { seedWeightsToString } from 'common/util/seedWeightPairs'; diff --git a/invokeai/frontend/web/src/features/parameters/store/postprocessingSelectors.ts b/invokeai/frontend/web/src/features/parameters/store/postprocessingSelectors.ts index 7cc346cbee..2908d16c54 100644 --- a/invokeai/frontend/web/src/features/parameters/store/postprocessingSelectors.ts +++ b/invokeai/frontend/web/src/features/parameters/store/postprocessingSelectors.ts @@ -1,4 +1,4 @@ -import { RootState } from 'app/store'; +import { RootState } from 'app/store/store'; export const postprocessingSelector = (state: RootState) => state.postprocessing; diff --git a/invokeai/frontend/web/src/features/system/components/ClearTempFolderButtonModal.tsx b/invokeai/frontend/web/src/features/system/components/ClearTempFolderButtonModal.tsx index e644487178..353eddc323 100644 --- a/invokeai/frontend/web/src/features/system/components/ClearTempFolderButtonModal.tsx +++ b/invokeai/frontend/web/src/features/system/components/ClearTempFolderButtonModal.tsx @@ -1,5 +1,5 @@ import { emptyTempFolder } from 'app/socketio/actions'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIAlertDialog from 'common/components/IAIAlertDialog'; import IAIButton from 'common/components/IAIButton'; import { isStagingSelector } from 'features/canvas/store/canvasSelectors'; diff --git a/invokeai/frontend/web/src/features/system/components/Console.tsx b/invokeai/frontend/web/src/features/system/components/Console.tsx index 7c227be226..6df54be3a5 100644 --- a/invokeai/frontend/web/src/features/system/components/Console.tsx +++ b/invokeai/frontend/web/src/features/system/components/Console.tsx @@ -1,6 +1,6 @@ import { Flex, Text, Tooltip } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIIconButton from 'common/components/IAIIconButton'; import { errorSeen, diff --git a/invokeai/frontend/web/src/features/system/components/InvokeAILogoComponent.tsx b/invokeai/frontend/web/src/features/system/components/InvokeAILogoComponent.tsx index 2c54d9d42a..e736450563 100644 --- a/invokeai/frontend/web/src/features/system/components/InvokeAILogoComponent.tsx +++ b/invokeai/frontend/web/src/features/system/components/InvokeAILogoComponent.tsx @@ -1,6 +1,6 @@ import { Flex, Text, Image } from '@chakra-ui/react'; -import { RootState } from 'app/store'; -import { useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppSelector } from 'app/store/storeHooks'; import InvokeAILogoImage from 'assets/images/logo.png'; const InvokeAILogoComponent = () => { diff --git a/invokeai/frontend/web/src/features/system/components/ModelManager/AddCheckpointModel.tsx b/invokeai/frontend/web/src/features/system/components/ModelManager/AddCheckpointModel.tsx index 5fc877891e..71d2b68a86 100644 --- a/invokeai/frontend/web/src/features/system/components/ModelManager/AddCheckpointModel.tsx +++ b/invokeai/frontend/web/src/features/system/components/ModelManager/AddCheckpointModel.tsx @@ -19,13 +19,13 @@ import SearchModels from './SearchModels'; import { addNewModel } from 'app/socketio/actions'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { Field, Formik } from 'formik'; import { useTranslation } from 'react-i18next'; -import type { InvokeModelConfigProps } from 'app/invokeai'; -import type { RootState } from 'app/store'; +import type { InvokeModelConfigProps } from 'app/types/invokeai'; +import type { RootState } from 'app/store/store'; import { setAddNewModelUIOption } from 'features/ui/store/uiSlice'; import type { FieldInputProps, FormikProps } from 'formik'; import IAIForm from 'common/components/IAIForm'; diff --git a/invokeai/frontend/web/src/features/system/components/ModelManager/AddDiffusersModel.tsx b/invokeai/frontend/web/src/features/system/components/ModelManager/AddDiffusersModel.tsx index 14cd488b72..5a22472fc4 100644 --- a/invokeai/frontend/web/src/features/system/components/ModelManager/AddDiffusersModel.tsx +++ b/invokeai/frontend/web/src/features/system/components/ModelManager/AddDiffusersModel.tsx @@ -7,16 +7,16 @@ import { Text, VStack, } from '@chakra-ui/react'; -import { InvokeDiffusersModelConfigProps } from 'app/invokeai'; +import { InvokeDiffusersModelConfigProps } from 'app/types/invokeai'; import { addNewModel } from 'app/socketio/actions'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIButton from 'common/components/IAIButton'; import IAIInput from 'common/components/IAIInput'; import { setAddNewModelUIOption } from 'features/ui/store/uiSlice'; import { Field, Formik } from 'formik'; import { useTranslation } from 'react-i18next'; -import type { RootState } from 'app/store'; +import type { RootState } from 'app/store/store'; import IAIForm from 'common/components/IAIForm'; import { IAIFormItemWrapper } from 'common/components/IAIForms/IAIFormItemWrapper'; diff --git a/invokeai/frontend/web/src/features/system/components/ModelManager/AddModel.tsx b/invokeai/frontend/web/src/features/system/components/ModelManager/AddModel.tsx index f0d46a89fa..bd0d0e5d3a 100644 --- a/invokeai/frontend/web/src/features/system/components/ModelManager/AddModel.tsx +++ b/invokeai/frontend/web/src/features/system/components/ModelManager/AddModel.tsx @@ -16,10 +16,10 @@ import IAIButton from 'common/components/IAIButton'; import { FaArrowLeft, FaPlus } from 'react-icons/fa'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { useTranslation } from 'react-i18next'; -import type { RootState } from 'app/store'; +import type { RootState } from 'app/store/store'; import { setAddNewModelUIOption } from 'features/ui/store/uiSlice'; import AddCheckpointModel from './AddCheckpointModel'; import AddDiffusersModel from './AddDiffusersModel'; diff --git a/invokeai/frontend/web/src/features/system/components/ModelManager/CheckpointModelEdit.tsx b/invokeai/frontend/web/src/features/system/components/ModelManager/CheckpointModelEdit.tsx index cfb94dd044..00f7a8cee8 100644 --- a/invokeai/frontend/web/src/features/system/components/ModelManager/CheckpointModelEdit.tsx +++ b/invokeai/frontend/web/src/features/system/components/ModelManager/CheckpointModelEdit.tsx @@ -5,7 +5,7 @@ import IAIInput from 'common/components/IAIInput'; import IAINumberInput from 'common/components/IAINumberInput'; import { useEffect, useState } from 'react'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { systemSelector } from 'features/system/store/systemSelectors'; import { @@ -21,8 +21,8 @@ import { addNewModel } from 'app/socketio/actions'; import { Field, Formik } from 'formik'; import { useTranslation } from 'react-i18next'; -import type { InvokeModelConfigProps } from 'app/invokeai'; -import type { RootState } from 'app/store'; +import type { InvokeModelConfigProps } from 'app/types/invokeai'; +import type { RootState } from 'app/store/store'; import type { FieldInputProps, FormikProps } from 'formik'; import { isEqual, pickBy } from 'lodash'; import ModelConvert from './ModelConvert'; diff --git a/invokeai/frontend/web/src/features/system/components/ModelManager/DiffusersModelEdit.tsx b/invokeai/frontend/web/src/features/system/components/ModelManager/DiffusersModelEdit.tsx index 4b86583d61..39765a1dd5 100644 --- a/invokeai/frontend/web/src/features/system/components/ModelManager/DiffusersModelEdit.tsx +++ b/invokeai/frontend/web/src/features/system/components/ModelManager/DiffusersModelEdit.tsx @@ -4,7 +4,7 @@ import IAIButton from 'common/components/IAIButton'; import IAIInput from 'common/components/IAIInput'; import { useEffect, useState } from 'react'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { systemSelector } from 'features/system/store/systemSelectors'; import { Flex, FormControl, FormLabel, Text, VStack } from '@chakra-ui/react'; @@ -13,8 +13,8 @@ import { addNewModel } from 'app/socketio/actions'; import { Field, Formik } from 'formik'; import { useTranslation } from 'react-i18next'; -import type { InvokeDiffusersModelConfigProps } from 'app/invokeai'; -import type { RootState } from 'app/store'; +import type { InvokeDiffusersModelConfigProps } from 'app/types/invokeai'; +import type { RootState } from 'app/store/store'; import { isEqual, pickBy } from 'lodash'; import IAIFormHelperText from 'common/components/IAIForms/IAIFormHelperText'; import IAIFormErrorMessage from 'common/components/IAIForms/IAIFormErrorMessage'; diff --git a/invokeai/frontend/web/src/features/system/components/ModelManager/MergeModels.tsx b/invokeai/frontend/web/src/features/system/components/ModelManager/MergeModels.tsx index 3b1905979c..47e9277a59 100644 --- a/invokeai/frontend/web/src/features/system/components/ModelManager/MergeModels.tsx +++ b/invokeai/frontend/web/src/features/system/components/ModelManager/MergeModels.tsx @@ -14,15 +14,15 @@ import { useDisclosure, } from '@chakra-ui/react'; import { mergeDiffusersModels } from 'app/socketio/actions'; -import { RootState } from 'app/store'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIButton from 'common/components/IAIButton'; import IAIInput from 'common/components/IAIInput'; import IAISelect from 'common/components/IAISelect'; import { diffusersModelsSelector } from 'features/system/store/systemSelectors'; import { useState } from 'react'; import { useTranslation } from 'react-i18next'; -import * as InvokeAI from 'app/invokeai'; +import * as InvokeAI from 'app/types/invokeai'; import IAISlider from 'common/components/IAISlider'; import IAICheckbox from 'common/components/IAICheckbox'; diff --git a/invokeai/frontend/web/src/features/system/components/ModelManager/ModelConvert.tsx b/invokeai/frontend/web/src/features/system/components/ModelManager/ModelConvert.tsx index 5896e634ea..3a5aa1264b 100644 --- a/invokeai/frontend/web/src/features/system/components/ModelManager/ModelConvert.tsx +++ b/invokeai/frontend/web/src/features/system/components/ModelManager/ModelConvert.tsx @@ -8,8 +8,8 @@ import { Tooltip, } from '@chakra-ui/react'; import { convertToDiffusers } from 'app/socketio/actions'; -import { RootState } from 'app/store'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIAlertDialog from 'common/components/IAIAlertDialog'; import IAIButton from 'common/components/IAIButton'; import IAIInput from 'common/components/IAIInput'; diff --git a/invokeai/frontend/web/src/features/system/components/ModelManager/ModelList.tsx b/invokeai/frontend/web/src/features/system/components/ModelManager/ModelList.tsx index ad5b9b9072..b22cbc7548 100644 --- a/invokeai/frontend/web/src/features/system/components/ModelManager/ModelList.tsx +++ b/invokeai/frontend/web/src/features/system/components/ModelManager/ModelList.tsx @@ -6,7 +6,7 @@ import AddModel from './AddModel'; import ModelListItem from './ModelListItem'; import MergeModels from './MergeModels'; -import { useAppSelector } from 'app/storeHooks'; +import { useAppSelector } from 'app/store/storeHooks'; import { useTranslation } from 'react-i18next'; import { createSelector } from '@reduxjs/toolkit'; diff --git a/invokeai/frontend/web/src/features/system/components/ModelManager/ModelListItem.tsx b/invokeai/frontend/web/src/features/system/components/ModelManager/ModelListItem.tsx index 6b9e4d1cfd..47d139cc8f 100644 --- a/invokeai/frontend/web/src/features/system/components/ModelManager/ModelListItem.tsx +++ b/invokeai/frontend/web/src/features/system/components/ModelManager/ModelListItem.tsx @@ -1,9 +1,9 @@ import { DeleteIcon, EditIcon } from '@chakra-ui/icons'; import { Box, Button, Flex, Spacer, Text, Tooltip } from '@chakra-ui/react'; -import { ModelStatus } from 'app/invokeai'; +import { ModelStatus } from 'app/types/invokeai'; import { deleteModel, requestModelChange } from 'app/socketio/actions'; -import { RootState } from 'app/store'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIAlertDialog from 'common/components/IAIAlertDialog'; import IAIIconButton from 'common/components/IAIIconButton'; import { setOpenModel } from 'features/system/store/systemSlice'; diff --git a/invokeai/frontend/web/src/features/system/components/ModelManager/ModelManagerModal.tsx b/invokeai/frontend/web/src/features/system/components/ModelManager/ModelManagerModal.tsx index 5de4faa80b..440e5ad4db 100644 --- a/invokeai/frontend/web/src/features/system/components/ModelManager/ModelManagerModal.tsx +++ b/invokeai/frontend/web/src/features/system/components/ModelManager/ModelManagerModal.tsx @@ -11,8 +11,8 @@ import { } from '@chakra-ui/react'; import { cloneElement } from 'react'; -import { RootState } from 'app/store'; -import { useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppSelector } from 'app/store/storeHooks'; import { useTranslation } from 'react-i18next'; import type { ReactElement } from 'react'; diff --git a/invokeai/frontend/web/src/features/system/components/ModelManager/SearchModels.tsx b/invokeai/frontend/web/src/features/system/components/ModelManager/SearchModels.tsx index 510c4de147..b791aae339 100644 --- a/invokeai/frontend/web/src/features/system/components/ModelManager/SearchModels.tsx +++ b/invokeai/frontend/web/src/features/system/components/ModelManager/SearchModels.tsx @@ -14,7 +14,7 @@ import { Text, } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { systemSelector } from 'features/system/store/systemSelectors'; import { useTranslation } from 'react-i18next'; @@ -27,8 +27,8 @@ import { } from 'features/system/store/systemSlice'; import { setShouldShowExistingModelsInSearch } from 'features/ui/store/uiSlice'; -import type { FoundModel } from 'app/invokeai'; -import type { RootState } from 'app/store'; +import type { FoundModel } from 'app/types/invokeai'; +import type { RootState } from 'app/store/store'; import IAIInput from 'common/components/IAIInput'; import { Field, Formik } from 'formik'; import { forEach, remove } from 'lodash'; diff --git a/invokeai/frontend/web/src/features/system/components/ModelSelect.tsx b/invokeai/frontend/web/src/features/system/components/ModelSelect.tsx index 9e06d2bff3..704a075474 100644 --- a/invokeai/frontend/web/src/features/system/components/ModelSelect.tsx +++ b/invokeai/frontend/web/src/features/system/components/ModelSelect.tsx @@ -3,14 +3,14 @@ import { ChangeEvent, memo } from 'react'; import { isEqual } from 'lodash'; import { useTranslation } from 'react-i18next'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAISelect from 'common/components/IAISelect'; import { modelSelected, selectedModelSelector, selectModelsIds, } from '../store/modelSlice'; -import { RootState } from 'app/store'; +import { RootState } from 'app/store/store'; const selector = createSelector( [(state: RootState) => state], diff --git a/invokeai/frontend/web/src/features/system/components/ProgressBar.tsx b/invokeai/frontend/web/src/features/system/components/ProgressBar.tsx index 7fa3d961fa..0687b3f39f 100644 --- a/invokeai/frontend/web/src/features/system/components/ProgressBar.tsx +++ b/invokeai/frontend/web/src/features/system/components/ProgressBar.tsx @@ -1,6 +1,6 @@ import { Progress } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; -import { useAppSelector } from 'app/storeHooks'; +import { useAppSelector } from 'app/store/storeHooks'; import { SystemState } from 'features/system/store/systemSlice'; import { isEqual } from 'lodash'; import { useTranslation } from 'react-i18next'; diff --git a/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsModal.tsx b/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsModal.tsx index c203edfc37..53b0463208 100644 --- a/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsModal.tsx +++ b/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsModal.tsx @@ -15,8 +15,8 @@ import { } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; import { IN_PROGRESS_IMAGE_TYPES } from 'app/constants'; -import { RootState } from 'app/store'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIButton from 'common/components/IAIButton'; import IAINumberInput from 'common/components/IAINumberInput'; import IAISelect from 'common/components/IAISelect'; @@ -38,7 +38,7 @@ import { } from 'features/ui/store/uiSlice'; import { UIState } from 'features/ui/store/uiTypes'; import { isEqual, map } from 'lodash'; -import { persistor } from 'persistor'; +import { persistor } from 'app/store/persistor'; import { ChangeEvent, cloneElement, ReactElement } from 'react'; import { useTranslation } from 'react-i18next'; diff --git a/invokeai/frontend/web/src/features/system/components/SiteHeader.tsx b/invokeai/frontend/web/src/features/system/components/SiteHeader.tsx index af7a4ce33f..004e3690fd 100644 --- a/invokeai/frontend/web/src/features/system/components/SiteHeader.tsx +++ b/invokeai/frontend/web/src/features/system/components/SiteHeader.tsx @@ -7,8 +7,8 @@ import InvokeAILogoComponent from './InvokeAILogoComponent'; import SiteHeaderMenu from './SiteHeaderMenu'; import useResolution from 'common/hooks/useResolution'; import { FaBars } from 'react-icons/fa'; -import { IAIIconButton } from 'exports'; import { useTranslation } from 'react-i18next'; +import IAIIconButton from 'common/components/IAIIconButton'; /** * Header, includes color mode toggle, settings button, status message. diff --git a/invokeai/frontend/web/src/features/system/components/StatusIndicator.tsx b/invokeai/frontend/web/src/features/system/components/StatusIndicator.tsx index a8a87bc39a..9820eb7345 100644 --- a/invokeai/frontend/web/src/features/system/components/StatusIndicator.tsx +++ b/invokeai/frontend/web/src/features/system/components/StatusIndicator.tsx @@ -1,6 +1,6 @@ import { Text, Tooltip } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { errorSeen, SystemState } from 'features/system/store/systemSlice'; import { isEqual } from 'lodash'; import { useTranslation } from 'react-i18next'; diff --git a/invokeai/frontend/web/src/features/system/components/ThemeChanger.tsx b/invokeai/frontend/web/src/features/system/components/ThemeChanger.tsx index dd8b19b93e..ff825e9bf0 100644 --- a/invokeai/frontend/web/src/features/system/components/ThemeChanger.tsx +++ b/invokeai/frontend/web/src/features/system/components/ThemeChanger.tsx @@ -1,6 +1,6 @@ import { VStack } from '@chakra-ui/react'; -import { RootState } from 'app/store'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIButton from 'common/components/IAIButton'; import IAIIconButton from 'common/components/IAIIconButton'; import IAIPopover from 'common/components/IAIPopover'; diff --git a/invokeai/frontend/web/src/features/system/hooks/useFeatureStatus.ts b/invokeai/frontend/web/src/features/system/hooks/useFeatureStatus.ts index 1006844dcf..2e0cfb3d20 100644 --- a/invokeai/frontend/web/src/features/system/hooks/useFeatureStatus.ts +++ b/invokeai/frontend/web/src/features/system/hooks/useFeatureStatus.ts @@ -1,6 +1,6 @@ -import { AppFeature } from 'app/invokeai'; -import { RootState } from 'app/store'; -import { useAppSelector } from 'app/storeHooks'; +import { AppFeature } from 'app/types/invokeai'; +import { RootState } from 'app/store/store'; +import { useAppSelector } from 'app/store/storeHooks'; import { useMemo } from 'react'; export const useFeatureStatus = (feature: AppFeature) => { diff --git a/invokeai/frontend/web/src/features/system/hooks/useIsApplicationReady.ts b/invokeai/frontend/web/src/features/system/hooks/useIsApplicationReady.ts index 52821425f3..cecd739278 100644 --- a/invokeai/frontend/web/src/features/system/hooks/useIsApplicationReady.ts +++ b/invokeai/frontend/web/src/features/system/hooks/useIsApplicationReady.ts @@ -1,6 +1,6 @@ import { createSelector } from '@reduxjs/toolkit'; -import { RootState } from 'app/store'; -import { useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppSelector } from 'app/store/storeHooks'; import { useMemo } from 'react'; import { configSelector } from '../store/configSelectors'; import { systemSelector } from '../store/systemSelectors'; diff --git a/invokeai/frontend/web/src/features/system/hooks/useIsTabDisabled.ts b/invokeai/frontend/web/src/features/system/hooks/useIsTabDisabled.ts index b4b2a390b1..1d14ac2243 100644 --- a/invokeai/frontend/web/src/features/system/hooks/useIsTabDisabled.ts +++ b/invokeai/frontend/web/src/features/system/hooks/useIsTabDisabled.ts @@ -1,5 +1,5 @@ -import { RootState } from 'app/store'; -import { useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppSelector } from 'app/store/storeHooks'; import { InvokeTabName } from 'features/ui/store/tabMap'; import { useCallback } from 'react'; diff --git a/invokeai/frontend/web/src/features/system/hooks/useToastWatcher.ts b/invokeai/frontend/web/src/features/system/hooks/useToastWatcher.ts index 0c99eec0a4..b51bf48a36 100644 --- a/invokeai/frontend/web/src/features/system/hooks/useToastWatcher.ts +++ b/invokeai/frontend/web/src/features/system/hooks/useToastWatcher.ts @@ -1,5 +1,5 @@ import { useToast, UseToastOptions } from '@chakra-ui/react'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { toastQueueSelector } from 'features/system/store/systemSelectors'; import { clearToastQueue } from 'features/system/store/systemSlice'; import { useEffect } from 'react'; diff --git a/invokeai/frontend/web/src/features/system/store/configSelectors.ts b/invokeai/frontend/web/src/features/system/store/configSelectors.ts index 399f974611..e96775321a 100644 --- a/invokeai/frontend/web/src/features/system/store/configSelectors.ts +++ b/invokeai/frontend/web/src/features/system/store/configSelectors.ts @@ -1,3 +1,3 @@ -import { RootState } from 'app/store'; +import { RootState } from 'app/store/store'; export const configSelector = (state: RootState) => state.config; diff --git a/invokeai/frontend/web/src/features/system/store/configSlice.ts b/invokeai/frontend/web/src/features/system/store/configSlice.ts index 9f2bec606b..e38d554603 100644 --- a/invokeai/frontend/web/src/features/system/store/configSlice.ts +++ b/invokeai/frontend/web/src/features/system/store/configSlice.ts @@ -1,6 +1,6 @@ import type { PayloadAction } from '@reduxjs/toolkit'; import { createSlice } from '@reduxjs/toolkit'; -import { AppConfig, PartialAppConfig } from 'app/invokeai'; +import { AppConfig, PartialAppConfig } from 'app/types/invokeai'; import { merge } from 'lodash'; const initialConfigState: AppConfig = { diff --git a/invokeai/frontend/web/src/features/system/store/modelSelectors.ts b/invokeai/frontend/web/src/features/system/store/modelSelectors.ts index 74027d631b..5695ae8556 100644 --- a/invokeai/frontend/web/src/features/system/store/modelSelectors.ts +++ b/invokeai/frontend/web/src/features/system/store/modelSelectors.ts @@ -1,5 +1,5 @@ import { createSelector } from '@reduxjs/toolkit'; -import { RootState } from 'app/store'; +import { RootState } from 'app/store/store'; import { reduce } from 'lodash'; export const modelSelector = (state: RootState) => state.models; diff --git a/invokeai/frontend/web/src/features/system/store/modelSlice.ts b/invokeai/frontend/web/src/features/system/store/modelSlice.ts index 843e27a435..f858fafd8b 100644 --- a/invokeai/frontend/web/src/features/system/store/modelSlice.ts +++ b/invokeai/frontend/web/src/features/system/store/modelSlice.ts @@ -1,6 +1,6 @@ import { createEntityAdapter, PayloadAction } from '@reduxjs/toolkit'; import { createSlice } from '@reduxjs/toolkit'; -import { RootState } from 'app/store'; +import { RootState } from 'app/store/store'; import { keys, sample } from 'lodash'; import { CkptModelInfo, DiffusersModelInfo } from 'services/api'; import { receivedModels } from 'services/thunks/model'; diff --git a/invokeai/frontend/web/src/features/system/store/systemSelectors.ts b/invokeai/frontend/web/src/features/system/store/systemSelectors.ts index b1f670c075..876d40e862 100644 --- a/invokeai/frontend/web/src/features/system/store/systemSelectors.ts +++ b/invokeai/frontend/web/src/features/system/store/systemSelectors.ts @@ -1,5 +1,5 @@ import { createSelector } from '@reduxjs/toolkit'; -import { RootState } from 'app/store'; +import { RootState } from 'app/store/store'; import { isEqual, reduce, pickBy } from 'lodash'; export const systemSelector = (state: RootState) => state.system; diff --git a/invokeai/frontend/web/src/features/system/store/systemSlice.ts b/invokeai/frontend/web/src/features/system/store/systemSlice.ts index 3291cd96d7..01d19973f9 100644 --- a/invokeai/frontend/web/src/features/system/store/systemSlice.ts +++ b/invokeai/frontend/web/src/features/system/store/systemSlice.ts @@ -1,7 +1,7 @@ import { ExpandedIndex, UseToastOptions } from '@chakra-ui/react'; import type { PayloadAction } from '@reduxjs/toolkit'; import { createSlice } from '@reduxjs/toolkit'; -import * as InvokeAI from 'app/invokeai'; +import * as InvokeAI from 'app/types/invokeai'; import { generatorProgress, invocationComplete, diff --git a/invokeai/frontend/web/src/features/ui/components/FloatingGalleryButton.tsx b/invokeai/frontend/web/src/features/ui/components/FloatingGalleryButton.tsx index e0dd3eadd3..ea13842f23 100644 --- a/invokeai/frontend/web/src/features/ui/components/FloatingGalleryButton.tsx +++ b/invokeai/frontend/web/src/features/ui/components/FloatingGalleryButton.tsx @@ -1,5 +1,5 @@ import { createSelector } from '@reduxjs/toolkit'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIIconButton from 'common/components/IAIIconButton'; import { useTranslation } from 'react-i18next'; import { requestCanvasRescale } from 'features/canvas/store/thunks/requestCanvasScale'; diff --git a/invokeai/frontend/web/src/features/ui/components/FloatingParametersPanelButtons.tsx b/invokeai/frontend/web/src/features/ui/components/FloatingParametersPanelButtons.tsx index 77855cd05f..6b47ee1c97 100644 --- a/invokeai/frontend/web/src/features/ui/components/FloatingParametersPanelButtons.tsx +++ b/invokeai/frontend/web/src/features/ui/components/FloatingParametersPanelButtons.tsx @@ -1,6 +1,6 @@ import { ChakraProps, Flex } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIIconButton from 'common/components/IAIIconButton'; import { requestCanvasRescale } from 'features/canvas/store/thunks/requestCanvasScale'; import CancelButton from 'features/parameters/components/ProcessButtons/CancelButton'; diff --git a/invokeai/frontend/web/src/features/ui/components/InvokeTabs.tsx b/invokeai/frontend/web/src/features/ui/components/InvokeTabs.tsx index 3e0ee9ed85..e053986897 100644 --- a/invokeai/frontend/web/src/features/ui/components/InvokeTabs.tsx +++ b/invokeai/frontend/web/src/features/ui/components/InvokeTabs.tsx @@ -9,8 +9,8 @@ import { Tooltip, VisuallyHidden, } from '@chakra-ui/react'; -import { RootState } from 'app/store'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { setIsLightboxOpen } from 'features/lightbox/store/lightboxSlice'; import { InvokeTabName } from 'features/ui/store/tabMap'; import { setActiveTab, togglePanels } from 'features/ui/store/uiSlice'; diff --git a/invokeai/frontend/web/src/features/ui/components/InvokeWorkarea.tsx b/invokeai/frontend/web/src/features/ui/components/InvokeWorkarea.tsx index 8ed443a345..691ce5f703 100644 --- a/invokeai/frontend/web/src/features/ui/components/InvokeWorkarea.tsx +++ b/invokeai/frontend/web/src/features/ui/components/InvokeWorkarea.tsx @@ -1,6 +1,6 @@ import { Box, BoxProps, Grid, GridItem } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { initialImageSelected } from 'features/parameters/store/generationSlice'; import { activeTabNameSelector, diff --git a/invokeai/frontend/web/src/features/ui/components/ParametersPanel.tsx b/invokeai/frontend/web/src/features/ui/components/ParametersPanel.tsx index 09d4d6c316..116aa7bcc4 100644 --- a/invokeai/frontend/web/src/features/ui/components/ParametersPanel.tsx +++ b/invokeai/frontend/web/src/features/ui/components/ParametersPanel.tsx @@ -1,5 +1,5 @@ import { Flex } from '@chakra-ui/react'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { memo, ReactNode } from 'react'; diff --git a/invokeai/frontend/web/src/features/ui/components/PinParametersPanelButton.tsx b/invokeai/frontend/web/src/features/ui/components/PinParametersPanelButton.tsx index a385f29c35..46d0fa3f93 100644 --- a/invokeai/frontend/web/src/features/ui/components/PinParametersPanelButton.tsx +++ b/invokeai/frontend/web/src/features/ui/components/PinParametersPanelButton.tsx @@ -1,5 +1,5 @@ import { Tooltip } from '@chakra-ui/react'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIIconButton, { IAIIconButtonProps, } from 'common/components/IAIIconButton'; diff --git a/invokeai/frontend/web/src/features/ui/components/common/ParametersSlide.tsx b/invokeai/frontend/web/src/features/ui/components/common/ParametersSlide.tsx index 0889e779f1..4dcc8dc06e 100644 --- a/invokeai/frontend/web/src/features/ui/components/common/ParametersSlide.tsx +++ b/invokeai/frontend/web/src/features/ui/components/common/ParametersSlide.tsx @@ -1,7 +1,7 @@ import { Box, Flex, useOutsideClick } from '@chakra-ui/react'; import { Slide } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { uiSelector } from 'features/ui/store/uiSelectors'; import { isEqual } from 'lodash'; import { memo, PropsWithChildren, useRef } from 'react'; diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/Generate/GenerateWorkspace.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/Generate/GenerateWorkspace.tsx index e6c0c71ae1..df201af6ac 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/Generate/GenerateWorkspace.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/Generate/GenerateWorkspace.tsx @@ -1,10 +1,10 @@ import { Box, Flex } from '@chakra-ui/react'; -import { useAppSelector } from 'app/storeHooks'; +import { useAppSelector } from 'app/store/storeHooks'; import { memo } from 'react'; import GenerateContent from './GenerateContent'; import GenerateParameters from './GenerateParameters'; import PinParametersPanelButton from '../../PinParametersPanelButton'; -import { RootState } from 'app/store'; +import { RootState } from 'app/store/store'; import Scrollable from '../../common/Scrollable'; import ParametersSlide from '../../common/ParametersSlide'; import AnimatedImageToImagePanel from 'features/parameters/components/AnimatedImageToImagePanel'; diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasContentBeta.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasContentBeta.tsx index b489acf916..ff3736d3b6 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasContentBeta.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasContentBeta.tsx @@ -1,7 +1,7 @@ import { createSelector } from '@reduxjs/toolkit'; // import IAICanvas from 'features/canvas/components/IAICanvas'; import { Box, Flex } from '@chakra-ui/react'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAICanvas from 'features/canvas/components/IAICanvas'; import IAICanvasResizer from 'features/canvas/components/IAICanvasResizer'; import { canvasSelector } from 'features/canvas/store/canvasSelectors'; diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolSettings/UnifiedCanvasBrushSize.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolSettings/UnifiedCanvasBrushSize.tsx index 0ff57236c2..5117505826 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolSettings/UnifiedCanvasBrushSize.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolSettings/UnifiedCanvasBrushSize.tsx @@ -1,5 +1,5 @@ -import { RootState } from 'app/store'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAISlider from 'common/components/IAISlider'; import { isStagingSelector } from 'features/canvas/store/canvasSelectors'; import { setBrushSize } from 'features/canvas/store/canvasSlice'; diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolSettings/UnifiedCanvasClearMask.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolSettings/UnifiedCanvasClearMask.tsx index 9f13404f39..325afa7327 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolSettings/UnifiedCanvasClearMask.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolSettings/UnifiedCanvasClearMask.tsx @@ -1,4 +1,4 @@ -import { useAppDispatch } from 'app/storeHooks'; +import { useAppDispatch } from 'app/store/storeHooks'; import IAIButton from 'common/components/IAIButton'; import { clearMask } from 'features/canvas/store/canvasSlice'; diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolSettings/UnifiedCanvasColorPicker.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolSettings/UnifiedCanvasColorPicker.tsx index 2a3fa831fe..32f82d48f4 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolSettings/UnifiedCanvasColorPicker.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolSettings/UnifiedCanvasColorPicker.tsx @@ -1,6 +1,6 @@ import { Box, Flex } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIColorPicker from 'common/components/IAIColorPicker'; import IAIPopover from 'common/components/IAIPopover'; import { diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolSettings/UnifiedCanvasDarkenOutsideSelection.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolSettings/UnifiedCanvasDarkenOutsideSelection.tsx index f3fc4514f6..042749e792 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolSettings/UnifiedCanvasDarkenOutsideSelection.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolSettings/UnifiedCanvasDarkenOutsideSelection.tsx @@ -1,5 +1,5 @@ -import { RootState } from 'app/store'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAICheckbox from 'common/components/IAICheckbox'; import { setShouldDarkenOutsideBoundingBox } from 'features/canvas/store/canvasSlice'; import { useTranslation } from 'react-i18next'; diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolSettings/UnifiedCanvasEnableMask.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolSettings/UnifiedCanvasEnableMask.tsx index 7f0c5c07ed..24f3f45a25 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolSettings/UnifiedCanvasEnableMask.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolSettings/UnifiedCanvasEnableMask.tsx @@ -1,5 +1,5 @@ -import { RootState } from 'app/store'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAICheckbox from 'common/components/IAICheckbox'; import { setIsMaskEnabled } from 'features/canvas/store/canvasSlice'; import { useTranslation } from 'react-i18next'; diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolSettings/UnifiedCanvasLimitStrokesToBox.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolSettings/UnifiedCanvasLimitStrokesToBox.tsx index 90d8a86ac7..27fb21be21 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolSettings/UnifiedCanvasLimitStrokesToBox.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolSettings/UnifiedCanvasLimitStrokesToBox.tsx @@ -1,5 +1,5 @@ -import { RootState } from 'app/store'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAICheckbox from 'common/components/IAICheckbox'; import { setShouldRestrictStrokesToBox } from 'features/canvas/store/canvasSlice'; import { useTranslation } from 'react-i18next'; diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolSettings/UnifiedCanvasPreserveMask.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolSettings/UnifiedCanvasPreserveMask.tsx index f9da240ed7..9b4b20e936 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolSettings/UnifiedCanvasPreserveMask.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolSettings/UnifiedCanvasPreserveMask.tsx @@ -1,5 +1,5 @@ -import { RootState } from 'app/store'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAICheckbox from 'common/components/IAICheckbox'; import { setShouldPreserveMaskedArea } from 'features/canvas/store/canvasSlice'; import { useTranslation } from 'react-i18next'; diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolSettings/UnifiedCanvasSettings.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolSettings/UnifiedCanvasSettings.tsx index 689b9a7292..eed8f73433 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolSettings/UnifiedCanvasSettings.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolSettings/UnifiedCanvasSettings.tsx @@ -1,6 +1,6 @@ import { Flex } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAICheckbox from 'common/components/IAICheckbox'; import IAIIconButton from 'common/components/IAIIconButton'; import IAIPopover from 'common/components/IAIPopover'; diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolSettings/UnifiedCanvasShowGrid.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolSettings/UnifiedCanvasShowGrid.tsx index 20d81435a2..e3d8a518ef 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolSettings/UnifiedCanvasShowGrid.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolSettings/UnifiedCanvasShowGrid.tsx @@ -1,5 +1,5 @@ -import { RootState } from 'app/store'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAICheckbox from 'common/components/IAICheckbox'; import { setShouldShowGrid } from 'features/canvas/store/canvasSlice'; import { useTranslation } from 'react-i18next'; diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolSettings/UnifiedCanvasSnapToGrid.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolSettings/UnifiedCanvasSnapToGrid.tsx index 5320d129f7..c334bd213b 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolSettings/UnifiedCanvasSnapToGrid.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolSettings/UnifiedCanvasSnapToGrid.tsx @@ -1,5 +1,5 @@ -import { RootState } from 'app/store'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAICheckbox from 'common/components/IAICheckbox'; import { setShouldSnapToGrid } from 'features/canvas/store/canvasSlice'; import { ChangeEvent } from 'react'; diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolSettingsBeta.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolSettingsBeta.tsx index 5db0c21361..e3382c39a7 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolSettingsBeta.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolSettingsBeta.tsx @@ -1,5 +1,5 @@ import { createSelector } from '@reduxjs/toolkit'; -import { useAppSelector } from 'app/storeHooks'; +import { useAppSelector } from 'app/store/storeHooks'; import { canvasSelector } from 'features/canvas/store/canvasSelectors'; import { Flex } from '@chakra-ui/react'; diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolbar/UnifiedCanvasCopyToClipboard.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolbar/UnifiedCanvasCopyToClipboard.tsx index 177166f8a8..4d1241c132 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolbar/UnifiedCanvasCopyToClipboard.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolbar/UnifiedCanvasCopyToClipboard.tsx @@ -1,5 +1,5 @@ -import { RootState } from 'app/store'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIIconButton from 'common/components/IAIIconButton'; import { isStagingSelector } from 'features/canvas/store/canvasSelectors'; import { mergeAndUploadCanvas } from 'features/canvas/store/thunks/mergeAndUploadCanvas'; diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolbar/UnifiedCanvasDownloadImage.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolbar/UnifiedCanvasDownloadImage.tsx index 215e2ea623..2be9db2afd 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolbar/UnifiedCanvasDownloadImage.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolbar/UnifiedCanvasDownloadImage.tsx @@ -1,5 +1,5 @@ -import { RootState } from 'app/store'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIIconButton from 'common/components/IAIIconButton'; import { isStagingSelector } from 'features/canvas/store/canvasSelectors'; import { mergeAndUploadCanvas } from 'features/canvas/store/thunks/mergeAndUploadCanvas'; diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolbar/UnifiedCanvasFileUploader.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolbar/UnifiedCanvasFileUploader.tsx index 3435551d6f..0e8761111c 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolbar/UnifiedCanvasFileUploader.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolbar/UnifiedCanvasFileUploader.tsx @@ -1,4 +1,4 @@ -import { useAppSelector } from 'app/storeHooks'; +import { useAppSelector } from 'app/store/storeHooks'; import IAIIconButton from 'common/components/IAIIconButton'; import useImageUploader from 'common/hooks/useImageUploader'; import { isStagingSelector } from 'features/canvas/store/canvasSelectors'; diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolbar/UnifiedCanvasLayerSelect.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolbar/UnifiedCanvasLayerSelect.tsx index 7ba0bb3949..8655a344b4 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolbar/UnifiedCanvasLayerSelect.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolbar/UnifiedCanvasLayerSelect.tsx @@ -1,5 +1,5 @@ import { createSelector } from '@reduxjs/toolkit'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAISelect from 'common/components/IAISelect'; import { canvasSelector, diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolbar/UnifiedCanvasMergeVisible.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolbar/UnifiedCanvasMergeVisible.tsx index 6067483cd8..41642e78e0 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolbar/UnifiedCanvasMergeVisible.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolbar/UnifiedCanvasMergeVisible.tsx @@ -1,5 +1,5 @@ -import { RootState } from 'app/store'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIIconButton from 'common/components/IAIIconButton'; import { isStagingSelector } from 'features/canvas/store/canvasSelectors'; import { mergeAndUploadCanvas } from 'features/canvas/store/thunks/mergeAndUploadCanvas'; diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolbar/UnifiedCanvasMoveTool.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolbar/UnifiedCanvasMoveTool.tsx index 4b73d28749..5362657def 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolbar/UnifiedCanvasMoveTool.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolbar/UnifiedCanvasMoveTool.tsx @@ -1,5 +1,5 @@ -import { RootState } from 'app/store'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIIconButton from 'common/components/IAIIconButton'; import { isStagingSelector } from 'features/canvas/store/canvasSelectors'; import { setTool } from 'features/canvas/store/canvasSlice'; diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolbar/UnifiedCanvasProcessingButtons.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolbar/UnifiedCanvasProcessingButtons.tsx index 11436f7abe..ca2d2a1d0a 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolbar/UnifiedCanvasProcessingButtons.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolbar/UnifiedCanvasProcessingButtons.tsx @@ -1,5 +1,5 @@ import { Flex } from '@chakra-ui/layout'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIIconButton from 'common/components/IAIIconButton'; import { requestCanvasRescale } from 'features/canvas/store/thunks/requestCanvasScale'; import CancelButton from 'features/parameters/components/ProcessButtons/CancelButton'; diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolbar/UnifiedCanvasResetCanvas.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolbar/UnifiedCanvasResetCanvas.tsx index b6bbfccbba..e8eeed7acc 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolbar/UnifiedCanvasResetCanvas.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolbar/UnifiedCanvasResetCanvas.tsx @@ -1,4 +1,4 @@ -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIIconButton from 'common/components/IAIIconButton'; import { isStagingSelector } from 'features/canvas/store/canvasSelectors'; import { diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolbar/UnifiedCanvasResetView.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolbar/UnifiedCanvasResetView.tsx index 6c9814f56f..fa002a788e 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolbar/UnifiedCanvasResetView.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolbar/UnifiedCanvasResetView.tsx @@ -1,4 +1,4 @@ -import { useAppDispatch } from 'app/storeHooks'; +import { useAppDispatch } from 'app/store/storeHooks'; import IAIIconButton from 'common/components/IAIIconButton'; import { useSingleAndDoubleClick } from 'common/hooks/useSingleAndDoubleClick'; import { resetCanvasView } from 'features/canvas/store/canvasSlice'; diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolbar/UnifiedCanvasSaveToGallery.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolbar/UnifiedCanvasSaveToGallery.tsx index d3d5e58862..80ad607540 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolbar/UnifiedCanvasSaveToGallery.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolbar/UnifiedCanvasSaveToGallery.tsx @@ -1,5 +1,5 @@ -import { RootState } from 'app/store'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { RootState } from 'app/store/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIIconButton from 'common/components/IAIIconButton'; import { isStagingSelector } from 'features/canvas/store/canvasSelectors'; import { mergeAndUploadCanvas } from 'features/canvas/store/thunks/mergeAndUploadCanvas'; diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolbar/UnifiedCanvasToolSelect.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolbar/UnifiedCanvasToolSelect.tsx index 82b48fe435..deb9bfd144 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolbar/UnifiedCanvasToolSelect.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolbar/UnifiedCanvasToolSelect.tsx @@ -1,6 +1,6 @@ import { ButtonGroup, Flex } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIIconButton from 'common/components/IAIIconButton'; import { canvasSelector, diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasContent.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasContent.tsx index 1ae4a6500f..00c0245af5 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasContent.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasContent.tsx @@ -1,7 +1,7 @@ import { Box, Flex } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; // import IAICanvas from 'features/canvas/components/IAICanvas'; -import { useAppDispatch, useAppSelector } from 'app/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAICanvas from 'features/canvas/components/IAICanvas'; import IAICanvasResizer from 'features/canvas/components/IAICanvasResizer'; import IAICanvasToolbar from 'features/canvas/components/IAICanvasToolbar/IAICanvasToolbar'; diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasWorkarea.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasWorkarea.tsx index f1b931f5f1..dd32295f3c 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasWorkarea.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasWorkarea.tsx @@ -1,5 +1,5 @@ -// import { RootState } from 'app/store'; -// import { useAppSelector } from 'app/storeHooks'; +// import { RootState } from 'app/store/store'; +// import { useAppSelector } from 'app/store/storeHooks'; // import InvokeWorkarea from 'features/ui/components/InvokeWorkarea'; // import { activeTabNameSelector } from 'features/ui/store/uiSelectors'; // import UnifiedCanvasContentBeta from './UnifiedCanvasBeta/UnifiedCanvasContentBeta'; @@ -25,10 +25,10 @@ // ); // } import { Box, Flex } from '@chakra-ui/react'; -import { useAppSelector } from 'app/storeHooks'; +import { useAppSelector } from 'app/store/storeHooks'; import { memo } from 'react'; import PinParametersPanelButton from '../../PinParametersPanelButton'; -import { RootState } from 'app/store'; +import { RootState } from 'app/store/store'; import Scrollable from '../../common/Scrollable'; import ParametersSlide from '../../common/ParametersSlide'; import UnifiedCanvasParameters from './UnifiedCanvasParameters'; diff --git a/invokeai/frontend/web/src/features/ui/store/hotkeysSlice.ts b/invokeai/frontend/web/src/features/ui/store/hotkeysSlice.ts index 6c44a7d859..4e72d1dce9 100644 --- a/invokeai/frontend/web/src/features/ui/store/hotkeysSlice.ts +++ b/invokeai/frontend/web/src/features/ui/store/hotkeysSlice.ts @@ -1,6 +1,6 @@ import type { PayloadAction } from '@reduxjs/toolkit'; import { createSlice } from '@reduxjs/toolkit'; -import { RootState } from 'app/store'; +import { RootState } from 'app/store/store'; type HotkeysState = { shift: boolean; diff --git a/invokeai/frontend/web/src/features/ui/store/uiSelectors.ts b/invokeai/frontend/web/src/features/ui/store/uiSelectors.ts index d474bf6f27..88edd76786 100644 --- a/invokeai/frontend/web/src/features/ui/store/uiSelectors.ts +++ b/invokeai/frontend/web/src/features/ui/store/uiSelectors.ts @@ -1,5 +1,5 @@ import { createSelector } from '@reduxjs/toolkit'; -import { RootState } from 'app/store'; +import { RootState } from 'app/store/store'; import { isEqual } from 'lodash'; import { tabMap } from './tabMap'; diff --git a/invokeai/frontend/web/src/main.tsx b/invokeai/frontend/web/src/main.tsx index e0423d7e4e..4a57f73eeb 100644 --- a/invokeai/frontend/web/src/main.tsx +++ b/invokeai/frontend/web/src/main.tsx @@ -1,7 +1,7 @@ import ReactDOM from 'react-dom/client'; -import Component from './component'; +import App from './app/components/App'; ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( - + ); diff --git a/invokeai/frontend/web/src/services/events/middleware.ts b/invokeai/frontend/web/src/services/events/middleware.ts index 4e2a3fbabc..4c457f3d24 100644 --- a/invokeai/frontend/web/src/services/events/middleware.ts +++ b/invokeai/frontend/web/src/services/events/middleware.ts @@ -20,7 +20,7 @@ import { receivedResultImagesPage, receivedUploadImagesPage, } from 'services/thunks/gallery'; -import { AppDispatch, RootState } from 'app/store'; +import { AppDispatch, RootState } from 'app/store/store'; import { getTimestamp } from 'common/util/getTimestamp'; import { sessionInvoked, diff --git a/invokeai/frontend/web/src/services/thunks/gallery.ts b/invokeai/frontend/web/src/services/thunks/gallery.ts index 3badee2549..4361ce1499 100644 --- a/invokeai/frontend/web/src/services/thunks/gallery.ts +++ b/invokeai/frontend/web/src/services/thunks/gallery.ts @@ -1,4 +1,4 @@ -import { createAppAsyncThunk } from 'app/storeUtils'; +import { createAppAsyncThunk } from 'app/store/storeUtils'; import { ImagesService } from 'services/api'; export const IMAGES_PER_PAGE = 20; diff --git a/invokeai/frontend/web/src/services/thunks/image.ts b/invokeai/frontend/web/src/services/thunks/image.ts index 7288429ca0..6b902f6e26 100644 --- a/invokeai/frontend/web/src/services/thunks/image.ts +++ b/invokeai/frontend/web/src/services/thunks/image.ts @@ -1,5 +1,5 @@ import { isFulfilled, isRejected } from '@reduxjs/toolkit'; -import { createAppAsyncThunk } from 'app/storeUtils'; +import { createAppAsyncThunk } from 'app/store/storeUtils'; import { imageSelected } from 'features/gallery/store/gallerySlice'; import { clamp } from 'lodash'; import { ImagesService } from 'services/api'; diff --git a/invokeai/frontend/web/src/services/thunks/model.ts b/invokeai/frontend/web/src/services/thunks/model.ts index f5ee522593..b8017b562d 100644 --- a/invokeai/frontend/web/src/services/thunks/model.ts +++ b/invokeai/frontend/web/src/services/thunks/model.ts @@ -1,4 +1,4 @@ -import { createAppAsyncThunk } from 'app/storeUtils'; +import { createAppAsyncThunk } from 'app/store/storeUtils'; import { Model } from 'features/system/store/modelSlice'; import { reduce } from 'lodash'; import { ModelsService } from 'services/api'; diff --git a/invokeai/frontend/web/src/services/thunks/session.ts b/invokeai/frontend/web/src/services/thunks/session.ts index 6267f66ac2..ba796f7467 100644 --- a/invokeai/frontend/web/src/services/thunks/session.ts +++ b/invokeai/frontend/web/src/services/thunks/session.ts @@ -1,4 +1,4 @@ -import { createAppAsyncThunk } from 'app/storeUtils'; +import { createAppAsyncThunk } from 'app/store/storeUtils'; import { SessionsService } from 'services/api'; import { buildLinearGraph as buildGenerateGraph } from 'features/nodes/util/linearGraphBuilder/buildLinearGraph'; import { isAnyOf, isFulfilled } from '@reduxjs/toolkit'; diff --git a/invokeai/frontend/web/src/services/util/deserializeImageField.ts b/invokeai/frontend/web/src/services/util/deserializeImageField.ts index 0d50a78e49..adda71ccdd 100644 --- a/invokeai/frontend/web/src/services/util/deserializeImageField.ts +++ b/invokeai/frontend/web/src/services/util/deserializeImageField.ts @@ -1,4 +1,4 @@ -import { Image } from 'app/invokeai'; +import { Image } from 'app/types/invokeai'; import { ImageField, ImageType } from 'services/api'; import { AnyInvocation } from 'services/events/types'; diff --git a/invokeai/frontend/web/src/services/util/deserializeImageResponse.ts b/invokeai/frontend/web/src/services/util/deserializeImageResponse.ts index ec90fb6793..8d2a6df49e 100644 --- a/invokeai/frontend/web/src/services/util/deserializeImageResponse.ts +++ b/invokeai/frontend/web/src/services/util/deserializeImageResponse.ts @@ -1,4 +1,4 @@ -import { Image } from 'app/invokeai'; +import { Image } from 'app/types/invokeai'; import { parseInvokeAIMetadata } from 'common/util/parseMetadata'; import { ImageResponse } from 'services/api'; diff --git a/invokeai/frontend/web/src/theme/theme.ts b/invokeai/frontend/web/src/theme/theme.ts index 1ac868c272..c5b127f040 100644 --- a/invokeai/frontend/web/src/theme/theme.ts +++ b/invokeai/frontend/web/src/theme/theme.ts @@ -1,7 +1,7 @@ import { ThemeOverride } from '@chakra-ui/react'; import type { StyleFunctionProps } from '@chakra-ui/styled-system'; -import { invokeAIThemeColors } from './colors/invokeAI'; +import { invokeAIThemeColors } from 'theme/colors/invokeAI'; import { accordionTheme } from './components/accordion'; import { buttonTheme } from './components/button'; import { checkboxTheme } from './components/checkbox'; From de574eb4d9b40a93fde2aa7d23ee53e5209ceb4c Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Fri, 28 Apr 2023 12:41:41 +1000 Subject: [PATCH 17/68] chore(ui): upgrade all packages --- invokeai/frontend/web/package.json | 61 +- ...2.3.0.patch => @chakra-ui+cli+2.4.0.patch} | 0 invokeai/frontend/web/yarn.lock | 1985 +++++++++-------- 3 files changed, 1035 insertions(+), 1011 deletions(-) rename invokeai/frontend/web/patches/{@chakra-ui+cli+2.3.0.patch => @chakra-ui+cli+2.4.0.patch} (100%) diff --git a/invokeai/frontend/web/package.json b/invokeai/frontend/web/package.json index 5ac1c7f9d3..75609a1da8 100644 --- a/invokeai/frontend/web/package.json +++ b/invokeai/frontend/web/package.json @@ -40,40 +40,40 @@ }, "dependencies": { "@chakra-ui/anatomy": "^2.1.1", - "@chakra-ui/cli": "^2.3.0", - "@chakra-ui/icons": "^2.0.17", - "@chakra-ui/react": "^2.5.1", - "@chakra-ui/styled-system": "^2.6.1", + "@chakra-ui/cli": "^2.4.0", + "@chakra-ui/icons": "^2.0.19", + "@chakra-ui/react": "^2.6.0", + "@chakra-ui/styled-system": "^2.9.0", "@chakra-ui/theme-tools": "^2.0.16", "@dagrejs/graphlib": "^2.1.12", "@emotion/react": "^11.10.6", "@emotion/styled": "^11.10.6", "@fontsource/inter": "^4.5.15", - "@reduxjs/toolkit": "^1.9.3", + "@reduxjs/toolkit": "^1.9.5", "chakra-ui-contextmenu": "^1.0.5", "dateformat": "^5.0.3", "formik": "^2.2.9", - "framer-motion": "^9.0.4", + "framer-motion": "^10.12.4", "fuse.js": "^6.6.2", - "i18next": "^22.4.10", + "i18next": "^22.4.15", "i18next-browser-languagedetector": "^7.0.1", - "i18next-http-backend": "^2.1.1", - "konva": "^8.4.2", + "i18next-http-backend": "^2.2.0", + "konva": "^9.0.1", "lodash": "^4.17.21", - "patch-package": "^6.5.1", + "patch-package": "^7.0.0", "re-resizable": "^6.9.9", "react": "^18.2.0", "react-colorful": "^5.6.1", "react-dom": "^18.2.0", "react-dropzone": "^14.2.3", - "react-hotkeys-hook": "4.3.5", - "react-i18next": "^12.1.5", + "react-hotkeys-hook": "4.4.0", + "react-i18next": "^12.2.2", "react-icons": "^4.7.1", - "react-konva": "^18.2.4", - "react-konva-utils": "^0.3.2", + "react-konva": "^18.2.7", + "react-konva-utils": "^1.0.4", "react-redux": "^8.0.5", "react-transition-group": "^4.4.5", - "react-zoom-pan-pinch": "^2.6.1", + "react-zoom-pan-pinch": "^3.0.7", "reactflow": "^11.7.0", "redux-deep-persist": "^1.0.7", "redux-dynamic-middlewares": "^2.2.0", @@ -85,36 +85,35 @@ "devDependencies": { "@types/dateformat": "^5.0.0", "@types/lodash": "^4.14.194", - "@types/react": "^18.0.28", - "@types/react-dom": "^18.0.11", + "@types/react": "^18.2.0", + "@types/react-dom": "^18.2.1", "@types/react-transition-group": "^4.4.5", "@types/uuid": "^9.0.0", - "@typescript-eslint/eslint-plugin": "^5.52.0", - "@typescript-eslint/parser": "^5.52.0", - "@vitejs/plugin-react-swc": "^3.2.0", - "axios": "^1.3.4", + "@typescript-eslint/eslint-plugin": "^5.59.1", + "@typescript-eslint/parser": "^5.59.1", + "@vitejs/plugin-react-swc": "^3.3.0", + "axios": "^1.4.0", "babel-plugin-transform-imports": "^2.0.0", - "concurrently": "^7.6.0", - "eslint": "^8.34.0", - "eslint-config-prettier": "^8.6.0", + "concurrently": "^8.0.1", + "eslint": "^8.39.0", + "eslint-config-prettier": "^8.8.0", "eslint-plugin-prettier": "^4.2.1", "eslint-plugin-react": "^7.32.2", "eslint-plugin-react-hooks": "^4.6.0", "form-data": "^4.0.0", "husky": "^8.0.3", - "lint-staged": "^13.1.2", + "lint-staged": "^13.2.2", "madge": "^6.0.0", "openapi-types": "^12.1.0", - "openapi-typescript-codegen": "^0.23.0", + "openapi-typescript-codegen": "^0.24.0", "postinstall-postinstall": "^2.1.0", - "prettier": "^2.8.4", + "prettier": "^2.8.8", "rollup-plugin-visualizer": "^5.9.0", - "terser": "^5.16.4", + "terser": "^5.17.1", "ts-toolbelt": "^9.6.0", - "typescript": "4.9.5", - "vite": "^4.1.2", + "vite": "^4.3.3", "vite-plugin-eslint": "^1.8.1", - "vite-tsconfig-paths": "^4.0.5", + "vite-tsconfig-paths": "^4.2.0", "yarn": "^1.22.19" } } diff --git a/invokeai/frontend/web/patches/@chakra-ui+cli+2.3.0.patch b/invokeai/frontend/web/patches/@chakra-ui+cli+2.4.0.patch similarity index 100% rename from invokeai/frontend/web/patches/@chakra-ui+cli+2.3.0.patch rename to invokeai/frontend/web/patches/@chakra-ui+cli+2.4.0.patch diff --git a/invokeai/frontend/web/yarn.lock b/invokeai/frontend/web/yarn.lock index 7cc6ab769b..1e9bff0197 100644 --- a/invokeai/frontend/web/yarn.lock +++ b/invokeai/frontend/web/yarn.lock @@ -13,18 +13,18 @@ js-yaml "^4.1.0" "@babel/code-frame@^7.0.0": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.18.6.tgz#3b25d38c89600baa2dcc219edfa88a74eb2c427a" - integrity sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q== + version "7.21.4" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.21.4.tgz#d0fa9e4413aca81f2b23b9442797bda1826edb39" + integrity sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g== dependencies: "@babel/highlight" "^7.18.6" "@babel/helper-module-imports@^7.16.7": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz#1e3ebdbbd08aad1437b428c50204db13c5a3ca6e" - integrity sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA== + version "7.21.4" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.21.4.tgz#ac88b2f76093637489e718a90cec6cf8a9b029af" + integrity sha512-orajc5T2PsRYUN3ZryCEFeMDYwyw09c/pZeaQEZPH0MpKzSvn3e0uXsDBu3k03VI+9DBiRo+l22BfKTpKwa/Wg== dependencies: - "@babel/types" "^7.18.6" + "@babel/types" "^7.21.4" "@babel/helper-string-parser@^7.19.4": version "7.19.4" @@ -45,10 +45,10 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.0.0": - version "7.21.2" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.21.2.tgz#dacafadfc6d7654c3051a66d6fe55b6cb2f2a0b3" - integrity sha512-URpaIJQwEkEC2T9Kn+Ai6Xe/02iNaVCuT/PtoRz3GPVJVDpPd7mLo+VddTbhCRU9TXqW5mSrQfXZyi8kDKOVpQ== +"@babel/parser@^7.0.0", "@babel/parser@^7.21.4": + version "7.21.4" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.21.4.tgz#94003fdfc520bbe2875d4ae557b43ddb6d880f17" + integrity sha512-alVJj7k7zIxqBZ7BTRhz0IqJFxW1VJbm6N8JbcYhQ186df9ZBPbZBmWSqAMXwHGsCJdYks7z/voa3ibiS5bCIw== "@babel/runtime@^7.0.0", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.18.3", "@babel/runtime@^7.19.4", "@babel/runtime@^7.20.6", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": version "7.21.0" @@ -57,35 +57,35 @@ dependencies: regenerator-runtime "^0.13.11" -"@babel/types@^7.18.6", "@babel/types@^7.4": - version "7.21.2" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.21.2.tgz#92246f6e00f91755893c2876ad653db70c8310d1" - integrity sha512-3wRZSs7jiFaB8AjxiiD+VqN5DTG2iRvJGQ+qYFrs/654lg6kGTQWIOFjlBo5RaXuAZjBmP3+OQH4dmhqiiyYxw== +"@babel/types@^7.21.4", "@babel/types@^7.4": + version "7.21.4" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.21.4.tgz#2d5d6bb7908699b3b416409ffd3b5daa25b030d4" + integrity sha512-rU2oY501qDxE8Pyo7i/Orqma4ziCOrby0/9mvbDUGEfvZjb279Nk9k19e2fiCxHbRRpY2ZyrgW1eq22mvmOIzA== dependencies: "@babel/helper-string-parser" "^7.19.4" "@babel/helper-validator-identifier" "^7.19.1" to-fast-properties "^2.0.0" -"@chakra-ui/accordion@2.1.9": - version "2.1.9" - resolved "https://registry.yarnpkg.com/@chakra-ui/accordion/-/accordion-2.1.9.tgz#20fa86d94dc034251df2f7c8595ae4dd541a29d9" - integrity sha512-a9CKIAUHezc0f5FR/SQ4GVxnWuIb2HbDTxTEKTp58w/J9pecIbJaNrJ5TUZ0MVbDU9jkgO9RsZ29jkja8PomAw== +"@chakra-ui/accordion@2.1.11": + version "2.1.11" + resolved "https://registry.yarnpkg.com/@chakra-ui/accordion/-/accordion-2.1.11.tgz#c6df0100c543645d0631df3aefde2ea2b8ed6313" + integrity sha512-mfVPmqETp9pyRDHJ33AdF19oHv/LyxVzQJtlxUByuvs8Cj9QQZ2LQLg5kejm+b3mj03A7A6yfbuo3RNaI4Bhsg== dependencies: - "@chakra-ui/descendant" "3.0.13" + "@chakra-ui/descendant" "3.0.14" "@chakra-ui/icon" "3.0.16" - "@chakra-ui/react-context" "2.0.7" + "@chakra-ui/react-context" "2.0.8" "@chakra-ui/react-use-controllable-state" "2.0.8" "@chakra-ui/react-use-merge-refs" "2.0.7" "@chakra-ui/shared-utils" "2.0.5" - "@chakra-ui/transition" "2.0.15" + "@chakra-ui/transition" "2.0.16" -"@chakra-ui/alert@2.0.17": - version "2.0.17" - resolved "https://registry.yarnpkg.com/@chakra-ui/alert/-/alert-2.0.17.tgz#b129732ec308db6a6a1afa7c06a6595ad853c967" - integrity sha512-0Y5vw+HkeXpwbL1roVpSSNM6luMRmUbwduUSHEA4OnX1ismvsDb1ZBfpi4Vxp6w8euJ2Uj6df3krbd5tbCP6tg== +"@chakra-ui/alert@2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@chakra-ui/alert/-/alert-2.1.0.tgz#7a234ac6426231b39243088648455cbcf1cbdf24" + integrity sha512-OcfHwoXI5VrmM+tHJTHT62Bx6TfyfCxSa0PWUOueJzSyhlUOKBND5we6UtrOB7D0jwX45qKKEDJOLG5yCG21jQ== dependencies: "@chakra-ui/icon" "3.0.16" - "@chakra-ui/react-context" "2.0.7" + "@chakra-ui/react-context" "2.0.8" "@chakra-ui/shared-utils" "2.0.5" "@chakra-ui/spinner" "2.0.13" @@ -99,23 +99,23 @@ resolved "https://registry.yarnpkg.com/@chakra-ui/anatomy/-/anatomy-2.1.2.tgz#ea66b1841e7195da08ddc862daaa3f3e56e565f5" integrity sha512-pKfOS/mztc4sUXHNc8ypJ1gPWSolWT770jrgVRfolVbYlki8y5Y+As996zMF6k5lewTu6j9DQequ7Cc9a69IVQ== -"@chakra-ui/avatar@2.2.5": - version "2.2.5" - resolved "https://registry.yarnpkg.com/@chakra-ui/avatar/-/avatar-2.2.5.tgz#50eb7cc5a172d394b301fa0abd5f607b7f5d3563" - integrity sha512-TEHXuGE79+fEn61qJ7J/A0Ec+WjyNwobrDTATcLg9Zx2/WEMmZNfrWIAlI5ANQAwVbdSWeGVbyoLAK5mbcrE0A== +"@chakra-ui/avatar@2.2.9": + version "2.2.9" + resolved "https://registry.yarnpkg.com/@chakra-ui/avatar/-/avatar-2.2.9.tgz#7dc21f432f3ab52d05c3ac66641412896cd08b19" + integrity sha512-fjO25iNeMxSZKYGvbAqdMjsRus9Hgvhb+Ux8jNwKcfg47nqT+wVieMqsPdpQ0ggAuh1872oVvg2q1GfDdieMmA== dependencies: - "@chakra-ui/image" "2.0.15" + "@chakra-ui/image" "2.0.16" "@chakra-ui/react-children-utils" "2.0.6" - "@chakra-ui/react-context" "2.0.7" + "@chakra-ui/react-context" "2.0.8" "@chakra-ui/shared-utils" "2.0.5" -"@chakra-ui/breadcrumb@2.1.4": - version "2.1.4" - resolved "https://registry.yarnpkg.com/@chakra-ui/breadcrumb/-/breadcrumb-2.1.4.tgz#0d249dc2a92639bd2bf46d097dd5445112bd2367" - integrity sha512-vyBx5TAxPnHhb0b8nyRGfqyjleD//9mySFhk96c9GL+T6YDO4swHw5y/kvDv3Ngc/iRwJ9hdI49PZKwPxLqsEg== +"@chakra-ui/breadcrumb@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@chakra-ui/breadcrumb/-/breadcrumb-2.1.5.tgz#a43b22cc8005291a615696a8c88efc37064562f3" + integrity sha512-p3eQQrHQBkRB69xOmNyBJqEdfCrMt+e0eOH+Pm/DjFWfIVIbnIaFbmDCeWClqlLa21Ypc6h1hR9jEmvg8kmOog== dependencies: "@chakra-ui/react-children-utils" "2.0.6" - "@chakra-ui/react-context" "2.0.7" + "@chakra-ui/react-context" "2.0.8" "@chakra-ui/shared-utils" "2.0.5" "@chakra-ui/breakpoint-utils@2.0.8": @@ -125,12 +125,12 @@ dependencies: "@chakra-ui/shared-utils" "2.0.5" -"@chakra-ui/button@2.0.16": - version "2.0.16" - resolved "https://registry.yarnpkg.com/@chakra-ui/button/-/button-2.0.16.tgz#ff315b57ee47c3511a6507fcfb6f00bb93e2ac7d" - integrity sha512-NjuTKa7gNhnGSUutKuTc8HoAOe9WWIigpciBG7yj3ok67kg8bXtSzPyQFZlgTY6XGdAckWTT+Do4tvhwa5LA+g== +"@chakra-ui/button@2.0.18": + version "2.0.18" + resolved "https://registry.yarnpkg.com/@chakra-ui/button/-/button-2.0.18.tgz#c13d2e404e22a9873ba5373fde494bedafe32fdd" + integrity sha512-E3c99+lOm6ou4nQVOTLkG+IdOPMjsQK+Qe7VyP8A/xeAMFONuibrWPRPpprr4ZkB4kEoLMfNuyH2+aEza3ScUA== dependencies: - "@chakra-ui/react-context" "2.0.7" + "@chakra-ui/react-context" "2.0.8" "@chakra-ui/react-use-merge-refs" "2.0.7" "@chakra-ui/shared-utils" "2.0.5" "@chakra-ui/spinner" "2.0.13" @@ -142,13 +142,13 @@ dependencies: "@chakra-ui/shared-utils" "2.0.5" -"@chakra-ui/checkbox@2.2.10": - version "2.2.10" - resolved "https://registry.yarnpkg.com/@chakra-ui/checkbox/-/checkbox-2.2.10.tgz#e4f773e7d2464f1d6e9d18dd88b679290cb33171" - integrity sha512-vzxEjw99qj7loxAdP1WuHNt4EAvj/t6cc8oxyOB2mEvkAzhxI34rLR+3zWDuHWsmhyUO+XEDh4FiWdR+DK5Siw== +"@chakra-ui/checkbox@2.2.15": + version "2.2.15" + resolved "https://registry.yarnpkg.com/@chakra-ui/checkbox/-/checkbox-2.2.15.tgz#e5ff65159f698d50edecee6b661b87e341eace70" + integrity sha512-Ju2yQjX8azgFa5f6VLPuwdGYobZ+rdbcYqjiks848JvPc75UsPhpS05cb4XlrKT7M16I8txDA5rPJdqqFicHCA== dependencies: - "@chakra-ui/form-control" "2.0.17" - "@chakra-ui/react-context" "2.0.7" + "@chakra-ui/form-control" "2.0.18" + "@chakra-ui/react-context" "2.0.8" "@chakra-ui/react-types" "2.0.7" "@chakra-ui/react-use-callback-ref" "2.0.7" "@chakra-ui/react-use-controllable-state" "2.0.8" @@ -157,12 +157,12 @@ "@chakra-ui/react-use-update-effect" "2.0.7" "@chakra-ui/shared-utils" "2.0.5" "@chakra-ui/visually-hidden" "2.0.15" - "@zag-js/focus-visible" "0.2.1" + "@zag-js/focus-visible" "0.2.2" -"@chakra-ui/cli@^2.3.0": - version "2.3.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/cli/-/cli-2.3.0.tgz#66f229b91c53c9738fb1592ba8b0bc4b1c55f16f" - integrity sha512-63Xs4aMYxc17U8GfyPuQnAv8qRg/z2oCd8lgAdn6m755lvQ0e5RZ+mNecfJN1uNXRs3BmKXWnmGh1NvfQ6q1UQ== +"@chakra-ui/cli@^2.4.0": + version "2.4.0" + resolved "https://registry.yarnpkg.com/@chakra-ui/cli/-/cli-2.4.0.tgz#720b6cd36b96ebc13894a659c566c3a31dd87961" + integrity sha512-Ko8bnQ4lbSwoldHyf2aHANuITL09XTlLJFAKCvgN/e/G+ZuL9ciHnITNG9nchLZKiK6mNj7o8pVfRbxkLm5xVw== dependencies: "@swc/core" "^1.2.177" chokidar "^3.5.3" @@ -214,17 +214,17 @@ "@chakra-ui/react-use-callback-ref" "2.0.7" "@chakra-ui/shared-utils" "2.0.5" -"@chakra-ui/css-reset@2.0.12": - version "2.0.12" - resolved "https://registry.yarnpkg.com/@chakra-ui/css-reset/-/css-reset-2.0.12.tgz#6eebcbe9e971facd215e174e063ace29f647a045" - integrity sha512-Q5OYIMvqTl2vZ947kIYxcS5DhQXeStB84BzzBd6C10wOx1gFUu9pL+jLpOnHR3hhpWRMdX5o7eT+gMJWIYUZ0Q== +"@chakra-ui/css-reset@2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@chakra-ui/css-reset/-/css-reset-2.1.1.tgz#c61f3d2103c13e62a86fd2d359682092e961852c" + integrity sha512-jwEOfIAWmQsnChHQTW/eRE+dfE4MjmhvSvoUug5nkV1pI7veC/20noFlIZxzi82EbiQI8Fs0+Jnusgxr2yaOHA== -"@chakra-ui/descendant@3.0.13": - version "3.0.13" - resolved "https://registry.yarnpkg.com/@chakra-ui/descendant/-/descendant-3.0.13.tgz#e883a2233ee07fe1ae6c014567824c0f79df11cf" - integrity sha512-9nzxZVxUSMc4xPL5fSaRkEOQjDQWUGjGvrZI7VzWk9eq63cojOtIxtWMSW383G9148PzWJjJYt30Eud5tdZzlg== +"@chakra-ui/descendant@3.0.14": + version "3.0.14" + resolved "https://registry.yarnpkg.com/@chakra-ui/descendant/-/descendant-3.0.14.tgz#fe8bac3f0e1ffe562e3e73eac393dbf222d57e13" + integrity sha512-+Ahvp9H4HMpfScIv9w1vaecGz7qWAaK1YFHHolz/SIsGLaLGlbdp+5UNabQC7L6TUnzzJDQDxzwif78rTD7ang== dependencies: - "@chakra-ui/react-context" "2.0.7" + "@chakra-ui/react-context" "2.0.8" "@chakra-ui/react-use-merge-refs" "2.0.7" "@chakra-ui/dom-utils@2.0.6": @@ -232,12 +232,12 @@ resolved "https://registry.yarnpkg.com/@chakra-ui/dom-utils/-/dom-utils-2.0.6.tgz#68f49f3b4a0bdebd5e416d6fd2c012c9ad64b76a" integrity sha512-PVtDkPrDD5b8aoL6Atg7SLjkwhWb7BwMcLOF1L449L3nZN+DAO3nyAh6iUhZVJyunELj9d0r65CDlnMREyJZmA== -"@chakra-ui/editable@2.0.19": - version "2.0.19" - resolved "https://registry.yarnpkg.com/@chakra-ui/editable/-/editable-2.0.19.tgz#1af2fe3c215111f61f7872fb5f599f4d8da24e7d" - integrity sha512-YxRJsJ2JQd42zfPBgTKzIhg1HugT+gfQz1ZosmUN+IZT9YZXL2yodHTUz6Lee04Vc/CdEqgBFLuREXEUNBfGtA== +"@chakra-ui/editable@3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@chakra-ui/editable/-/editable-3.0.0.tgz#b61d4fba5a581b41856ebd85fd5d17c96a224323" + integrity sha512-q/7C/TM3iLaoQKlEiM8AY565i9NoaXtS6N6N4HWIEL5mZJPbMeHKxrCHUZlHxYuQJqFOGc09ZPD9fAFx1GkYwQ== dependencies: - "@chakra-ui/react-context" "2.0.7" + "@chakra-ui/react-context" "2.0.8" "@chakra-ui/react-types" "2.0.7" "@chakra-ui/react-use-callback-ref" "2.0.7" "@chakra-ui/react-use-controllable-state" "2.0.8" @@ -260,21 +260,21 @@ "@chakra-ui/dom-utils" "2.0.6" react-focus-lock "^2.9.2" -"@chakra-ui/form-control@2.0.17": - version "2.0.17" - resolved "https://registry.yarnpkg.com/@chakra-ui/form-control/-/form-control-2.0.17.tgz#2f710325e77ce35067337616d440f903b137bdd5" - integrity sha512-34ptCaJ2LNvQNOlB6MAKsmH1AkT1xo7E+3Vw10Urr81yTOjDTM/iU6vG3JKPfRDMyXeowPjXmutlnuk72SSjRg== +"@chakra-ui/form-control@2.0.18": + version "2.0.18" + resolved "https://registry.yarnpkg.com/@chakra-ui/form-control/-/form-control-2.0.18.tgz#1923f293afde70b2b07ca731d98fef3660098c56" + integrity sha512-I0a0jG01IAtRPccOXSNugyRdUAe8Dy40ctqedZvznMweOXzbMCF1m+sHPLdWeWC/VI13VoAispdPY0/zHOdjsQ== dependencies: "@chakra-ui/icon" "3.0.16" - "@chakra-ui/react-context" "2.0.7" + "@chakra-ui/react-context" "2.0.8" "@chakra-ui/react-types" "2.0.7" "@chakra-ui/react-use-merge-refs" "2.0.7" "@chakra-ui/shared-utils" "2.0.5" -"@chakra-ui/hooks@2.1.6": - version "2.1.6" - resolved "https://registry.yarnpkg.com/@chakra-ui/hooks/-/hooks-2.1.6.tgz#4d829535868148912ef7a4ff274e03b8d1cf7c72" - integrity sha512-oMSOeoOF6/UpwTVlDFHSROAA4hPY8WgJ0erdHs1ZkuwAwHv7UzjDkvrb6xYzAAH9qHoFzc5RIBm6jVoh3LCc+Q== +"@chakra-ui/hooks@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@chakra-ui/hooks/-/hooks-2.2.0.tgz#f779bf85542dacd607abe7e67f4571cf8a1102fa" + integrity sha512-GZE64mcr20w+3KbCUPqQJHHmiFnX5Rcp8jS3YntGA4D5X2qU85jka7QkjfBwv/iduZ5Ei0YpCMYGCpi91dhD1Q== dependencies: "@chakra-ui/react-utils" "2.0.12" "@chakra-ui/utils" "2.0.15" @@ -288,42 +288,42 @@ dependencies: "@chakra-ui/shared-utils" "2.0.5" -"@chakra-ui/icons@^2.0.17": - version "2.0.17" - resolved "https://registry.yarnpkg.com/@chakra-ui/icons/-/icons-2.0.17.tgz#625a46d169707aad36d65c04a4626a422f92e5ae" - integrity sha512-HMJP0WrJgAmFR9+Xh/CBH0nVnGMsJ4ZC8MK6tMgxPKd9/muvn0I4hsicHqdPlLpmB0TlxlhkBAKaVMtOdz6F0w== +"@chakra-ui/icons@^2.0.19": + version "2.0.19" + resolved "https://registry.yarnpkg.com/@chakra-ui/icons/-/icons-2.0.19.tgz#b4581a59c2e2a2b95b01ab251eabb8cf984bb00f" + integrity sha512-0A6U1ZBZhLIxh3QgdjuvIEhAZi3B9v8g6Qvlfa3mu6vSnXQn2CHBZXmJwxpXxO40NK/2gj/gKXrLeUaFR6H/Qw== dependencies: "@chakra-ui/icon" "3.0.16" -"@chakra-ui/image@2.0.15": - version "2.0.15" - resolved "https://registry.yarnpkg.com/@chakra-ui/image/-/image-2.0.15.tgz#7f275f8f3edbb420e0613afd5023ad9cf442d09d" - integrity sha512-w2rElXtI3FHXuGpMCsSklus+pO1Pl2LWDwsCGdpBQUvGFbnHfl7MftQgTlaGHeD5OS95Pxva39hKrA2VklKHiQ== +"@chakra-ui/image@2.0.16": + version "2.0.16" + resolved "https://registry.yarnpkg.com/@chakra-ui/image/-/image-2.0.16.tgz#0e3a48c3caa6dc1d340502ea96766d9ef31e27e8" + integrity sha512-iFypk1slgP3OK7VIPOtkB0UuiqVxNalgA59yoRM43xLIeZAEZpKngUVno4A2kFS61yKN0eIY4hXD3Xjm+25EJA== dependencies: "@chakra-ui/react-use-safe-layout-effect" "2.0.5" "@chakra-ui/shared-utils" "2.0.5" -"@chakra-ui/input@2.0.20": - version "2.0.20" - resolved "https://registry.yarnpkg.com/@chakra-ui/input/-/input-2.0.20.tgz#8db3ec46b52be901c94599b3659a9003bdb2dd07" - integrity sha512-ypmsy4n4uNBVgn6Gd24Zrpi+qRf/T9WEzWkysuYC9Qfxo+i7yuf3snp7XmBy8KSGVSiXE11eO8ZN5oCg6Xg0jg== +"@chakra-ui/input@2.0.22": + version "2.0.22" + resolved "https://registry.yarnpkg.com/@chakra-ui/input/-/input-2.0.22.tgz#4c1f166f53555c698bb65950772314f78c147450" + integrity sha512-dCIC0/Q7mjZf17YqgoQsnXn0bus6vgriTRn8VmxOc+WcVl+KBSTBWujGrS5yu85WIFQ0aeqQvziDnDQybPqAbA== dependencies: - "@chakra-ui/form-control" "2.0.17" - "@chakra-ui/object-utils" "2.0.8" + "@chakra-ui/form-control" "2.0.18" + "@chakra-ui/object-utils" "2.1.0" "@chakra-ui/react-children-utils" "2.0.6" - "@chakra-ui/react-context" "2.0.7" + "@chakra-ui/react-context" "2.0.8" "@chakra-ui/shared-utils" "2.0.5" -"@chakra-ui/layout@2.1.16": - version "2.1.16" - resolved "https://registry.yarnpkg.com/@chakra-ui/layout/-/layout-2.1.16.tgz#9d90f25cf9f0537d19cd36a417f7ddc1461e8591" - integrity sha512-QFS3feozIGsvB0H74lUocev55aRF26eNrdmhfJifwikZAiq+zzZAMdBdNU9UJhHClnMOU8/iGZ0MF7ti4zQS1A== +"@chakra-ui/layout@2.1.19": + version "2.1.19" + resolved "https://registry.yarnpkg.com/@chakra-ui/layout/-/layout-2.1.19.tgz#4cd07c64239bf83c89a49487fdbd44227737b4eb" + integrity sha512-g7xMVKbQFCODwKCkEF4/OmdPsr/fAavWUV+DGc1ZWVPdroUlg1FGTpK9bOTwkC/gnko7cMClILA+BIPR3Ylu9Q== dependencies: "@chakra-ui/breakpoint-utils" "2.0.8" "@chakra-ui/icon" "3.0.16" - "@chakra-ui/object-utils" "2.0.8" + "@chakra-ui/object-utils" "2.1.0" "@chakra-ui/react-children-utils" "2.0.6" - "@chakra-ui/react-context" "2.0.7" + "@chakra-ui/react-context" "2.0.8" "@chakra-ui/shared-utils" "2.0.5" "@chakra-ui/lazy-utils@2.0.5": @@ -345,52 +345,52 @@ "@chakra-ui/react-env" "3.0.0" "@chakra-ui/shared-utils" "2.0.5" -"@chakra-ui/menu@2.1.9": - version "2.1.9" - resolved "https://registry.yarnpkg.com/@chakra-ui/menu/-/menu-2.1.9.tgz#2f3239a9b2855fd77fc317d9e6b904c1ad50d7c6" - integrity sha512-ue5nD4QJcl3H3UwN0zZNJmH89XUebnvEdW6THAUL41hDjJ0J/Fjpg9Sgzwug2aBbBXBNbVMsUuhcCj6x91d+IQ== +"@chakra-ui/menu@2.1.13": + version "2.1.13" + resolved "https://registry.yarnpkg.com/@chakra-ui/menu/-/menu-2.1.13.tgz#c76bab6ba1daf33974e3467fd590319d1973bc3b" + integrity sha512-O7ESUIxbqWINRaO9jkPbZ8vJVW+lxZIZ9K0q828XgYBMh5o7BS82XhT7li7CxWaSQNqBxS4XE9BU7btp1ADMrQ== dependencies: "@chakra-ui/clickable" "2.0.14" - "@chakra-ui/descendant" "3.0.13" + "@chakra-ui/descendant" "3.0.14" "@chakra-ui/lazy-utils" "2.0.5" "@chakra-ui/popper" "3.0.13" "@chakra-ui/react-children-utils" "2.0.6" - "@chakra-ui/react-context" "2.0.7" + "@chakra-ui/react-context" "2.0.8" "@chakra-ui/react-use-animation-state" "2.0.8" "@chakra-ui/react-use-controllable-state" "2.0.8" "@chakra-ui/react-use-disclosure" "2.0.8" - "@chakra-ui/react-use-focus-effect" "2.0.9" + "@chakra-ui/react-use-focus-effect" "2.0.10" "@chakra-ui/react-use-merge-refs" "2.0.7" - "@chakra-ui/react-use-outside-click" "2.0.7" + "@chakra-ui/react-use-outside-click" "2.1.0" "@chakra-ui/react-use-update-effect" "2.0.7" "@chakra-ui/shared-utils" "2.0.5" - "@chakra-ui/transition" "2.0.15" + "@chakra-ui/transition" "2.0.16" -"@chakra-ui/modal@2.2.9": - version "2.2.9" - resolved "https://registry.yarnpkg.com/@chakra-ui/modal/-/modal-2.2.9.tgz#aad65a2c60aa974e023f8b3facc0e79eb742e006" - integrity sha512-nTfNp7XsVwn5+xJOtstoFA8j0kq/9sJj7KesyYzjEDaMKvCZvIOntRYowoydho43jb4+YC7ebKhp0KOIINS0gg== +"@chakra-ui/modal@2.2.11": + version "2.2.11" + resolved "https://registry.yarnpkg.com/@chakra-ui/modal/-/modal-2.2.11.tgz#8a964288759f3d681e23bfc3a837a3e2c7523f8e" + integrity sha512-2J0ZUV5tEzkPiawdkgPz6bmex7NXAde1VXooMwdvK+vuT8PV3U61yorTJOZVLdw7TjjI1Yo94mzsp6UwBud43Q== dependencies: "@chakra-ui/close-button" "2.0.17" "@chakra-ui/focus-lock" "2.0.16" - "@chakra-ui/portal" "2.0.15" - "@chakra-ui/react-context" "2.0.7" + "@chakra-ui/portal" "2.0.16" + "@chakra-ui/react-context" "2.0.8" "@chakra-ui/react-types" "2.0.7" "@chakra-ui/react-use-merge-refs" "2.0.7" "@chakra-ui/shared-utils" "2.0.5" - "@chakra-ui/transition" "2.0.15" + "@chakra-ui/transition" "2.0.16" aria-hidden "^1.2.2" react-remove-scroll "^2.5.5" -"@chakra-ui/number-input@2.0.18": - version "2.0.18" - resolved "https://registry.yarnpkg.com/@chakra-ui/number-input/-/number-input-2.0.18.tgz#072a00ef869ebafa4960cfdee8caae8208864289" - integrity sha512-cPkyAFFHHzeFBselrT1BtjlzMkJ6TKrTDUnHFlzqXy6aqeXuhrjFhMfXucjedSpOqedsP9ZbKFTdIAhu9DdL/A== +"@chakra-ui/number-input@2.0.19": + version "2.0.19" + resolved "https://registry.yarnpkg.com/@chakra-ui/number-input/-/number-input-2.0.19.tgz#82d4522036904c04d07e7050822fc522f9b32233" + integrity sha512-HDaITvtMEqOauOrCPsARDxKD9PSHmhWywpcyCSOX0lMe4xx2aaGhU0QQFhsJsykj8Er6pytMv6t0KZksdDv3YA== dependencies: "@chakra-ui/counter" "2.0.14" - "@chakra-ui/form-control" "2.0.17" + "@chakra-ui/form-control" "2.0.18" "@chakra-ui/icon" "3.0.16" - "@chakra-ui/react-context" "2.0.7" + "@chakra-ui/react-context" "2.0.8" "@chakra-ui/react-types" "2.0.7" "@chakra-ui/react-use-callback-ref" "2.0.7" "@chakra-ui/react-use-event-listener" "2.0.7" @@ -405,36 +405,36 @@ resolved "https://registry.yarnpkg.com/@chakra-ui/number-utils/-/number-utils-2.0.7.tgz#aaee979ca2fb1923a0373a91619473811315db11" integrity sha512-yOGxBjXNvLTBvQyhMDqGU0Oj26s91mbAlqKHiuw737AXHt0aPllOthVUqQMeaYLwLCjGMg0jtI7JReRzyi94Dg== -"@chakra-ui/object-utils@2.0.8": - version "2.0.8" - resolved "https://registry.yarnpkg.com/@chakra-ui/object-utils/-/object-utils-2.0.8.tgz#307f927f6434f99feb32ba92bdf451a6b59a6199" - integrity sha512-2upjT2JgRuiupdrtBWklKBS6tqeGMA77Nh6Q0JaoQuH/8yq+15CGckqn3IUWkWoGI0Fg3bK9LDlbbD+9DLw95Q== +"@chakra-ui/object-utils@2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@chakra-ui/object-utils/-/object-utils-2.1.0.tgz#a4ecf9cea92f1de09f5531f53ffdc41e0b19b6c3" + integrity sha512-tgIZOgLHaoti5PYGPTwK3t/cqtcycW0owaiOXoZOcpwwX/vlVb+H1jFsQyWiiwQVPt9RkoSLtxzXamx+aHH+bQ== -"@chakra-ui/pin-input@2.0.19": - version "2.0.19" - resolved "https://registry.yarnpkg.com/@chakra-ui/pin-input/-/pin-input-2.0.19.tgz#f9b196174f0518feec5c1ee3fcaf2134c301148a" - integrity sha512-6O7s4vWz4cqQ6zvMov9sYj6ZqWAsTxR/MNGe3DNgu1zWQg8veNCYtj1rNGhNS3eZNUMAa8uM2dXIphGTP53Xow== +"@chakra-ui/pin-input@2.0.20": + version "2.0.20" + resolved "https://registry.yarnpkg.com/@chakra-ui/pin-input/-/pin-input-2.0.20.tgz#5bf115bf4282b69fc6532a9c542cbf41f815d200" + integrity sha512-IHVmerrtHN8F+jRB3W1HnMir1S1TUCWhI7qDInxqPtoRffHt6mzZgLZ0izx8p1fD4HkW4c1d4/ZLEz9uH9bBRg== dependencies: - "@chakra-ui/descendant" "3.0.13" + "@chakra-ui/descendant" "3.0.14" "@chakra-ui/react-children-utils" "2.0.6" - "@chakra-ui/react-context" "2.0.7" + "@chakra-ui/react-context" "2.0.8" "@chakra-ui/react-use-controllable-state" "2.0.8" "@chakra-ui/react-use-merge-refs" "2.0.7" "@chakra-ui/shared-utils" "2.0.5" -"@chakra-ui/popover@2.1.8": - version "2.1.8" - resolved "https://registry.yarnpkg.com/@chakra-ui/popover/-/popover-2.1.8.tgz#e906ce0533693d735b6e13a3a6ffe16d8e0a9ab4" - integrity sha512-ob7fAz+WWmXIq7iGHVB3wDKzZTj+T+noYBT/U1Q+jIf+jMr2WOpJLTfb0HTZcfhvn4EBFlfBg7Wk5qbXNaOn7g== +"@chakra-ui/popover@2.1.10": + version "2.1.10" + resolved "https://registry.yarnpkg.com/@chakra-ui/popover/-/popover-2.1.10.tgz#0079d4dbbabaf1a549c2385e3580d710de7c45e2" + integrity sha512-UCEW+zp2GEuNYvyK42+cQECSMSBFWcA0CD7Ip6TUL32BLF8EkYz5U5Gdx5Nhd/mlSE2lxo7c72/LOQd0emsO/A== dependencies: "@chakra-ui/close-button" "2.0.17" "@chakra-ui/lazy-utils" "2.0.5" "@chakra-ui/popper" "3.0.13" - "@chakra-ui/react-context" "2.0.7" + "@chakra-ui/react-context" "2.0.8" "@chakra-ui/react-types" "2.0.7" "@chakra-ui/react-use-animation-state" "2.0.8" "@chakra-ui/react-use-disclosure" "2.0.8" - "@chakra-ui/react-use-focus-effect" "2.0.9" + "@chakra-ui/react-use-focus-effect" "2.0.10" "@chakra-ui/react-use-focus-on-pointer-down" "2.0.6" "@chakra-ui/react-use-merge-refs" "2.0.7" "@chakra-ui/shared-utils" "2.0.5" @@ -448,53 +448,53 @@ "@chakra-ui/react-use-merge-refs" "2.0.7" "@popperjs/core" "^2.9.3" -"@chakra-ui/portal@2.0.15": - version "2.0.15" - resolved "https://registry.yarnpkg.com/@chakra-ui/portal/-/portal-2.0.15.tgz#21e1f97c4407fc15df8c365cb5cf799dac73ce41" - integrity sha512-z8v7K3j1/nMuBzp2+wRIIw7s/eipVtnXLdjK5yqbMxMRa44E8Mu5VNJLz3aQFLHXEUST+ifqrjImQeli9do6LQ== +"@chakra-ui/portal@2.0.16": + version "2.0.16" + resolved "https://registry.yarnpkg.com/@chakra-ui/portal/-/portal-2.0.16.tgz#e5ce3f9d9e559f17a95276e0c006d0e9b7703442" + integrity sha512-bVID0qbQ0l4xq38LdqAN4EKD4/uFkDnXzFwOlviC9sl0dNhzICDb1ltuH/Adl1d2HTMqyN60O3GO58eHy7plnQ== dependencies: - "@chakra-ui/react-context" "2.0.7" + "@chakra-ui/react-context" "2.0.8" "@chakra-ui/react-use-safe-layout-effect" "2.0.5" -"@chakra-ui/progress@2.1.5": - version "2.1.5" - resolved "https://registry.yarnpkg.com/@chakra-ui/progress/-/progress-2.1.5.tgz#eb6a47adf2bff93971262d163461d390782a04ff" - integrity sha512-jj5Vp4lxUchuwp4RPCepM0yAyKi344bgsOd3Apd+ldxclDcewPc82fbwDu7g/Xv27LqJkT+7E/SlQy04wGrk0g== +"@chakra-ui/progress@2.1.6": + version "2.1.6" + resolved "https://registry.yarnpkg.com/@chakra-ui/progress/-/progress-2.1.6.tgz#398db20440979c37adb0a34821f805ae3471873b" + integrity sha512-hHh5Ysv4z6bK+j2GJbi/FT9CVyto2PtNUNwBmr3oNMVsoOUMoRjczfXvvYqp0EHr9PCpxqrq7sRwgQXUzhbDSw== dependencies: - "@chakra-ui/react-context" "2.0.7" + "@chakra-ui/react-context" "2.0.8" -"@chakra-ui/provider@2.1.2": - version "2.1.2" - resolved "https://registry.yarnpkg.com/@chakra-ui/provider/-/provider-2.1.2.tgz#b025cb718826b003b3c9535b6961e8f3be70ebd5" - integrity sha512-4lLlz8QuJv00BhfyKzWpzfoti9MDOdJ/MqXixJV/EZ02RMBOdE9qy9bSz/WckPC2MVhtRUuwMkxH+0QY21PXuw== +"@chakra-ui/provider@2.2.3": + version "2.2.3" + resolved "https://registry.yarnpkg.com/@chakra-ui/provider/-/provider-2.2.3.tgz#a061891c26b38a1ac5a30e92e5c0b249ad1bc0cd" + integrity sha512-vLvs69tkq3D7sjmGV5ry8c93TKK0K5XfT2hTWr0QRPRvsccDSoEbYtCI8lb36kOZdXhYa/K8nd81vM+UBp0tzw== dependencies: - "@chakra-ui/css-reset" "2.0.12" - "@chakra-ui/portal" "2.0.15" + "@chakra-ui/css-reset" "2.1.1" + "@chakra-ui/portal" "2.0.16" "@chakra-ui/react-env" "3.0.0" - "@chakra-ui/system" "2.5.1" + "@chakra-ui/system" "2.5.6" "@chakra-ui/utils" "2.0.15" -"@chakra-ui/radio@2.0.19": - version "2.0.19" - resolved "https://registry.yarnpkg.com/@chakra-ui/radio/-/radio-2.0.19.tgz#8d5c02eae8eddbced4476b1b50921ade62f0a744" - integrity sha512-PlJiV59eGSmeKP4v/4+ccQUWGRd0cjPKkj/p3L+UbOf8pl9dWm8y9kIeL5TYbghQSDv0nzkrH4+yMnnDTZjdMQ== +"@chakra-ui/radio@2.0.22": + version "2.0.22" + resolved "https://registry.yarnpkg.com/@chakra-ui/radio/-/radio-2.0.22.tgz#fad0ce7c9ba4051991ed517cac4cfe526d6d47d9" + integrity sha512-GsQ5WAnLwivWl6gPk8P1x+tCcpVakCt5R5T0HumF7DGPXKdJbjS+RaFySrbETmyTJsKY4QrfXn+g8CWVrMjPjw== dependencies: - "@chakra-ui/form-control" "2.0.17" - "@chakra-ui/react-context" "2.0.7" + "@chakra-ui/form-control" "2.0.18" + "@chakra-ui/react-context" "2.0.8" "@chakra-ui/react-types" "2.0.7" "@chakra-ui/react-use-merge-refs" "2.0.7" "@chakra-ui/shared-utils" "2.0.5" - "@zag-js/focus-visible" "0.2.1" + "@zag-js/focus-visible" "0.2.2" "@chakra-ui/react-children-utils@2.0.6": version "2.0.6" resolved "https://registry.yarnpkg.com/@chakra-ui/react-children-utils/-/react-children-utils-2.0.6.tgz#6c480c6a60678fcb75cb7d57107c7a79e5179b92" integrity sha512-QVR2RC7QsOsbWwEnq9YduhpqSFnZGvjjGREV8ygKi8ADhXh93C8azLECCUVgRJF2Wc+So1fgxmjLcbZfY2VmBA== -"@chakra-ui/react-context@2.0.7": - version "2.0.7" - resolved "https://registry.yarnpkg.com/@chakra-ui/react-context/-/react-context-2.0.7.tgz#f79a2b072d04d4280ec8799dc03a8a1af521ca2e" - integrity sha512-i7EGmSU+h2GB30cwrKB4t1R5BMHyGoJM5L2Zz7b+ZUX4aAqyPcfe97wPiQB6Rgr1ImGXrUeov4CDVrRZ2FPgLQ== +"@chakra-ui/react-context@2.0.8": + version "2.0.8" + resolved "https://registry.yarnpkg.com/@chakra-ui/react-context/-/react-context-2.0.8.tgz#5e0ed33ac3995875a21dea0e12b0ee5fc4c2e3cc" + integrity sha512-tRTKdn6lCTXM6WPjSokAAKCw2ioih7Eg8cNgaYRSwKBck8nkz9YqxgIIEj3dJD7MGtpl24S/SNI98iRWkRwR/A== "@chakra-ui/react-env@3.0.0": version "3.0.0" @@ -542,10 +542,10 @@ dependencies: "@chakra-ui/react-use-callback-ref" "2.0.7" -"@chakra-ui/react-use-focus-effect@2.0.9": - version "2.0.9" - resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-focus-effect/-/react-use-focus-effect-2.0.9.tgz#9f94c0cb54e6e14ac9f048ca4d32a1fdcea067c1" - integrity sha512-20nfNkpbVwyb41q9wxp8c4jmVp6TUGAPE3uFTDpiGcIOyPW5aecQtPmTXPMJH+2aa8Nu1wyoT1btxO+UYiQM3g== +"@chakra-ui/react-use-focus-effect@2.0.10": + version "2.0.10" + resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-focus-effect/-/react-use-focus-effect-2.0.10.tgz#0328a85e05fd6f8927359a544184494b5cb947bd" + integrity sha512-HswfpzjP8gCQM3/fbeR+8wrYqt0B3ChnVTqssnYXqp9Fa/5Y1Kx1ZADUWW93zMs5SF7hIEuNt8uKeh1/3HTcqQ== dependencies: "@chakra-ui/dom-utils" "2.0.6" "@chakra-ui/react-use-event-listener" "2.0.7" @@ -576,10 +576,10 @@ resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-merge-refs/-/react-use-merge-refs-2.0.7.tgz#1a1fe800fb5501ec3da4088fbac78c03bbad13a7" integrity sha512-zds4Uhsc+AMzdH8JDDkLVet9baUBgtOjPbhC5r3A0ZXjZvGhCztFAVE3aExYiVoMPoHLKbLcqvCWE6ioFKz1lw== -"@chakra-ui/react-use-outside-click@2.0.7": - version "2.0.7" - resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-outside-click/-/react-use-outside-click-2.0.7.tgz#56c668f020fbc6331db4c3b61c8b845a68c4a134" - integrity sha512-MsAuGLkwYNxNJ5rb8lYNvXApXxYMnJ3MzqBpQj1kh5qP/+JSla9XMjE/P94ub4fSEttmNSqs43SmPPrmPuihsQ== +"@chakra-ui/react-use-outside-click@2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-outside-click/-/react-use-outside-click-2.1.0.tgz#f7e27653c470e516c55d79df67ed8b0ba2c4ec8d" + integrity sha512-JanCo4QtWvMl9ZZUpKJKV62RlMWDFdPCE0Q64a7eWTOQgWWcpyBW7TOYRunQTqrK30FqkYFJCOlAWOtn+6Rw7A== dependencies: "@chakra-ui/react-use-callback-ref" "2.0.7" @@ -602,12 +602,12 @@ resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-safe-layout-effect/-/react-use-safe-layout-effect-2.0.5.tgz#6cf388c37fd2a42b5295a292e149b32f860a00a7" integrity sha512-MwAQBz3VxoeFLaesaSEN87reVNVbjcQBDex2WGexAg6hUB6n4gc1OWYH/iXp4tzp4kuggBNhEHkk9BMYXWfhJQ== -"@chakra-ui/react-use-size@2.0.9": - version "2.0.9" - resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-size/-/react-use-size-2.0.9.tgz#00717867b98a24c3bdcfaa0c3e70732404193486" - integrity sha512-Jce7QmO1jlQZq+Y77VKckWzroRnajChzUQ8xhLQZO6VbYvrpg3cu+X2QCz3G+MZzB+1/hnvvAqmZ+uJLd8rEJg== +"@chakra-ui/react-use-size@2.0.10": + version "2.0.10" + resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-size/-/react-use-size-2.0.10.tgz#6131950852490c06e5fb3760bf64097c8057391f" + integrity sha512-fdIkH14GDnKQrtQfxX8N3gxbXRPXEl67Y3zeD9z4bKKcQUAYIMqs0MsPZY+FMpGQw8QqafM44nXfL038aIrC5w== dependencies: - "@zag-js/element-size" "0.3.1" + "@zag-js/element-size" "0.3.2" "@chakra-ui/react-use-timeout@2.0.5": version "2.0.5" @@ -628,69 +628,70 @@ dependencies: "@chakra-ui/utils" "2.0.15" -"@chakra-ui/react@^2.5.1": - version "2.5.1" - resolved "https://registry.yarnpkg.com/@chakra-ui/react/-/react-2.5.1.tgz#05414db2b512bd4402e42eecc6b915d85102c576" - integrity sha512-ugkaqfcNMb9L4TkalWiF3rnqfr0TlUUD46JZaDIZiORVisaSwXTZTQrVfG40VghhaJT28rnC5WtiE8kd567ZBQ== +"@chakra-ui/react@^2.6.0": + version "2.6.0" + resolved "https://registry.yarnpkg.com/@chakra-ui/react/-/react-2.6.0.tgz#67bea840ff97b2820798f52e706423ccc49f8b7e" + integrity sha512-dhufu/A4O5tQ65p//XGfvUqSrf0qRAgTmFRlBZ7HucyxF5RStQ65FXiTXV0s4Pj0X5hgSJm3oCasV6UD6MXYbw== dependencies: - "@chakra-ui/accordion" "2.1.9" - "@chakra-ui/alert" "2.0.17" - "@chakra-ui/avatar" "2.2.5" - "@chakra-ui/breadcrumb" "2.1.4" - "@chakra-ui/button" "2.0.16" + "@chakra-ui/accordion" "2.1.11" + "@chakra-ui/alert" "2.1.0" + "@chakra-ui/avatar" "2.2.9" + "@chakra-ui/breadcrumb" "2.1.5" + "@chakra-ui/button" "2.0.18" "@chakra-ui/card" "2.1.6" - "@chakra-ui/checkbox" "2.2.10" + "@chakra-ui/checkbox" "2.2.15" "@chakra-ui/close-button" "2.0.17" "@chakra-ui/control-box" "2.0.13" "@chakra-ui/counter" "2.0.14" - "@chakra-ui/css-reset" "2.0.12" - "@chakra-ui/editable" "2.0.19" + "@chakra-ui/css-reset" "2.1.1" + "@chakra-ui/editable" "3.0.0" "@chakra-ui/focus-lock" "2.0.16" - "@chakra-ui/form-control" "2.0.17" - "@chakra-ui/hooks" "2.1.6" + "@chakra-ui/form-control" "2.0.18" + "@chakra-ui/hooks" "2.2.0" "@chakra-ui/icon" "3.0.16" - "@chakra-ui/image" "2.0.15" - "@chakra-ui/input" "2.0.20" - "@chakra-ui/layout" "2.1.16" + "@chakra-ui/image" "2.0.16" + "@chakra-ui/input" "2.0.22" + "@chakra-ui/layout" "2.1.19" "@chakra-ui/live-region" "2.0.13" "@chakra-ui/media-query" "3.2.12" - "@chakra-ui/menu" "2.1.9" - "@chakra-ui/modal" "2.2.9" - "@chakra-ui/number-input" "2.0.18" - "@chakra-ui/pin-input" "2.0.19" - "@chakra-ui/popover" "2.1.8" + "@chakra-ui/menu" "2.1.13" + "@chakra-ui/modal" "2.2.11" + "@chakra-ui/number-input" "2.0.19" + "@chakra-ui/pin-input" "2.0.20" + "@chakra-ui/popover" "2.1.10" "@chakra-ui/popper" "3.0.13" - "@chakra-ui/portal" "2.0.15" - "@chakra-ui/progress" "2.1.5" - "@chakra-ui/provider" "2.1.2" - "@chakra-ui/radio" "2.0.19" + "@chakra-ui/portal" "2.0.16" + "@chakra-ui/progress" "2.1.6" + "@chakra-ui/provider" "2.2.3" + "@chakra-ui/radio" "2.0.22" "@chakra-ui/react-env" "3.0.0" - "@chakra-ui/select" "2.0.18" + "@chakra-ui/select" "2.0.19" "@chakra-ui/skeleton" "2.0.24" - "@chakra-ui/slider" "2.0.21" + "@chakra-ui/slider" "2.0.23" "@chakra-ui/spinner" "2.0.13" - "@chakra-ui/stat" "2.0.17" - "@chakra-ui/styled-system" "2.6.1" - "@chakra-ui/switch" "2.0.22" - "@chakra-ui/system" "2.5.1" - "@chakra-ui/table" "2.0.16" - "@chakra-ui/tabs" "2.1.8" - "@chakra-ui/tag" "2.0.17" - "@chakra-ui/textarea" "2.0.18" - "@chakra-ui/theme" "2.2.5" - "@chakra-ui/theme-utils" "2.0.11" - "@chakra-ui/toast" "6.0.1" - "@chakra-ui/tooltip" "2.2.6" - "@chakra-ui/transition" "2.0.15" + "@chakra-ui/stat" "2.0.18" + "@chakra-ui/stepper" "2.1.0" + "@chakra-ui/styled-system" "2.9.0" + "@chakra-ui/switch" "2.0.27" + "@chakra-ui/system" "2.5.6" + "@chakra-ui/table" "2.0.17" + "@chakra-ui/tabs" "2.1.9" + "@chakra-ui/tag" "3.0.0" + "@chakra-ui/textarea" "2.0.19" + "@chakra-ui/theme" "3.1.0" + "@chakra-ui/theme-utils" "2.0.16" + "@chakra-ui/toast" "6.1.2" + "@chakra-ui/tooltip" "2.2.7" + "@chakra-ui/transition" "2.0.16" "@chakra-ui/utils" "2.0.15" "@chakra-ui/visually-hidden" "2.0.15" -"@chakra-ui/select@2.0.18": - version "2.0.18" - resolved "https://registry.yarnpkg.com/@chakra-ui/select/-/select-2.0.18.tgz#4eb6092610067c1b4131353fe39b4466e251395b" - integrity sha512-1d2lUT5LM6oOs5x4lzBh4GFDuXX62+lr+sgV7099g951/5UNbb0CS2hSZHsO7yZThLNbr7QTWZvAOAayVcGzdw== +"@chakra-ui/select@2.0.19": + version "2.0.19" + resolved "https://registry.yarnpkg.com/@chakra-ui/select/-/select-2.0.19.tgz#957e95a17a890d8c0a851e2f00a8d8dd17932d66" + integrity sha512-eAlFh+JhwtJ17OrB6fO6gEAGOMH18ERNrXLqWbYLrs674Le7xuREgtuAYDoxUzvYXYYTTdOJtVbcHGriI3o6rA== dependencies: - "@chakra-ui/form-control" "2.0.17" + "@chakra-ui/form-control" "2.0.18" "@chakra-ui/shared-utils" "2.0.5" "@chakra-ui/shared-utils@2.0.4": @@ -712,20 +713,20 @@ "@chakra-ui/react-use-previous" "2.0.5" "@chakra-ui/shared-utils" "2.0.5" -"@chakra-ui/slider@2.0.21": - version "2.0.21" - resolved "https://registry.yarnpkg.com/@chakra-ui/slider/-/slider-2.0.21.tgz#f65b15bf0d5f827699ff9a2d6faee35006e2bfce" - integrity sha512-Mm76yJxEqJl21+3waEcKg3tM8Y4elJ7mcViN6Brj35PTfzUJfSJxeBGo1nLPJ+X5jLj7o/L4kfBmUk3lY4QYEQ== +"@chakra-ui/slider@2.0.23": + version "2.0.23" + resolved "https://registry.yarnpkg.com/@chakra-ui/slider/-/slider-2.0.23.tgz#9130c7aee8ca876be64d1aeba6b84fe421c8207b" + integrity sha512-/eyRUXLla+ZdBUPXpakE3SAS2JS8mIJR6qcUYiPVKSpRAi6tMyYeQijAXn2QC1AUVd2JrG8Pz+1Jy7Po3uA7cA== dependencies: "@chakra-ui/number-utils" "2.0.7" - "@chakra-ui/react-context" "2.0.7" + "@chakra-ui/react-context" "2.0.8" "@chakra-ui/react-types" "2.0.7" "@chakra-ui/react-use-callback-ref" "2.0.7" "@chakra-ui/react-use-controllable-state" "2.0.8" "@chakra-ui/react-use-latest-ref" "2.0.5" "@chakra-ui/react-use-merge-refs" "2.0.7" "@chakra-ui/react-use-pan-event" "2.0.9" - "@chakra-ui/react-use-size" "2.0.9" + "@chakra-ui/react-use-size" "2.0.10" "@chakra-ui/react-use-update-effect" "2.0.7" "@chakra-ui/spinner@2.0.13": @@ -735,82 +736,91 @@ dependencies: "@chakra-ui/shared-utils" "2.0.5" -"@chakra-ui/stat@2.0.17": - version "2.0.17" - resolved "https://registry.yarnpkg.com/@chakra-ui/stat/-/stat-2.0.17.tgz#2cd712cc7e0d58d9cbd542deea911f1b0925074f" - integrity sha512-PhD+5oVLWjQmGLfeZSmexp3AtLcaggWBwoMZ4z8QMZIQzf/fJJWMk0bMqxlpTv8ORDkfY/4ImuFB/RJHvcqlcA== +"@chakra-ui/stat@2.0.18": + version "2.0.18" + resolved "https://registry.yarnpkg.com/@chakra-ui/stat/-/stat-2.0.18.tgz#9e5d21d162b7cf2cf92065c19291ead2d4660772" + integrity sha512-wKyfBqhVlIs9bkSerUc6F9KJMw0yTIEKArW7dejWwzToCLPr47u+CtYO6jlJHV6lRvkhi4K4Qc6pyvtJxZ3VpA== dependencies: "@chakra-ui/icon" "3.0.16" - "@chakra-ui/react-context" "2.0.7" + "@chakra-ui/react-context" "2.0.8" "@chakra-ui/shared-utils" "2.0.5" -"@chakra-ui/styled-system@2.6.1", "@chakra-ui/styled-system@^2.6.1": - version "2.6.1" - resolved "https://registry.yarnpkg.com/@chakra-ui/styled-system/-/styled-system-2.6.1.tgz#302d496d34c0b7b30c646a7e3c9b113a2f4588da" - integrity sha512-jy/1dVi1LxjoRCm+Eo5mqBgvPy5SCWMlIcz6GbIZBDpkGeKZwtqrZLjekxxLBCy8ORY+kJlUB0FT6AzVR/1tjw== +"@chakra-ui/stepper@2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@chakra-ui/stepper/-/stepper-2.1.0.tgz#10ae7ea6c0b5edf554e9b2bfe5ec67fb7b7c67ec" + integrity sha512-Xo/3U+nduhLWNUAAQ0XuIeJjXhSCrxyEJ0PSGwR+2I8PJq82GDIxXjvfpeDLCHoB225l3Wyuy4paeIHkUQhDxA== + dependencies: + "@chakra-ui/icon" "3.0.16" + "@chakra-ui/react-context" "2.0.8" + "@chakra-ui/shared-utils" "2.0.5" + +"@chakra-ui/styled-system@2.9.0", "@chakra-ui/styled-system@^2.9.0": + version "2.9.0" + resolved "https://registry.yarnpkg.com/@chakra-ui/styled-system/-/styled-system-2.9.0.tgz#b3bace83c78cf9c072c461cc963bf73c0e7ccd3d" + integrity sha512-rToN30eOezrTZ5qBHmWqEwsYPenHtc3WU6ODAfMUwNnmCJQiu2erRGv8JwIjmRJnKSOEnNKccI2UXe2EwI6+JA== dependencies: "@chakra-ui/shared-utils" "2.0.5" csstype "^3.0.11" lodash.mergewith "4.6.2" -"@chakra-ui/switch@2.0.22": - version "2.0.22" - resolved "https://registry.yarnpkg.com/@chakra-ui/switch/-/switch-2.0.22.tgz#7b35e2b10ea4cf91fb49f5175b4335c61dcd25b3" - integrity sha512-+/Yy6y7VFD91uSPruF8ZvePi3tl5D8UNVATtWEQ+QBI92DLSM+PtgJ2F0Y9GMZ9NzMxpZ80DqwY7/kqcPCfLvw== +"@chakra-ui/switch@2.0.27": + version "2.0.27" + resolved "https://registry.yarnpkg.com/@chakra-ui/switch/-/switch-2.0.27.tgz#e76e5afdfc837c83fce34480de4431ff8c19fcb8" + integrity sha512-z76y2fxwMlvRBrC5W8xsZvo3gP+zAEbT3Nqy5P8uh/IPd5OvDsGeac90t5cgnQTyxMOpznUNNK+1eUZqtLxWnQ== dependencies: - "@chakra-ui/checkbox" "2.2.10" + "@chakra-ui/checkbox" "2.2.15" "@chakra-ui/shared-utils" "2.0.5" -"@chakra-ui/system@2.5.1": - version "2.5.1" - resolved "https://registry.yarnpkg.com/@chakra-ui/system/-/system-2.5.1.tgz#bc03a11ae31e795966c7618280548d5cd866f47e" - integrity sha512-4+86OrcSoq7lGkm5fh+sJ3IWXSTzjz+HOllRbCW2Rtnmcg7ritiXVNV2VygEg2DrCcx5+tNqRHDM764zW+AEug== +"@chakra-ui/system@2.5.6": + version "2.5.6" + resolved "https://registry.yarnpkg.com/@chakra-ui/system/-/system-2.5.6.tgz#244eef56be3d3d546ef3d1b93e5f9b9a591ef3fd" + integrity sha512-sKzonHUbjOnRxZvcysN8pqa3y0OkTb9xWPhNFnvye/Km8vZhw4SfHKbVpRXedMPVp5Q3PHOxqAXOs6Q0kpo6KA== dependencies: "@chakra-ui/color-mode" "2.1.12" - "@chakra-ui/object-utils" "2.0.8" + "@chakra-ui/object-utils" "2.1.0" "@chakra-ui/react-utils" "2.0.12" - "@chakra-ui/styled-system" "2.6.1" - "@chakra-ui/theme-utils" "2.0.11" + "@chakra-ui/styled-system" "2.9.0" + "@chakra-ui/theme-utils" "2.0.16" "@chakra-ui/utils" "2.0.15" - react-fast-compare "3.2.0" + react-fast-compare "3.2.1" -"@chakra-ui/table@2.0.16": - version "2.0.16" - resolved "https://registry.yarnpkg.com/@chakra-ui/table/-/table-2.0.16.tgz#e69736cba5cfb218c5e40592ad9280c6e32f6fe7" - integrity sha512-vWDXZ6Ad3Aj66curp1tZBHvCfQHX2FJ4ijLiqGgQszWFIchfhJ5vMgEBJaFMZ+BN1draAjuRTZqaQefOApzvRg== +"@chakra-ui/table@2.0.17": + version "2.0.17" + resolved "https://registry.yarnpkg.com/@chakra-ui/table/-/table-2.0.17.tgz#ad394dc6dcbe5a8a9e6d899997ecca3471603977" + integrity sha512-OScheTEp1LOYvTki2NFwnAYvac8siAhW9BI5RKm5f5ORL2gVJo4I72RUqE0aKe1oboxgm7CYt5afT5PS5cG61A== dependencies: - "@chakra-ui/react-context" "2.0.7" + "@chakra-ui/react-context" "2.0.8" "@chakra-ui/shared-utils" "2.0.5" -"@chakra-ui/tabs@2.1.8": - version "2.1.8" - resolved "https://registry.yarnpkg.com/@chakra-ui/tabs/-/tabs-2.1.8.tgz#e83071380f9a3633810308d45de51be7a74f5eb9" - integrity sha512-B7LeFN04Ny2jsSy5TFOQxnbZ6ITxGxLxsB2PE0vvQjMSblBrUryOxdjw80HZhfiw6od0ikK9CeKQOIt9QCguSw== +"@chakra-ui/tabs@2.1.9": + version "2.1.9" + resolved "https://registry.yarnpkg.com/@chakra-ui/tabs/-/tabs-2.1.9.tgz#2e5214cb453c6cc0c240e82bd88af1042fc6fe0e" + integrity sha512-Yf8e0kRvaGM6jfkJum0aInQ0U3ZlCafmrYYni2lqjcTtThqu+Yosmo3iYlnullXxCw5MVznfrkb9ySvgQowuYg== dependencies: "@chakra-ui/clickable" "2.0.14" - "@chakra-ui/descendant" "3.0.13" + "@chakra-ui/descendant" "3.0.14" "@chakra-ui/lazy-utils" "2.0.5" "@chakra-ui/react-children-utils" "2.0.6" - "@chakra-ui/react-context" "2.0.7" + "@chakra-ui/react-context" "2.0.8" "@chakra-ui/react-use-controllable-state" "2.0.8" "@chakra-ui/react-use-merge-refs" "2.0.7" "@chakra-ui/react-use-safe-layout-effect" "2.0.5" "@chakra-ui/shared-utils" "2.0.5" -"@chakra-ui/tag@2.0.17": - version "2.0.17" - resolved "https://registry.yarnpkg.com/@chakra-ui/tag/-/tag-2.0.17.tgz#97adb86db190ddb3526060b78c590392e0ac8b4c" - integrity sha512-A47zE9Ft9qxOJ+5r1cUseKRCoEdqCRzFm0pOtZgRcckqavglk75Xjgz8HbBpUO2zqqd49MlqdOwR8o87fXS1vg== +"@chakra-ui/tag@3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@chakra-ui/tag/-/tag-3.0.0.tgz#d86cdab59bb3ff7fc628c2dbe7a5ff1b36bd3e96" + integrity sha512-YWdMmw/1OWRwNkG9pX+wVtZio+B89odaPj6XeMn5nfNN8+jyhIEpouWv34+CO9G0m1lupJTxPSfgLAd7cqXZMA== dependencies: "@chakra-ui/icon" "3.0.16" - "@chakra-ui/react-context" "2.0.7" + "@chakra-ui/react-context" "2.0.8" -"@chakra-ui/textarea@2.0.18": - version "2.0.18" - resolved "https://registry.yarnpkg.com/@chakra-ui/textarea/-/textarea-2.0.18.tgz#da6d629b465f65bbc7b48039c2e48a4ae1d853b4" - integrity sha512-aGHHb29vVifO0OtcK/k8cMykzjOKo/coDTU0NJqz7OOLAWIMNV2eGenvmO1n9tTZbmbqHiX+Sa1nPRX+pd14lg== +"@chakra-ui/textarea@2.0.19": + version "2.0.19" + resolved "https://registry.yarnpkg.com/@chakra-ui/textarea/-/textarea-2.0.19.tgz#470b459f9cb3255d2abbe07d46b0a5b60a6a32c5" + integrity sha512-adJk+qVGsFeJDvfn56CcJKKse8k7oMGlODrmpnpTdF+xvlsiTM+1GfaJvgNSpHHuQFdz/A0z1uJtfGefk0G2ZA== dependencies: - "@chakra-ui/form-control" "2.0.17" + "@chakra-ui/form-control" "2.0.18" "@chakra-ui/shared-utils" "2.0.5" "@chakra-ui/theme-tools@2.0.17": @@ -831,57 +841,57 @@ "@chakra-ui/shared-utils" "2.0.4" color2k "^2.0.0" -"@chakra-ui/theme-utils@2.0.11": - version "2.0.11" - resolved "https://registry.yarnpkg.com/@chakra-ui/theme-utils/-/theme-utils-2.0.11.tgz#c01b1d14fdd63326d1ad11fd8f0872921ea43872" - integrity sha512-lBAay6Sq3/fl7exd3mFxWAbzgdQowytor0fnlHrpNStn1HgFjXukwsf6356XQOie2Vd8qaMM7qZtMh4AiC0dcg== +"@chakra-ui/theme-utils@2.0.16": + version "2.0.16" + resolved "https://registry.yarnpkg.com/@chakra-ui/theme-utils/-/theme-utils-2.0.16.tgz#9686b6b307ae8928a686df8df79bee16c4e0d25c" + integrity sha512-xVrQ8YEhIX51PB27kbEGHoQ3G78erSykqOeIPkoxaEfWBV4Ba83o7RwEZG8/Qa7c7S4qYPmCSGynegBWrsQpHA== dependencies: "@chakra-ui/shared-utils" "2.0.5" - "@chakra-ui/styled-system" "2.6.1" - "@chakra-ui/theme" "2.2.5" + "@chakra-ui/styled-system" "2.9.0" + "@chakra-ui/theme" "3.1.0" lodash.mergewith "4.6.2" -"@chakra-ui/theme@2.2.5": - version "2.2.5" - resolved "https://registry.yarnpkg.com/@chakra-ui/theme/-/theme-2.2.5.tgz#18ed1755ff27c1ff1f1a77083ffc546c361c926e" - integrity sha512-hYASZMwu0NqEv6PPydu+F3I+kMNd44yR4TwjR/lXBz/LEh64L6UPY6kQjebCfgdVtsGdl3HKg+eLlfa7SvfRgw== +"@chakra-ui/theme@3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@chakra-ui/theme/-/theme-3.1.0.tgz#ebb097c350ca9827b2efcc81df5f4b712729b9a0" + integrity sha512-lO2p37lyEGVmGUrr+lakHpnvrJHkkfPnSM+w9MGmR0V0rqIGTIBrirBO07vDccNRS17jcXjA8d9QZEBYzIVyNw== dependencies: "@chakra-ui/anatomy" "2.1.2" "@chakra-ui/shared-utils" "2.0.5" "@chakra-ui/theme-tools" "2.0.17" -"@chakra-ui/toast@6.0.1": - version "6.0.1" - resolved "https://registry.yarnpkg.com/@chakra-ui/toast/-/toast-6.0.1.tgz#726b67a57cdd592320bb3f450c66d007a2a1d902" - integrity sha512-ej2kJXvu/d2h6qnXU5D8XTyw0qpsfmbiU7hUffo/sPxkz89AUOQ08RUuUmB1ssW/FZcQvNMJ5WgzCTKHGBxtxw== +"@chakra-ui/toast@6.1.2": + version "6.1.2" + resolved "https://registry.yarnpkg.com/@chakra-ui/toast/-/toast-6.1.2.tgz#9a41dd01baf790232f07a4237ef49bc019d7a836" + integrity sha512-hKSv6tX0zgZIZDMpIzs0kZM56sYrD5lvlLQ5JfERLi0KTSTeP+vbYh4+Vg3GTXPCn1JBF7mZRX0gU22WEMfJ8A== dependencies: - "@chakra-ui/alert" "2.0.17" + "@chakra-ui/alert" "2.1.0" "@chakra-ui/close-button" "2.0.17" - "@chakra-ui/portal" "2.0.15" - "@chakra-ui/react-context" "2.0.7" + "@chakra-ui/portal" "2.0.16" + "@chakra-ui/react-context" "2.0.8" "@chakra-ui/react-use-timeout" "2.0.5" "@chakra-ui/react-use-update-effect" "2.0.7" "@chakra-ui/shared-utils" "2.0.5" - "@chakra-ui/styled-system" "2.6.1" - "@chakra-ui/theme" "2.2.5" + "@chakra-ui/styled-system" "2.9.0" + "@chakra-ui/theme" "3.1.0" -"@chakra-ui/tooltip@2.2.6": - version "2.2.6" - resolved "https://registry.yarnpkg.com/@chakra-ui/tooltip/-/tooltip-2.2.6.tgz#a38f9ff2dd8a574c8cf49526c3846533455f8ddd" - integrity sha512-4cbneidZ5+HCWge3OZzewRQieIvhDjSsl+scrl4Scx7E0z3OmqlTIESU5nGIZDBLYqKn/UirEZhqaQ33FOS2fw== +"@chakra-ui/tooltip@2.2.7": + version "2.2.7" + resolved "https://registry.yarnpkg.com/@chakra-ui/tooltip/-/tooltip-2.2.7.tgz#7c305efb057a5fe4694b1b8d82395aec776d8f57" + integrity sha512-ImUJ6NnVqARaYqpgtO+kzucDRmxo8AF3jMjARw0bx2LxUkKwgRCOEaaRK5p5dHc0Kr6t5/XqjDeUNa19/sLauA== dependencies: "@chakra-ui/popper" "3.0.13" - "@chakra-ui/portal" "2.0.15" + "@chakra-ui/portal" "2.0.16" "@chakra-ui/react-types" "2.0.7" "@chakra-ui/react-use-disclosure" "2.0.8" "@chakra-ui/react-use-event-listener" "2.0.7" "@chakra-ui/react-use-merge-refs" "2.0.7" "@chakra-ui/shared-utils" "2.0.5" -"@chakra-ui/transition@2.0.15": - version "2.0.15" - resolved "https://registry.yarnpkg.com/@chakra-ui/transition/-/transition-2.0.15.tgz#c640df2ea82f5ad58c55a6e1a7c338f377cb96d8" - integrity sha512-o9LBK/llQfUDHF/Ty3cQ6nShpekKTqHUoJlUOzNKhoTsNpoRerr9v0jwojrX1YI02KtVjfhFU6PiqXlDfREoNw== +"@chakra-ui/transition@2.0.16": + version "2.0.16" + resolved "https://registry.yarnpkg.com/@chakra-ui/transition/-/transition-2.0.16.tgz#498c91e6835bb5d950fd1d1402f483b85f7dcd87" + integrity sha512-E+RkwlPc3H7P1crEXmXwDXMB2lqY2LLia2P5siQ4IEnRWIgZXlIw+8Em+NtHNgusel2N+9yuB0wT9SeZZeZ3CQ== dependencies: "@chakra-ui/shared-utils" "2.0.5" @@ -912,6 +922,14 @@ resolved "https://registry.yarnpkg.com/@dagrejs/graphlib/-/graphlib-2.1.12.tgz#97d29eae006e4efcb68863505464e0e3f28fa5c7" integrity sha512-yHk2G7ZNzDEHhQTlYtbtEy5PqlIoioCxZUKcrlBgubMvrLmewXqSV3v4rhc8RAt5s8lr8PcWbiovEPuORxe2KA== +"@dependents/detective-less@^3.0.1": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@dependents/detective-less/-/detective-less-3.0.2.tgz#c6e46997010fe03a5dc98351a7e99a46d34f5832" + integrity sha512-1YUvQ+e0eeTWAHoN8Uz2x2U37jZs6IGutiIE5LXId7cxfUGhtZjzxE06FdUiuiRrW+UE0vNCdSNPH2lY4dQCOQ== + dependencies: + gonzales-pe "^4.3.0" + node-source-walk "^5.0.1" + "@emotion/babel-plugin@^11.10.6": version "11.10.6" resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.10.6.tgz#a68ee4b019d661d6f37dec4b8903255766925ead" @@ -930,9 +948,9 @@ stylis "4.1.3" "@emotion/cache@^11.10.5": - version "11.10.5" - resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.10.5.tgz#c142da9351f94e47527ed458f7bbbbe40bb13c12" - integrity sha512-dGYHWyzTdmK+f2+EnIGBpkz1lKc4Zbj2KHd4cX3Wi8/OWr5pKslNjc3yABKH4adRGCvSX4VDC0i04mrrq0aiRA== + version "11.10.7" + resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.10.7.tgz#2e3b12d3c7c74db0a020ae79eefc52a1b03a6908" + integrity sha512-VLl1/2D6LOjH57Y8Vem1RoZ9haWF4jesHDGiHtKozDQuBIkJm2gimVo0I02sWCuzZtVACeixTVB4jeE8qvCBoQ== dependencies: "@emotion/memoize" "^0.8.0" "@emotion/sheet" "^1.2.1" @@ -1031,124 +1049,136 @@ resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.3.0.tgz#ea89004119dc42db2e1dba0f97d553f7372f6fcb" integrity sha512-AHPmaAx+RYfZz0eYu6Gviiagpmiyw98ySSlQvCUhVGDRtDFe4DBS0x1bSjdF3gqUDYOczB+yYvBTtEylYSdRhg== -"@esbuild/android-arm64@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.16.17.tgz#cf91e86df127aa3d141744edafcba0abdc577d23" - integrity sha512-MIGl6p5sc3RDTLLkYL1MyL8BMRN4tLMRCn+yRJJmEDvYZ2M7tmAf80hx1kbNEUX2KJ50RRtxZ4JHLvCfuB6kBg== +"@esbuild/android-arm64@0.17.18": + version "0.17.18" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.17.18.tgz#4aa8d8afcffb4458736ca9b32baa97d7cb5861ea" + integrity sha512-/iq0aK0eeHgSC3z55ucMAHO05OIqmQehiGay8eP5l/5l+iEr4EIbh4/MI8xD9qRFjqzgkc0JkX0LculNC9mXBw== -"@esbuild/android-arm@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.16.17.tgz#025b6246d3f68b7bbaa97069144fb5fb70f2fff2" - integrity sha512-N9x1CMXVhtWEAMS7pNNONyA14f71VPQN9Cnavj1XQh6T7bskqiLLrSca4O0Vr8Wdcga943eThxnVp3JLnBMYtw== +"@esbuild/android-arm@0.17.18": + version "0.17.18" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.17.18.tgz#74a7e95af4ee212ebc9db9baa87c06a594f2a427" + integrity sha512-EmwL+vUBZJ7mhFCs5lA4ZimpUH3WMAoqvOIYhVQwdIgSpHC8ImHdsRyhHAVxpDYUSm0lWvd63z0XH1IlImS2Qw== -"@esbuild/android-x64@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.16.17.tgz#c820e0fef982f99a85c4b8bfdd582835f04cd96e" - integrity sha512-a3kTv3m0Ghh4z1DaFEuEDfz3OLONKuFvI4Xqczqx4BqLyuFaFkuaG4j2MtA6fuWEFeC5x9IvqnX7drmRq/fyAQ== +"@esbuild/android-x64@0.17.18": + version "0.17.18" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.17.18.tgz#1dcd13f201997c9fe0b204189d3a0da4eb4eb9b6" + integrity sha512-x+0efYNBF3NPW2Xc5bFOSFW7tTXdAcpfEg2nXmxegm4mJuVeS+i109m/7HMiOQ6M12aVGGFlqJX3RhNdYM2lWg== -"@esbuild/darwin-arm64@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.16.17.tgz#edef4487af6b21afabba7be5132c26d22379b220" - integrity sha512-/2agbUEfmxWHi9ARTX6OQ/KgXnOWfsNlTeLcoV7HSuSTv63E4DqtAc+2XqGw1KHxKMHGZgbVCZge7HXWX9Vn+w== +"@esbuild/darwin-arm64@0.17.18": + version "0.17.18" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.17.18.tgz#444f3b961d4da7a89eb9bd35cfa4415141537c2a" + integrity sha512-6tY+djEAdF48M1ONWnQb1C+6LiXrKjmqjzPNPWXhu/GzOHTHX2nh8Mo2ZAmBFg0kIodHhciEgUBtcYCAIjGbjQ== -"@esbuild/darwin-x64@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.16.17.tgz#42829168730071c41ef0d028d8319eea0e2904b4" - integrity sha512-2By45OBHulkd9Svy5IOCZt376Aa2oOkiE9QWUK9fe6Tb+WDr8hXL3dpqi+DeLiMed8tVXspzsTAvd0jUl96wmg== +"@esbuild/darwin-x64@0.17.18": + version "0.17.18" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.17.18.tgz#a6da308d0ac8a498c54d62e0b2bfb7119b22d315" + integrity sha512-Qq84ykvLvya3dO49wVC9FFCNUfSrQJLbxhoQk/TE1r6MjHo3sFF2tlJCwMjhkBVq3/ahUisj7+EpRSz0/+8+9A== -"@esbuild/freebsd-arm64@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.16.17.tgz#1f4af488bfc7e9ced04207034d398e793b570a27" - integrity sha512-mt+cxZe1tVx489VTb4mBAOo2aKSnJ33L9fr25JXpqQqzbUIw/yzIzi+NHwAXK2qYV1lEFp4OoVeThGjUbmWmdw== +"@esbuild/freebsd-arm64@0.17.18": + version "0.17.18" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.18.tgz#b83122bb468889399d0d63475d5aea8d6829c2c2" + integrity sha512-fw/ZfxfAzuHfaQeMDhbzxp9mc+mHn1Y94VDHFHjGvt2Uxl10mT4CDavHm+/L9KG441t1QdABqkVYwakMUeyLRA== -"@esbuild/freebsd-x64@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.16.17.tgz#636306f19e9bc981e06aa1d777302dad8fddaf72" - integrity sha512-8ScTdNJl5idAKjH8zGAsN7RuWcyHG3BAvMNpKOBaqqR7EbUhhVHOqXRdL7oZvz8WNHL2pr5+eIT5c65kA6NHug== +"@esbuild/freebsd-x64@0.17.18": + version "0.17.18" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.17.18.tgz#af59e0e03fcf7f221b34d4c5ab14094862c9c864" + integrity sha512-FQFbRtTaEi8ZBi/A6kxOC0V0E9B/97vPdYjY9NdawyLd4Qk5VD5g2pbWN2VR1c0xhzcJm74HWpObPszWC+qTew== -"@esbuild/linux-arm64@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.16.17.tgz#a003f7ff237c501e095d4f3a09e58fc7b25a4aca" - integrity sha512-7S8gJnSlqKGVJunnMCrXHU9Q8Q/tQIxk/xL8BqAP64wchPCTzuM6W3Ra8cIa1HIflAvDnNOt2jaL17vaW+1V0g== +"@esbuild/linux-arm64@0.17.18": + version "0.17.18" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.17.18.tgz#8551d72ba540c5bce4bab274a81c14ed01eafdcf" + integrity sha512-R7pZvQZFOY2sxUG8P6A21eq6q+eBv7JPQYIybHVf1XkQYC+lT7nDBdC7wWKTrbvMXKRaGudp/dzZCwL/863mZQ== -"@esbuild/linux-arm@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.16.17.tgz#b591e6a59d9c4fe0eeadd4874b157ab78cf5f196" - integrity sha512-iihzrWbD4gIT7j3caMzKb/RsFFHCwqqbrbH9SqUSRrdXkXaygSZCZg1FybsZz57Ju7N/SHEgPyaR0LZ8Zbe9gQ== +"@esbuild/linux-arm@0.17.18": + version "0.17.18" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.17.18.tgz#e09e76e526df4f665d4d2720d28ff87d15cdf639" + integrity sha512-jW+UCM40LzHcouIaqv3e/oRs0JM76JfhHjCavPxMUti7VAPh8CaGSlS7cmyrdpzSk7A+8f0hiedHqr/LMnfijg== -"@esbuild/linux-ia32@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.16.17.tgz#24333a11027ef46a18f57019450a5188918e2a54" - integrity sha512-kiX69+wcPAdgl3Lonh1VI7MBr16nktEvOfViszBSxygRQqSpzv7BffMKRPMFwzeJGPxcio0pdD3kYQGpqQ2SSg== +"@esbuild/linux-ia32@0.17.18": + version "0.17.18" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.17.18.tgz#47878860ce4fe73a36fd8627f5647bcbbef38ba4" + integrity sha512-ygIMc3I7wxgXIxk6j3V00VlABIjq260i967Cp9BNAk5pOOpIXmd1RFQJQX9Io7KRsthDrQYrtcx7QCof4o3ZoQ== -"@esbuild/linux-loong64@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.16.17.tgz#d5ad459d41ed42bbd4d005256b31882ec52227d8" - integrity sha512-dTzNnQwembNDhd654cA4QhbS9uDdXC3TKqMJjgOWsC0yNCbpzfWoXdZvp0mY7HU6nzk5E0zpRGGx3qoQg8T2DQ== +"@esbuild/linux-loong64@0.17.18": + version "0.17.18" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.17.18.tgz#3f8fbf5267556fc387d20b2e708ce115de5c967a" + integrity sha512-bvPG+MyFs5ZlwYclCG1D744oHk1Pv7j8psF5TfYx7otCVmcJsEXgFEhQkbhNW8otDHL1a2KDINW20cfCgnzgMQ== -"@esbuild/linux-mips64el@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.16.17.tgz#4e5967a665c38360b0a8205594377d4dcf9c3726" - integrity sha512-ezbDkp2nDl0PfIUn0CsQ30kxfcLTlcx4Foz2kYv8qdC6ia2oX5Q3E/8m6lq84Dj/6b0FrkgD582fJMIfHhJfSw== +"@esbuild/linux-mips64el@0.17.18": + version "0.17.18" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.17.18.tgz#9d896d8f3c75f6c226cbeb840127462e37738226" + integrity sha512-oVqckATOAGuiUOa6wr8TXaVPSa+6IwVJrGidmNZS1cZVx0HqkTMkqFGD2HIx9H1RvOwFeWYdaYbdY6B89KUMxA== -"@esbuild/linux-ppc64@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.16.17.tgz#206443a02eb568f9fdf0b438fbd47d26e735afc8" - integrity sha512-dzS678gYD1lJsW73zrFhDApLVdM3cUF2MvAa1D8K8KtcSKdLBPP4zZSLy6LFZ0jYqQdQ29bjAHJDgz0rVbLB3g== +"@esbuild/linux-ppc64@0.17.18": + version "0.17.18" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.17.18.tgz#3d9deb60b2d32c9985bdc3e3be090d30b7472783" + integrity sha512-3dLlQO+b/LnQNxgH4l9rqa2/IwRJVN9u/bK63FhOPB4xqiRqlQAU0qDU3JJuf0BmaH0yytTBdoSBHrb2jqc5qQ== -"@esbuild/linux-riscv64@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.16.17.tgz#c351e433d009bf256e798ad048152c8d76da2fc9" - integrity sha512-ylNlVsxuFjZK8DQtNUwiMskh6nT0vI7kYl/4fZgV1llP5d6+HIeL/vmmm3jpuoo8+NuXjQVZxmKuhDApK0/cKw== +"@esbuild/linux-riscv64@0.17.18": + version "0.17.18" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.17.18.tgz#8a943cf13fd24ff7ed58aefb940ef178f93386bc" + integrity sha512-/x7leOyDPjZV3TcsdfrSI107zItVnsX1q2nho7hbbQoKnmoeUWjs+08rKKt4AUXju7+3aRZSsKrJtaRmsdL1xA== -"@esbuild/linux-s390x@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.16.17.tgz#661f271e5d59615b84b6801d1c2123ad13d9bd87" - integrity sha512-gzy7nUTO4UA4oZ2wAMXPNBGTzZFP7mss3aKR2hH+/4UUkCOyqmjXiKpzGrY2TlEUhbbejzXVKKGazYcQTZWA/w== +"@esbuild/linux-s390x@0.17.18": + version "0.17.18" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.17.18.tgz#66cb01f4a06423e5496facabdce4f7cae7cb80e5" + integrity sha512-cX0I8Q9xQkL/6F5zWdYmVf5JSQt+ZfZD2bJudZrWD+4mnUvoZ3TDDXtDX2mUaq6upMFv9FlfIh4Gfun0tbGzuw== -"@esbuild/linux-x64@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.16.17.tgz#e4ba18e8b149a89c982351443a377c723762b85f" - integrity sha512-mdPjPxfnmoqhgpiEArqi4egmBAMYvaObgn4poorpUaqmvzzbvqbowRllQ+ZgzGVMGKaPkqUmPDOOFQRUFDmeUw== +"@esbuild/linux-x64@0.17.18": + version "0.17.18" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.17.18.tgz#23c26050c6c5d1359c7b774823adc32b3883b6c9" + integrity sha512-66RmRsPlYy4jFl0vG80GcNRdirx4nVWAzJmXkevgphP1qf4dsLQCpSKGM3DUQCojwU1hnepI63gNZdrr02wHUA== -"@esbuild/netbsd-x64@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.16.17.tgz#7d4f4041e30c5c07dd24ffa295c73f06038ec775" - integrity sha512-/PzmzD/zyAeTUsduZa32bn0ORug+Jd1EGGAUJvqfeixoEISYpGnAezN6lnJoskauoai0Jrs+XSyvDhppCPoKOA== +"@esbuild/netbsd-x64@0.17.18": + version "0.17.18" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.17.18.tgz#789a203d3115a52633ff6504f8cbf757f15e703b" + integrity sha512-95IRY7mI2yrkLlTLb1gpDxdC5WLC5mZDi+kA9dmM5XAGxCME0F8i4bYH4jZreaJ6lIZ0B8hTrweqG1fUyW7jbg== -"@esbuild/openbsd-x64@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.16.17.tgz#970fa7f8470681f3e6b1db0cc421a4af8060ec35" - integrity sha512-2yaWJhvxGEz2RiftSk0UObqJa/b+rIAjnODJgv2GbGGpRwAfpgzyrg1WLK8rqA24mfZa9GvpjLcBBg8JHkoodg== +"@esbuild/openbsd-x64@0.17.18": + version "0.17.18" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.17.18.tgz#d7b998a30878f8da40617a10af423f56f12a5e90" + integrity sha512-WevVOgcng+8hSZ4Q3BKL3n1xTv5H6Nb53cBrtzzEjDbbnOmucEVcZeGCsCOi9bAOcDYEeBZbD2SJNBxlfP3qiA== -"@esbuild/sunos-x64@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.16.17.tgz#abc60e7c4abf8b89fb7a4fe69a1484132238022c" - integrity sha512-xtVUiev38tN0R3g8VhRfN7Zl42YCJvyBhRKw1RJjwE1d2emWTVToPLNEQj/5Qxc6lVFATDiy6LjVHYhIPrLxzw== +"@esbuild/sunos-x64@0.17.18": + version "0.17.18" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.17.18.tgz#ecad0736aa7dae07901ba273db9ef3d3e93df31f" + integrity sha512-Rzf4QfQagnwhQXVBS3BYUlxmEbcV7MY+BH5vfDZekU5eYpcffHSyjU8T0xucKVuOcdCsMo+Ur5wmgQJH2GfNrg== -"@esbuild/win32-arm64@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.16.17.tgz#7b0ff9e8c3265537a7a7b1fd9a24e7bd39fcd87a" - integrity sha512-ga8+JqBDHY4b6fQAmOgtJJue36scANy4l/rL97W+0wYmijhxKetzZdKOJI7olaBaMhWt8Pac2McJdZLxXWUEQw== +"@esbuild/win32-arm64@0.17.18": + version "0.17.18" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.17.18.tgz#58dfc177da30acf956252d7c8ae9e54e424887c4" + integrity sha512-Kb3Ko/KKaWhjeAm2YoT/cNZaHaD1Yk/pa3FTsmqo9uFh1D1Rfco7BBLIPdDOozrObj2sahslFuAQGvWbgWldAg== -"@esbuild/win32-ia32@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.16.17.tgz#e90fe5267d71a7b7567afdc403dfd198c292eb09" - integrity sha512-WnsKaf46uSSF/sZhwnqE4L/F89AYNMiD4YtEcYekBt9Q7nj0DiId2XH2Ng2PHM54qi5oPrQ8luuzGszqi/veig== +"@esbuild/win32-ia32@0.17.18": + version "0.17.18" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.17.18.tgz#340f6163172b5272b5ae60ec12c312485f69232b" + integrity sha512-0/xUMIdkVHwkvxfbd5+lfG7mHOf2FRrxNbPiKWg9C4fFrB8H0guClmaM3BFiRUYrznVoyxTIyC/Ou2B7QQSwmw== -"@esbuild/win32-x64@0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.16.17.tgz#c5a1a4bfe1b57f0c3e61b29883525c6da3e5c091" - integrity sha512-y+EHuSchhL7FjHgvQL/0fnnFmO4T1bhvWANX6gcnqTjtnKWbTvUMCpGnv2+t+31d7RzyEAYAd4u2fnIhHL6N/Q== +"@esbuild/win32-x64@0.17.18": + version "0.17.18" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.17.18.tgz#3a8e57153905308db357fd02f57c180ee3a0a1fa" + integrity sha512-qU25Ma1I3NqTSHJUOKi9sAH1/Mzuvlke0ioMJRthLXKm7JiSKVwFghlGbDLOO2sARECGhja4xYfRAZNPAkooYg== -"@eslint/eslintrc@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.0.0.tgz#943309d8697c52fc82c076e90c1c74fbbe69dbff" - integrity sha512-fluIaaV+GyV24CCu/ggiHdV+j4RNh85yQnAYS/G2mZODZgGmmlrgCydjUcV3YvxCm9x8nMAfThsqTni4KiXT4A== +"@eslint-community/eslint-utils@^4.2.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" + integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== + dependencies: + eslint-visitor-keys "^3.3.0" + +"@eslint-community/regexpp@^4.4.0": + version "4.5.0" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.5.0.tgz#f6f729b02feee2c749f57e334b7a1b5f40a81724" + integrity sha512-vITaYzIcNmjn5tF5uxcZ/ft7/RXGrMUIS9HalWckEOF6ESiwXKoMzAQf2UW0aVd6rnOeExTJVd5hmWXucBKGXQ== + +"@eslint/eslintrc@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.0.2.tgz#01575e38707add677cf73ca1589abba8da899a02" + integrity sha512-3W4f5tDUra+pA+FzgugqL2pRimUTDJWKr7BINqOpkZrC0uYI0NIc0/JFgBROCU07HR6GieA5m3/rsPIhDmCXTQ== dependencies: ajv "^6.12.4" debug "^4.3.2" - espree "^9.4.0" + espree "^9.5.1" globals "^13.19.0" ignore "^5.2.0" import-fresh "^3.2.1" @@ -1156,10 +1186,10 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@eslint/js@8.35.0": - version "8.35.0" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.35.0.tgz#b7569632b0b788a0ca0e438235154e45d42813a7" - integrity sha512-JXdzbRiWclLVoD8sNUjR443VVlYqiYmDVT6rGUEIEHU5YJW0gaVZwV2xgM7D4arkvASqD0IlLUVjHiFuxaftRw== +"@eslint/js@8.39.0": + version "8.39.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.39.0.tgz#58b536bcc843f4cd1e02a7e6171da5c040f4d44b" + integrity sha512-kf9RB0Fg7NZfap83B3QOqOGg9QmD9yBudqQXzzOtn3i4y7ZUXe5ONeW34Gwi+TxhH4mvj72R1Zc300KUMa9Bng== "@fontsource/inter@^4.5.15": version "4.5.15" @@ -1186,37 +1216,47 @@ integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== "@jridgewell/gen-mapping@^0.3.0": - version "0.3.2" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" - integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A== + version "0.3.3" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098" + integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ== dependencies: "@jridgewell/set-array" "^1.0.1" "@jridgewell/sourcemap-codec" "^1.4.10" "@jridgewell/trace-mapping" "^0.3.9" -"@jridgewell/resolve-uri@3.1.0", "@jridgewell/resolve-uri@^3.0.3": +"@jridgewell/resolve-uri@3.1.0": version "3.1.0" resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== +"@jridgewell/resolve-uri@^3.0.3": + version "3.1.1" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721" + integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA== + "@jridgewell/set-array@^1.0.1": version "1.1.2" resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== "@jridgewell/source-map@^0.3.2": - version "0.3.2" - resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.2.tgz#f45351aaed4527a298512ec72f81040c998580fb" - integrity sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw== + version "0.3.3" + resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.3.tgz#8108265659d4c33e72ffe14e33d6cc5eb59f2fda" + integrity sha512-b+fsZXeLYi9fEULmfBrhxn4IrPlINf8fiNarzTof004v3lFdntdwa9PF7vFJqm3mg7s+ScJMxXaE3Acp1irZcg== dependencies: "@jridgewell/gen-mapping" "^0.3.0" "@jridgewell/trace-mapping" "^0.3.9" -"@jridgewell/sourcemap-codec@1.4.14", "@jridgewell/sourcemap-codec@^1.4.10": +"@jridgewell/sourcemap-codec@1.4.14": version "1.4.14" resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== +"@jridgewell/sourcemap-codec@^1.4.10": + version "1.4.15" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" + integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== + "@jridgewell/trace-mapping@0.3.9": version "0.3.9" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" @@ -1226,9 +1266,9 @@ "@jridgewell/sourcemap-codec" "^1.4.10" "@jridgewell/trace-mapping@^0.3.9": - version "0.3.17" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz#793041277af9073b0951a7fe0f0d8c4c98c36985" - integrity sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g== + version "0.3.18" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz#25783b2086daf6ff1dcb53c9249ae480e4dd4cd6" + integrity sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA== dependencies: "@jridgewell/resolve-uri" "3.1.0" "@jridgewell/sourcemap-codec" "1.4.14" @@ -1260,9 +1300,9 @@ fastq "^1.6.0" "@popperjs/core@^2.9.3": - version "2.11.6" - resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.6.tgz#cee20bd55e68a1720bdab363ecf0c821ded4cd45" - integrity sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw== + version "2.11.7" + resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.7.tgz#ccab5c8f7dc557a52ca3288c10075c9ccd37fff7" + integrity sha512-Cr4OjIkipTtcXKjAsm8agyleBuDHvxzeBoa1v543lbv1YaIwQjESsVcmjiWiPEbC1FIeHOG/Op9kdCmAmiS3Kw== "@reactflow/background@11.2.0": version "11.2.0" @@ -1329,15 +1369,15 @@ classcat "^5.0.3" zustand "^4.3.1" -"@reduxjs/toolkit@^1.9.3": - version "1.9.3" - resolved "https://registry.yarnpkg.com/@reduxjs/toolkit/-/toolkit-1.9.3.tgz#27e1a33072b5a312e4f7fa19247fec160bbb2df9" - integrity sha512-GU2TNBQVofL09VGmuSioNPQIu6Ml0YLf4EJhgj0AvBadRlCGzUWet8372LjvO4fqKZF2vH1xU0htAa7BrK9pZg== +"@reduxjs/toolkit@^1.9.5": + version "1.9.5" + resolved "https://registry.yarnpkg.com/@reduxjs/toolkit/-/toolkit-1.9.5.tgz#d3987849c24189ca483baa7aa59386c8e52077c4" + integrity sha512-Rt97jHmfTeaxL4swLRNPD/zV4OxTes4la07Xc4hetpUW/vc75t5m1ANyxG6ymnEQ2FsLQsoMlYB2vV1sO3m8tQ== dependencies: - immer "^9.0.16" - redux "^4.2.0" + immer "^9.0.21" + redux "^4.2.1" redux-thunk "^2.4.2" - reselect "^4.1.7" + reselect "^4.1.8" "@rollup/pluginutils@^4.2.1": version "4.2.1" @@ -1357,71 +1397,71 @@ resolved "https://registry.yarnpkg.com/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz#96116f2a912e0c02817345b3c10751069920d553" integrity sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg== -"@swc/core-darwin-arm64@1.3.37": - version "1.3.37" - resolved "https://registry.yarnpkg.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.37.tgz#a92e075ae35f18a64aaf3823ea175f03564f8da1" - integrity sha512-iIyVqqioUpVeT/hbBVfkrsjfCyL4idNH+LVKGmoTAWaTTSB0+UNhNuA7Wh2CqIHWh1Mv7IlumitWPcqsVDdoEw== +"@swc/core-darwin-arm64@1.3.55": + version "1.3.55" + resolved "https://registry.yarnpkg.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.55.tgz#bd7fdf838a8d27c3df98d279017710a2da6af6a3" + integrity sha512-UnHC8aPg/JvHhgXxTU6EhTtfnYNS7nhq8EKB8laNPxlHbwEyMBVQ2QuJHlNCtFtvSfX/uH5l04Ld1iGXnBTfdQ== -"@swc/core-darwin-x64@1.3.37": - version "1.3.37" - resolved "https://registry.yarnpkg.com/@swc/core-darwin-x64/-/core-darwin-x64-1.3.37.tgz#a3cc06c87140a2ca0b8e7ef1f3d5cc34dd080429" - integrity sha512-dao5nXPWKxtaxqak4ZkRyBoApNIelW/glantQhPhj0FjMjuIQc+v03ldJ8XDByWOG+6xuVUTheANCtEccxoQBw== +"@swc/core-darwin-x64@1.3.55": + version "1.3.55" + resolved "https://registry.yarnpkg.com/@swc/core-darwin-x64/-/core-darwin-x64-1.3.55.tgz#da7e4076cce35e42f2688f7aae1fd26ecb5dcbef" + integrity sha512-VNJkFVARrktIqtaLrD1NFA54gqekH7eAUcUY2U2SdHwO67HYjfMXMxlugLP5PDasSKpTkrVooUdhkffoA5W50g== -"@swc/core-linux-arm-gnueabihf@1.3.37": - version "1.3.37" - resolved "https://registry.yarnpkg.com/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.3.37.tgz#f7d8f8523830c6be653f608839d4bd5598457f1f" - integrity sha512-/mVrc8H/f062CUkqKGmBiil2VIYu4mKawHxERfeP1y38X5K/OwjG5s9MgO9TVxy+Ly6vejwj70kRhSa3hVp1Bw== +"@swc/core-linux-arm-gnueabihf@1.3.55": + version "1.3.55" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.3.55.tgz#fd9214d5050987b312cbe9aa105d48365899c1d8" + integrity sha512-6OcohhIFKKNW/TpJt26Tpul8zyL7dmp1Lnyj2BX9ycsZZ5UnsNiGqn37mrqJgVTx/ansEmbyOmKu2mzm/Ct6cQ== -"@swc/core-linux-arm64-gnu@1.3.37": - version "1.3.37" - resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.3.37.tgz#b162febd9de14fb08000c722b063be2bb5aefa6b" - integrity sha512-eRQ3KaZI0j5LidTfOIi/kUVOOMuVmw1HCdt/Z1TAUKoHMLVxY8xcJ3pEE3/+ednI60EmHpwpJRs6LelXyL6uzQ== +"@swc/core-linux-arm64-gnu@1.3.55": + version "1.3.55" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.3.55.tgz#214a4c1c89d9bab9277843b526b32463a98c516b" + integrity sha512-MfZtXGBv21XWwvrSMP0CMxScDolT/iv5PRl9UBprYUehwWr7BNjA3V9W7QQ+kKoPyORWk7LX7OpJZF3FnO618Q== -"@swc/core-linux-arm64-musl@1.3.37": - version "1.3.37" - resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.3.37.tgz#3b1a628e880fbb1a5e2a7a46d42e8aa878c6bfdd" - integrity sha512-w2BRLODyxNQY2rfHZMZ5ir6QrrnGBPlnIslTrgKmVbn1OjZoxUCtuqhrYnCmybaAc4DOkeH02TqynEFXrm+EMw== +"@swc/core-linux-arm64-musl@1.3.55": + version "1.3.55" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.3.55.tgz#21a11fd919883bc0dc0ceb686f2627c1dc279b71" + integrity sha512-iZJo+7L5lv10W0f0C6SlyteAyMJt5Tp+aH3+nlAwKdtc+VjyL1sGhR8DJMXp2/buBRZJ9tjEtpXKDaWUdSdF7Q== -"@swc/core-linux-x64-gnu@1.3.37": - version "1.3.37" - resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.37.tgz#ed443ad77dc90e415267d02a38e4113047b2d3d8" - integrity sha512-CfoH8EsZJZ9kunjMUjBNYD5fFuO86zw+K/o4wEw72Yg6ZEiqPmeIlCKU8tpTv4sK+CbhUXrmVzMB5tqsb2jALQ== +"@swc/core-linux-x64-gnu@1.3.55": + version "1.3.55" + resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.55.tgz#3cdf5e669e8d1ef3a1fd4249e535d53d4768a009" + integrity sha512-Rmc8ny/mslzzz0+wNK9/mLdyAWVbMZHRSvljhpzASmq48NBkmZ5vk9/WID6MnUz2e9cQ0JxJQs8t39KlFJtW3g== -"@swc/core-linux-x64-musl@1.3.37": - version "1.3.37" - resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.3.37.tgz#de607a4985458bd6e8b0e40f0d62d0e26bd8df1e" - integrity sha512-9YPrHYNdoG7PK11gV51GfL45biI2dic+YTqHUDKyykemsD7Ot1zUFX7Ty//pdvpKcKSff6SrHbfFACD5ziNirA== +"@swc/core-linux-x64-musl@1.3.55": + version "1.3.55" + resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.3.55.tgz#099f75a04827afe59c8755498c749ac667635749" + integrity sha512-Ymoc4xxINzS93ZjVd2UZfLZk1jF6wHjdCbC1JF+0zK3IrNrxCIDoWoaAj0+Bbvyo3hD1Xg/cneSTsqX8amnnuQ== -"@swc/core-win32-arm64-msvc@1.3.37": - version "1.3.37" - resolved "https://registry.yarnpkg.com/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.3.37.tgz#d5851a47d7df183929b9746d56f76c282f940e6a" - integrity sha512-h17Ek8/wCDje6BrXOvCXBM80oBRmTSMMdLyt87whTl5xqYlWYYs9oQIzZndNRTlNpTgjGO8Ns2eo4kwVxIkBIA== +"@swc/core-win32-arm64-msvc@1.3.55": + version "1.3.55" + resolved "https://registry.yarnpkg.com/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.3.55.tgz#e70b3cc06bbd6c04ebb7c1af1da1301d52dc5260" + integrity sha512-OhnmFstq2qRU2GI5I0G/8L+vc2rx8+w+IOA6EZBrY4FuMCbPIZKKzlnAIxYn2W+yD4gvBzYP3tgEcaDfQk6EkA== -"@swc/core-win32-ia32-msvc@1.3.37": - version "1.3.37" - resolved "https://registry.yarnpkg.com/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.3.37.tgz#06ad7016f61b56aec4abf60eab3a91b786f9e294" - integrity sha512-1BR175E1olGy/zdt94cgdb6ps/lBNissAOaxyBk8taFpcjy3zpdP30yAoH0GIsC6isnZ5JfArbOJNRXXO5tE0Q== +"@swc/core-win32-ia32-msvc@1.3.55": + version "1.3.55" + resolved "https://registry.yarnpkg.com/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.3.55.tgz#d2780198baec4aff1d01cb89a53dab53003e127c" + integrity sha512-3VR5rHZ6uoL/Vo3djV30GgX2oyDwWWsk+Yp+nyvYyBaKYiH2zeHfxdYRLSQV3W7kSlCAH3oDYpSljrWZ0t5XEQ== -"@swc/core-win32-x64-msvc@1.3.37": - version "1.3.37" - resolved "https://registry.yarnpkg.com/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.3.37.tgz#60139a7089003a7447a4efef9704ae8fde21995e" - integrity sha512-1siDQ7dccQ1pesJmgAL3BUBbRPtfbNInOWnZOkiie/DfFqGQ117QKnCVyjUvwFKfTQx1+3UUTDmMSlRd00SlXg== +"@swc/core-win32-x64-msvc@1.3.55": + version "1.3.55" + resolved "https://registry.yarnpkg.com/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.3.55.tgz#6f9b9ac3f820f5a8476f93863b558c3b727be3d0" + integrity sha512-KBtMFtRwnbxBugYf6i2ePqEGdxsk715KcqGMjGhxNg7BTACnXnhj37irHu2e7A7wZffbkUVUYuj/JEgVkEjSxg== -"@swc/core@^1.2.177", "@swc/core@^1.3.35": - version "1.3.37" - resolved "https://registry.yarnpkg.com/@swc/core/-/core-1.3.37.tgz#644653fa7deb20c7c342e7fd019c7abc44ecf1bf" - integrity sha512-VOFlEQ1pReOM73N9A7R8rt561GU8Rxsq833jiimWDUB2sXEN3V6n6wFTgYmZuMz2T4/R0cQA1nV48KkaT4gkFw== +"@swc/core@^1.2.177", "@swc/core@^1.3.42": + version "1.3.55" + resolved "https://registry.yarnpkg.com/@swc/core/-/core-1.3.55.tgz#0886c07fb6d32803fee85cf135c1a3352142d51f" + integrity sha512-w/lN3OuJsuy868yJZKop+voZLVzI5pVSoopQVtgDNkEzejnPuRp9XaeAValvuMaWqKoTMtOjLzEPyv/xiAGYQQ== optionalDependencies: - "@swc/core-darwin-arm64" "1.3.37" - "@swc/core-darwin-x64" "1.3.37" - "@swc/core-linux-arm-gnueabihf" "1.3.37" - "@swc/core-linux-arm64-gnu" "1.3.37" - "@swc/core-linux-arm64-musl" "1.3.37" - "@swc/core-linux-x64-gnu" "1.3.37" - "@swc/core-linux-x64-musl" "1.3.37" - "@swc/core-win32-arm64-msvc" "1.3.37" - "@swc/core-win32-ia32-msvc" "1.3.37" - "@swc/core-win32-x64-msvc" "1.3.37" + "@swc/core-darwin-arm64" "1.3.55" + "@swc/core-darwin-x64" "1.3.55" + "@swc/core-linux-arm-gnueabihf" "1.3.55" + "@swc/core-linux-arm64-gnu" "1.3.55" + "@swc/core-linux-arm64-musl" "1.3.55" + "@swc/core-linux-x64-gnu" "1.3.55" + "@swc/core-linux-x64-musl" "1.3.55" + "@swc/core-win32-arm64-msvc" "1.3.55" + "@swc/core-win32-ia32-msvc" "1.3.55" + "@swc/core-win32-x64-msvc" "1.3.55" "@szmarczak/http-timer@^1.1.2": version "1.1.2" @@ -1666,17 +1706,17 @@ integrity sha512-SZg4JdHIWHQGEokbYGZSDvo5wA4TLYPXaqhigs/wH+REDOejcJzgH+qyY+HtEUtWOZxEUkbhbdYPqQDiEgrXeA== "@types/eslint@^8.4.5": - version "8.21.1" - resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.21.1.tgz#110b441a210d53ab47795124dbc3e9bb993d1e7c" - integrity sha512-rc9K8ZpVjNcLs8Fp0dkozd5Pt2Apk1glO4Vgz8ix1u6yFByxfqo5Yavpy65o+93TAe24jr7v+eSBtFLvOQtCRQ== + version "8.37.0" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.37.0.tgz#29cebc6c2a3ac7fea7113207bf5a828fdf4d7ef1" + integrity sha512-Piet7dG2JBuDIfohBngQ3rCt7MgO9xCO4xIMKxBThCq5PNRB91IjlJ10eJVwfoNtvTErmxLzwBZ7rHZtbOMmFQ== dependencies: "@types/estree" "*" "@types/json-schema" "*" "@types/estree@*": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.0.tgz#5fb2e536c1ae9bf35366eed879e827fa59ca41c2" - integrity sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ== + version "1.0.1" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.1.tgz#aa22750962f3bf0e79d753d3cc067f010c95f194" + integrity sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA== "@types/geojson@*": version "7946.0.10" @@ -1708,12 +1748,7 @@ dependencies: "@types/lodash" "*" -"@types/lodash@*": - version "4.14.191" - resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.191.tgz#09511e7f7cba275acd8b419ddac8da9a6a79e2fa" - integrity sha512-BdZ5BCCvho3EIXw6wUCXHe7rS53AIDPLE+JzwgT+OsJk53oBfbSmZZ7CX4VaRoN78N+TJpFi9QPlfIVNmJYWxQ== - -"@types/lodash@^4.14.194": +"@types/lodash@*", "@types/lodash@^4.14.194": version "4.14.194" resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.194.tgz#b71eb6f7a0ff11bff59fc987134a093029258a76" integrity sha512-r22s9tAS7imvBt2lyHC9B8AGwWnXaYb1tY09oyLkXDs4vArpYJzw09nj8MLx5VfciBPGIb+ZwG0ssYnEPJxn/g== @@ -1728,10 +1763,10 @@ resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf" integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w== -"@types/react-dom@^18.0.11": - version "18.0.11" - resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.0.11.tgz#321351c1459bc9ca3d216aefc8a167beec334e33" - integrity sha512-O38bPbI2CWtgw/OoQoY+BRelw7uysmXbWvw3nLWO21H1HSh+GOlqPuXshJfjmpNlKiiSDG9cc1JZAaMmVdcTlw== +"@types/react-dom@^18.2.1": + version "18.2.1" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.2.1.tgz#663b2612feb5f6431a70207430d7c04881b87f29" + integrity sha512-8QZEV9+Kwy7tXFmjJrp3XUKQSs9LTnE0KnoUb0YCguWBiNW0Yfb2iBMYZ08WPg35IR6P3Z0s00B15SwZnO26+w== dependencies: "@types/react" "*" @@ -1749,19 +1784,19 @@ dependencies: "@types/react" "*" -"@types/react@*", "@types/react@^18.0.28": - version "18.0.28" - resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.28.tgz#accaeb8b86f4908057ad629a26635fe641480065" - integrity sha512-RD0ivG1kEztNBdoAK7lekI9M+azSnitIn85h4iOiaLjaTrMjzslhaqCGaI4IyCJ1RljWiLCEu4jyrLLgqxBTew== +"@types/react@*", "@types/react@^18.2.0": + version "18.2.0" + resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.0.tgz#15cda145354accfc09a18d2f2305f9fc099ada21" + integrity sha512-0FLj93y5USLHdnhIhABk83rm8XEGA7kH3cr+YUlvxoUGp1xNt/DINUMvqPxLyOQMzLmZe8i4RTHbvb8MC7NmrA== dependencies: "@types/prop-types" "*" "@types/scheduler" "*" csstype "^3.0.2" "@types/scheduler@*": - version "0.16.2" - resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39" - integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew== + version "0.16.3" + resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.3.tgz#cef09e3ec9af1d63d2a6cc5b383a737e24e6dcf5" + integrity sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ== "@types/semver@^7.3.12": version "7.3.13" @@ -1778,47 +1813,47 @@ resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-9.0.1.tgz#98586dc36aee8dacc98cc396dbca8d0429647aa6" integrity sha512-rFT3ak0/2trgvp4yYZo5iKFEPsET7vKydKF+VRCxlQ9bpheehyAJH89dAkaLEq/j/RZXJIqcgsmPJKUP1Z28HA== -"@typescript-eslint/eslint-plugin@^5.52.0": - version "5.54.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.54.0.tgz#2c821ad81b2c786d142279a8292090f77d1881f4" - integrity sha512-+hSN9BdSr629RF02d7mMtXhAJvDTyCbprNYJKrXETlul/Aml6YZwd90XioVbjejQeHbb3R8Dg0CkRgoJDxo8aw== +"@typescript-eslint/eslint-plugin@^5.59.1": + version "5.59.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.1.tgz#9b09ee1541bff1d2cebdcb87e7ce4a4003acde08" + integrity sha512-AVi0uazY5quFB9hlp2Xv+ogpfpk77xzsgsIEWyVS7uK/c7MZ5tw7ZPbapa0SbfkqE0fsAMkz5UwtgMLVk2BQAg== dependencies: - "@typescript-eslint/scope-manager" "5.54.0" - "@typescript-eslint/type-utils" "5.54.0" - "@typescript-eslint/utils" "5.54.0" + "@eslint-community/regexpp" "^4.4.0" + "@typescript-eslint/scope-manager" "5.59.1" + "@typescript-eslint/type-utils" "5.59.1" + "@typescript-eslint/utils" "5.59.1" debug "^4.3.4" grapheme-splitter "^1.0.4" ignore "^5.2.0" natural-compare-lite "^1.4.0" - regexpp "^3.2.0" semver "^7.3.7" tsutils "^3.21.0" -"@typescript-eslint/parser@^5.52.0": - version "5.54.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.54.0.tgz#def186eb1b1dbd0439df0dacc44fb6d8d5c417fe" - integrity sha512-aAVL3Mu2qTi+h/r04WI/5PfNWvO6pdhpeMRWk9R7rEV4mwJNzoWf5CCU5vDKBsPIFQFjEq1xg7XBI2rjiMXQbQ== +"@typescript-eslint/parser@^5.59.1": + version "5.59.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.59.1.tgz#73c2c12127c5c1182d2e5b71a8fa2a85d215cbb4" + integrity sha512-nzjFAN8WEu6yPRDizIFyzAfgK7nybPodMNFGNH0M9tei2gYnYszRDqVA0xlnRjkl7Hkx2vYrEdb6fP2a21cG1g== dependencies: - "@typescript-eslint/scope-manager" "5.54.0" - "@typescript-eslint/types" "5.54.0" - "@typescript-eslint/typescript-estree" "5.54.0" + "@typescript-eslint/scope-manager" "5.59.1" + "@typescript-eslint/types" "5.59.1" + "@typescript-eslint/typescript-estree" "5.59.1" debug "^4.3.4" -"@typescript-eslint/scope-manager@5.54.0": - version "5.54.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.54.0.tgz#74b28ac9a3fc8166f04e806c957adb8c1fd00536" - integrity sha512-VTPYNZ7vaWtYna9M4oD42zENOBrb+ZYyCNdFs949GcN8Miwn37b8b7eMj+EZaq7VK9fx0Jd+JhmkhjFhvnovhg== +"@typescript-eslint/scope-manager@5.59.1": + version "5.59.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.59.1.tgz#8a20222719cebc5198618a5d44113705b51fd7fe" + integrity sha512-mau0waO5frJctPuAzcxiNWqJR5Z8V0190FTSqRw1Q4Euop6+zTwHAf8YIXNwDOT29tyUDrQ65jSg9aTU/H0omA== dependencies: - "@typescript-eslint/types" "5.54.0" - "@typescript-eslint/visitor-keys" "5.54.0" + "@typescript-eslint/types" "5.59.1" + "@typescript-eslint/visitor-keys" "5.59.1" -"@typescript-eslint/type-utils@5.54.0": - version "5.54.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.54.0.tgz#390717216eb61393a0cad2995da154b613ba7b26" - integrity sha512-WI+WMJ8+oS+LyflqsD4nlXMsVdzTMYTxl16myXPaCXnSgc7LWwMsjxQFZCK/rVmTZ3FN71Ct78ehO9bRC7erYQ== +"@typescript-eslint/type-utils@5.59.1": + version "5.59.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.59.1.tgz#63981d61684fd24eda2f9f08c0a47ecb000a2111" + integrity sha512-ZMWQ+Oh82jWqWzvM3xU+9y5U7MEMVv6GLioM3R5NJk6uvP47kZ7YvlgSHJ7ERD6bOY7Q4uxWm25c76HKEwIjZw== dependencies: - "@typescript-eslint/typescript-estree" "5.54.0" - "@typescript-eslint/utils" "5.54.0" + "@typescript-eslint/typescript-estree" "5.59.1" + "@typescript-eslint/utils" "5.59.1" debug "^4.3.4" tsutils "^3.21.0" @@ -1827,18 +1862,18 @@ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.33.0.tgz#a1e59036a3b53ae8430ceebf2a919dc7f9af6d72" integrity sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ== -"@typescript-eslint/types@5.54.0": - version "5.54.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.54.0.tgz#7d519df01f50739254d89378e0dcac504cab2740" - integrity sha512-nExy+fDCBEgqblasfeE3aQ3NuafBUxZxgxXcYfzYRZFHdVvk5q60KhCSkG0noHgHRo/xQ/BOzURLZAafFpTkmQ== +"@typescript-eslint/types@5.59.1": + version "5.59.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.59.1.tgz#03f3fedd1c044cb336ebc34cc7855f121991f41d" + integrity sha512-dg0ICB+RZwHlysIy/Dh1SP+gnXNzwd/KS0JprD3Lmgmdq+dJAJnUPe1gNG34p0U19HvRlGX733d/KqscrGC1Pg== -"@typescript-eslint/typescript-estree@5.54.0", "@typescript-eslint/typescript-estree@^5.13.0": - version "5.54.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.54.0.tgz#f6f3440cabee8a43a0b25fa498213ebb61fdfe99" - integrity sha512-X2rJG97Wj/VRo5YxJ8Qx26Zqf0RRKsVHd4sav8NElhbZzhpBI8jU54i6hfo9eheumj4oO4dcRN1B/zIVEqR/MQ== +"@typescript-eslint/typescript-estree@5.59.1", "@typescript-eslint/typescript-estree@^5.55.0": + version "5.59.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.1.tgz#4aa546d27fd0d477c618f0ca00b483f0ec84c43c" + integrity sha512-lYLBBOCsFltFy7XVqzX0Ju+Lh3WPIAWxYpmH/Q7ZoqzbscLiCW00LeYCdsUnnfnj29/s1WovXKh2gwCoinHNGA== dependencies: - "@typescript-eslint/types" "5.54.0" - "@typescript-eslint/visitor-keys" "5.54.0" + "@typescript-eslint/types" "5.59.1" + "@typescript-eslint/visitor-keys" "5.59.1" debug "^4.3.4" globby "^11.1.0" is-glob "^4.0.3" @@ -1858,18 +1893,18 @@ semver "^7.3.5" tsutils "^3.21.0" -"@typescript-eslint/utils@5.54.0": - version "5.54.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.54.0.tgz#3db758aae078be7b54b8ea8ea4537ff6cd3fbc21" - integrity sha512-cuwm8D/Z/7AuyAeJ+T0r4WZmlnlxQ8wt7C7fLpFlKMR+dY6QO79Cq1WpJhvZbMA4ZeZGHiRWnht7ZJ8qkdAunw== +"@typescript-eslint/utils@5.59.1": + version "5.59.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.59.1.tgz#d89fc758ad23d2157cfae53f0b429bdf15db9473" + integrity sha512-MkTe7FE+K1/GxZkP5gRj3rCztg45bEhsd8HYjczBuYm+qFHP5vtZmjx3B0yUCDotceQ4sHgTyz60Ycl225njmA== dependencies: + "@eslint-community/eslint-utils" "^4.2.0" "@types/json-schema" "^7.0.9" "@types/semver" "^7.3.12" - "@typescript-eslint/scope-manager" "5.54.0" - "@typescript-eslint/types" "5.54.0" - "@typescript-eslint/typescript-estree" "5.54.0" + "@typescript-eslint/scope-manager" "5.59.1" + "@typescript-eslint/types" "5.59.1" + "@typescript-eslint/typescript-estree" "5.59.1" eslint-scope "^5.1.1" - eslint-utils "^3.0.0" semver "^7.3.7" "@typescript-eslint/visitor-keys@4.33.0": @@ -1880,35 +1915,35 @@ "@typescript-eslint/types" "4.33.0" eslint-visitor-keys "^2.0.0" -"@typescript-eslint/visitor-keys@5.54.0": - version "5.54.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.54.0.tgz#846878afbf0cd67c19cfa8d75947383d4490db8f" - integrity sha512-xu4wT7aRCakGINTLGeyGqDn+78BwFlggwBjnHa1ar/KaGagnmwLYmlrXIrgAaQ3AE1Vd6nLfKASm7LrFHNbKGA== +"@typescript-eslint/visitor-keys@5.59.1": + version "5.59.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.1.tgz#0d96c36efb6560d7fb8eb85de10442c10d8f6058" + integrity sha512-6waEYwBTCWryx0VJmP7JaM4FpipLsFl9CvYf2foAE8Qh/Y0s+bxWysciwOs0LTBED4JCaNxTZ5rGadB14M6dwA== dependencies: - "@typescript-eslint/types" "5.54.0" + "@typescript-eslint/types" "5.59.1" eslint-visitor-keys "^3.3.0" -"@vitejs/plugin-react-swc@^3.2.0": - version "3.2.0" - resolved "https://registry.yarnpkg.com/@vitejs/plugin-react-swc/-/plugin-react-swc-3.2.0.tgz#7c4f6e116a296c27f680d05750f9dbf798cf7709" - integrity sha512-IcBoXL/mcH7JdQr/nfDlDwTdIaH8Rg7LpfQDF4nAht+juHWIuv6WhpKPCSfY4+zztAaB07qdBoFz1XCZsgo3pQ== +"@vitejs/plugin-react-swc@^3.3.0": + version "3.3.0" + resolved "https://registry.yarnpkg.com/@vitejs/plugin-react-swc/-/plugin-react-swc-3.3.0.tgz#d443a4bbb423542c5a089c65a58dca597170c549" + integrity sha512-Ycg+n2eyCOTpn/wRy+evVo859+hw7qCj9iaX5CMny6x1fx1Uoq0xBG+a98lFtwLNGfGEnpI0F26YigRuxCRkwg== dependencies: - "@swc/core" "^1.3.35" + "@swc/core" "^1.3.42" "@yarnpkg/lockfile@^1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz#e77a97fbd345b76d83245edcd17d393b1b41fb31" integrity sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ== -"@zag-js/element-size@0.3.1": - version "0.3.1" - resolved "https://registry.yarnpkg.com/@zag-js/element-size/-/element-size-0.3.1.tgz#f9f6ae98355e2250d18d0f6e2f1134a0ae4c6a2f" - integrity sha512-jR5j4G//bRzcxwAACWi9EfITnwjNmn10LxF4NmALrdZU7/PNWP3uUCdhCxd/0SCyeiJXUl0yvD57rWAbKPs1nw== +"@zag-js/element-size@0.3.2": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@zag-js/element-size/-/element-size-0.3.2.tgz#ebb76af2a024230482406db41344598d1a9f54f4" + integrity sha512-bVvvigUGvAuj7PCkE5AbzvTJDTw5f3bg9nQdv+ErhVN8SfPPppLJEmmWdxqsRzrHXgx8ypJt/+Ty0kjtISVDsQ== -"@zag-js/focus-visible@0.2.1": - version "0.2.1" - resolved "https://registry.yarnpkg.com/@zag-js/focus-visible/-/focus-visible-0.2.1.tgz#bf4f1009f4fd35a9728dfaa9214d8cb318fe8b1e" - integrity sha512-19uTjoZGP4/Ax7kSNhhay9JA83BirKzpqLkeEAilrpdI1hE5xuq6q+tzJOsrMOOqJrm7LkmZp5lbsTQzvK2pYg== +"@zag-js/focus-visible@0.2.2": + version "0.2.2" + resolved "https://registry.yarnpkg.com/@zag-js/focus-visible/-/focus-visible-0.2.2.tgz#56233480ca1275d3218fb2e10696a33d1a6b9e64" + integrity sha512-0j2gZq8HiZ51z4zNnSkF1iSkqlwRDvdH+son3wHdoz+7IUdMN/5Exd4TxMJ+gq2Of1DiXReYLL9qqh2PdQ4wgA== acorn-jsx@^5.3.2: version "5.3.2" @@ -2015,12 +2050,20 @@ argparse@^2.0.1: integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== aria-hidden@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/aria-hidden/-/aria-hidden-1.2.2.tgz#8c4f7cc88d73ca42114106fdf6f47e68d31475b8" - integrity sha512-6y/ogyDTk/7YAe91T3E2PR1ALVKyM2QbTio5HwM+N1Q6CMlCKhvClyIjkckBswa0f2xJhjsfzIGa1yVSe1UMVA== + version "1.2.3" + resolved "https://registry.yarnpkg.com/aria-hidden/-/aria-hidden-1.2.3.tgz#14aeb7fb692bbb72d69bebfa47279c1fd725e954" + integrity sha512-xcLxITLe2HYa1cnYnwCjkOO1PqUHQpozB8x9AR0OgWN2woOBi5kSDVxKfd0b7sb1hw5qFeJhXm9H1nu3xSfLeQ== dependencies: tslib "^2.0.0" +array-buffer-byte-length@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz#fabe8bc193fea865f317fe7807085ee0dee5aead" + integrity sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A== + dependencies: + call-bind "^1.0.2" + is-array-buffer "^3.0.1" + array-includes@^3.1.5, array-includes@^3.1.6: version "3.1.6" resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.6.tgz#9e9e720e194f198266ba9e18c29e6a9b0e4b225f" @@ -2068,6 +2111,11 @@ ast-module-types@^3.0.0: resolved "https://registry.yarnpkg.com/ast-module-types/-/ast-module-types-3.0.0.tgz#9a6d8a80f438b6b8fe4995699d700297f398bf81" integrity sha512-CMxMCOCS+4D+DkOQfuZf+vLrSEmY/7xtORwdxs4wtcC1wVgvk2MqFFTwQCFhvWsI4KPU9lcWXPI8DgRiz+xetQ== +ast-module-types@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/ast-module-types/-/ast-module-types-4.0.0.tgz#17e1cadd5b5b108e7295b0cf0cff21ccc226b639" + integrity sha512-Kd0o8r6CDazJGCRzs8Ivpn0xj19oNKrULhoJFzhGjRsLpekF2zyZs9Ukz+JvZhWD6smszfepakTFhAaYpsI12g== + astral-regex@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" @@ -2093,10 +2141,10 @@ available-typed-arrays@^1.0.5: resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== -axios@^1.3.4: - version "1.3.4" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.3.4.tgz#f5760cefd9cfb51fd2481acf88c05f67c4523024" - integrity sha512-toYm+Bsyl6VC5wSkfkbbNB6ROv7KY93PEBBL6xyDczaIHasAiv4wPqQ/c4RjoQzipxRD2W5g21cOqQulZ7rHwQ== +axios@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.4.0.tgz#38a7bf1224cd308de271146038b551d725f0be1f" + integrity sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA== dependencies: follow-redirects "^1.15.0" form-data "^4.0.0" @@ -2226,6 +2274,11 @@ chakra-ui-contextmenu@^1.0.5: resolved "https://registry.yarnpkg.com/chakra-ui-contextmenu/-/chakra-ui-contextmenu-1.0.5.tgz#de54ad83c413a62040a06fefd3d73264a580a987" integrity sha512-0pvi2RmNFpaoXPBT8mRDBZ1q6Ic8lE7YIyHBMgx4AubgN7dySww4SlN9g3mKWN3egkBL/ORCmxRfW6AlDeR+Nw== +chalk@5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.2.0.tgz#249623b7d66869c673699fb66d65723e54dfcfb3" + integrity sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA== + chalk@^2.0.0, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" @@ -2271,6 +2324,11 @@ ci-info@^2.0.0: resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== +ci-info@^3.7.0: + version "3.8.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.8.0.tgz#81408265a5380c929f0bc665d62256628ce9ef91" + integrity sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw== + classcat@^5.0.3, classcat@^5.0.4: version "5.0.4" resolved "https://registry.yarnpkg.com/classcat/-/classcat-5.0.4.tgz#e12d1dfe6df6427f260f03b80dc63571a5107ba6" @@ -2322,9 +2380,9 @@ cli-handle-unhandled@^1.1.1: cli-handle-error "^4.1.0" cli-spinners@^2.5.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.7.0.tgz#f815fd30b5f9eaac02db604c7a231ed7cb2f797a" - integrity sha512-qu3pN8Y3qHNgE2AFweciB1IfMnmZ/fsNTEE+NOFjmGB2F/7rLhnhzppvpCnN4FovtP26k8lHyy9ptEbNwWFLzw== + version "2.8.0" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.8.0.tgz#e97a3e2bd00e6d85aa0c13d7f9e3ce236f7787fc" + integrity sha512-/eG5sJcvEIwxcdYM86k5tPwn0MUzkX5YY3eImTGpJOZgVe4SdTMY14vQpcxgBzJ0wXwAYrS8E+c3uHeK4JNyzQ== cli-truncate@^2.1.0: version "2.1.0" @@ -2402,9 +2460,9 @@ color2k@^2.0.0: integrity sha512-kJhwH5nAwb34tmyuqq/lgjEKzlFXn1U99NlnB6Ws4qVaERcRUYeYP1cBw6BJ4vxaWStAUEef4WMr7WjOCnBt8w== colorette@^2.0.19: - version "2.0.19" - resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.19.tgz#cdf044f47ad41a0f4b56b3a0d5b4e6e1a2d5a798" - integrity sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ== + version "2.0.20" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" + integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== combined-stream@^1.0.8: version "1.0.8" @@ -2413,6 +2471,11 @@ combined-stream@^1.0.8: dependencies: delayed-stream "~1.0.0" +commander@^10.0.0: + version "10.0.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" + integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== + commander@^2.16.0, commander@^2.20.0, commander@^2.20.3, commander@^2.8.1: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" @@ -2423,7 +2486,7 @@ commander@^7.2.0: resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== -commander@^9.1.0, commander@^9.3.0, commander@^9.4.1: +commander@^9.3.0, commander@^9.5.0: version "9.5.0" resolved "https://registry.yarnpkg.com/commander/-/commander-9.5.0.tgz#bc08d1eb5cedf7ccb797a96199d41c7bc3e60d30" integrity sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ== @@ -2443,20 +2506,20 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== -concurrently@^7.6.0: - version "7.6.0" - resolved "https://registry.yarnpkg.com/concurrently/-/concurrently-7.6.0.tgz#531a6f5f30cf616f355a4afb8f8fcb2bba65a49a" - integrity sha512-BKtRgvcJGeZ4XttiDiNcFiRlxoAeZOseqUvyYRUp/Vtd+9p1ULmeoSqGsDA+2ivdeDFpqrJvGvmI+StKfKl5hw== +concurrently@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/concurrently/-/concurrently-8.0.1.tgz#80c0591920a9fa3e68ba0dd8aa6eac8487eb904c" + integrity sha512-Sh8bGQMEL0TAmAm2meAXMjcASHZa7V0xXQVDBLknCPa9TPtkY9yYs+0cnGGgfdkW0SV1Mlg+hVGfXcoI8d3MJA== dependencies: - chalk "^4.1.0" - date-fns "^2.29.1" + chalk "^4.1.2" + date-fns "^2.29.3" lodash "^4.17.21" - rxjs "^7.0.0" - shell-quote "^1.7.3" - spawn-command "^0.0.2-1" - supports-color "^8.1.0" + rxjs "^7.8.0" + shell-quote "^1.8.0" + spawn-command "0.0.2-1" + supports-color "^8.1.1" tree-kill "^1.2.2" - yargs "^17.3.1" + yargs "^17.7.1" configstore@^5.0.1: version "5.0.1" @@ -2505,17 +2568,6 @@ cross-fetch@3.1.5: dependencies: node-fetch "2.6.7" -cross-spawn@^6.0.5: - version "6.0.5" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" - integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== - dependencies: - nice-try "^1.0.4" - path-key "^2.0.1" - semver "^5.5.0" - shebang-command "^1.2.0" - which "^1.2.9" - cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" @@ -2538,9 +2590,9 @@ css-box-model@1.2.1: tiny-invariant "^1.0.6" csstype@^3.0.11, csstype@^3.0.2: - version "3.1.1" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.1.tgz#841b532c45c758ee546a11d5bd7b7b473c8c30b9" - integrity sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw== + version "3.1.2" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.2.tgz#1d4bf9d572f11c14031f0436e1c10bc1f571f50b" + integrity sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ== "d3-color@1 - 3": version "3.1.0" @@ -2604,7 +2656,7 @@ d3-zoom@^3.0.0: d3-selection "2 - 3" d3-transition "2 - 3" -date-fns@^2.29.1: +date-fns@^2.29.3: version "2.29.3" resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.29.3.tgz#27402d2fc67eb442b511b70bbdf98e6411cd68a8" integrity sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA== @@ -2660,7 +2712,7 @@ define-lazy-prop@^2.0.0: resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== -define-properties@^1.1.3, define-properties@^1.1.4: +define-properties@^1.1.3, define-properties@^1.1.4, define-properties@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.0.tgz#52988570670c9eacedd8064f4a990f2405849bd5" integrity sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA== @@ -2699,15 +2751,15 @@ detective-amd@^3.1.0: get-amd-module-type "^3.0.0" node-source-walk "^4.2.0" -detective-amd@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/detective-amd/-/detective-amd-4.0.1.tgz#1a827d9e4fa2f832506bd87aa392f124155bca3a" - integrity sha512-bDo22IYbJ8yzALB0Ow5CQLtyhU1BpDksLB9dsWHI9Eh0N3OQR6aQqhjPsNDd69ncYwRfL1sTo7OA9T3VRVSe2Q== +detective-amd@^4.0.1, detective-amd@^4.1.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/detective-amd/-/detective-amd-4.2.0.tgz#21c43465669f06cf894eef047a27e6e72ba6bc13" + integrity sha512-RbuEJHz78A8nW7CklkqTzd8lDCN42En53dgEIsya0DilpkwslamSZDasLg8dJyxbw46OxhSQeY+C2btdSkCvQQ== dependencies: - ast-module-types "^3.0.0" + ast-module-types "^4.0.0" escodegen "^2.0.0" - get-amd-module-type "^4.0.0" - node-source-walk "^5.0.0" + get-amd-module-type "^4.1.0" + node-source-walk "^5.0.1" detective-cjs@^3.1.1: version "3.1.3" @@ -2717,13 +2769,13 @@ detective-cjs@^3.1.1: ast-module-types "^3.0.0" node-source-walk "^4.0.0" -detective-cjs@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/detective-cjs/-/detective-cjs-4.0.0.tgz#316e2c7ae14276a5dcfe0c43dc05d8cf9a0e5cf9" - integrity sha512-VsD6Yo1+1xgxJWoeDRyut7eqZ8EWaJI70C5eanSAPcBHzenHZx0uhjxaaEfIm0cHII7dBiwU98Orh44bwXN2jg== +detective-cjs@^4.0.0, detective-cjs@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/detective-cjs/-/detective-cjs-4.1.0.tgz#56b1558ca0910933c7fc47c740b957f0280ff302" + integrity sha512-QxzMwt5MfPLwS7mG30zvnmOvHLx5vyVvjsAV6gQOyuMoBR5G1DhS1eJZ4P10AlH+HSnk93mTcrg3l39+24XCtg== dependencies: - ast-module-types "^3.0.0" - node-source-walk "^5.0.0" + ast-module-types "^4.0.0" + node-source-walk "^5.0.1" detective-es6@^2.2.1: version "2.2.2" @@ -2732,10 +2784,10 @@ detective-es6@^2.2.1: dependencies: node-source-walk "^4.0.0" -detective-es6@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/detective-es6/-/detective-es6-3.0.0.tgz#78c9ef5492d5b59748b411aecaaf52b5ca0f0bc2" - integrity sha512-Uv2b5Uih7vorYlqGzCX+nTPUb4CMzUAn3VPHTV5p5lBkAN4cAApLGgUz4mZE2sXlBfv4/LMmeP7qzxHV/ZcfWA== +detective-es6@^3.0.0, detective-es6@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/detective-es6/-/detective-es6-3.0.1.tgz#53a15fbb2f298c4a106d9fe7427da8a57162dde6" + integrity sha512-evPeYIEdK1jK3Oji5p0hX4sPV/1vK+o4ihcWZkMQE6voypSW/cIBiynOLxQk5KOOQbdP8oOAsYqouMTYO5l1sw== dependencies: node-source-walk "^5.0.0" @@ -2758,13 +2810,13 @@ detective-postcss@^4.0.0: postcss "^8.1.7" postcss-values-parser "^2.0.1" -detective-postcss@^6.0.1, detective-postcss@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/detective-postcss/-/detective-postcss-6.1.0.tgz#01ca6f83dbc3158540fb0e6a6c631f3998946e54" - integrity sha512-ZFZnEmUrL2XHAC0j/4D1fdwZbo/anAcK84soJh7qc7xfx2Kc8gFO5Bk5I9jU7NLC/OAF1Yho1GLxEDnmQnRH2A== +detective-postcss@^6.1.0, detective-postcss@^6.1.1: + version "6.1.3" + resolved "https://registry.yarnpkg.com/detective-postcss/-/detective-postcss-6.1.3.tgz#51a2d4419327ad85d0af071c7054c79fafca7e73" + integrity sha512-7BRVvE5pPEvk2ukUWNQ+H2XOq43xENWbH0LcdCE14mwgTBEAMoAx+Fc1rdp76SmyZ4Sp48HlV7VedUnP6GA1Tw== dependencies: is-url "^1.2.4" - postcss "^8.4.12" + postcss "^8.4.23" postcss-values-parser "^6.0.2" detective-sass@^3.0.1: @@ -2775,13 +2827,13 @@ detective-sass@^3.0.1: gonzales-pe "^4.3.0" node-source-walk "^4.0.0" -detective-sass@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/detective-sass/-/detective-sass-4.0.1.tgz#2a9e303a0bd472d00aaa79512334845e3acbaffc" - integrity sha512-80zfpxux1krOrkxCHbtwvIs2gNHUBScnSqlGl0FvUuHVz8HD6vD2ov66OroMctyvzhM67fxhuEeVjIk18s6yTQ== +detective-sass@^4.0.1, detective-sass@^4.1.1: + version "4.1.3" + resolved "https://registry.yarnpkg.com/detective-sass/-/detective-sass-4.1.3.tgz#6cdcc27ae8a90d15704e0ba83683048f77f10b75" + integrity sha512-xGRbwGaGte57gvEqM8B9GDiURY3El/H49vA6g9wFkxq9zalmTlTAuqWu+BsH0iwonGPruLt55tZZDEZqPc6lag== dependencies: gonzales-pe "^4.3.0" - node-source-walk "^5.0.0" + node-source-walk "^5.0.1" detective-scss@^2.0.1: version "2.0.2" @@ -2791,24 +2843,29 @@ detective-scss@^2.0.1: gonzales-pe "^4.3.0" node-source-walk "^4.0.0" -detective-scss@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/detective-scss/-/detective-scss-3.0.0.tgz#c3c7bc4799f51515a4f0ed1e8ca491151364230f" - integrity sha512-37MB/mhJyS45ngqfzd6eTbuLMoDgdZnH03ZOMW2m9WqJ/Rlbuc8kZAr0Ypovaf1DJiTRzy5mmxzOTja85jbzlA== +detective-scss@^3.0.0, detective-scss@^3.0.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/detective-scss/-/detective-scss-3.1.1.tgz#b49f05cadfb0837b04e23baba292581b7c7f65e1" + integrity sha512-FWkfru1jZBhUeuBsOeGKXKAVDrzYFSQFK2o2tuG/nCCFQ0U/EcXC157MNAcR5mmj+mCeneZzlkBOFJTesDjrww== dependencies: gonzales-pe "^4.3.0" - node-source-walk "^5.0.0" + node-source-walk "^5.0.1" detective-stylus@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/detective-stylus/-/detective-stylus-1.0.3.tgz#20a702936c9fd7d4203fd7a903314b5dd43ac713" integrity sha512-4/bfIU5kqjwugymoxLXXLltzQNeQfxGoLm2eIaqtnkWxqbhap9puDVpJPVDx96hnptdERzS5Cy6p9N8/08A69Q== -detective-stylus@^2.0.0, detective-stylus@^2.0.1: +detective-stylus@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/detective-stylus/-/detective-stylus-2.0.1.tgz#d528dfa7ef3c4eb2fbc9a7249d54906ec4e05d09" integrity sha512-/Tvs1pWLg8eYwwV6kZQY5IslGaYqc/GACxjcaGudiNtN5nKCH6o2WnJK3j0gA3huCnoQcbv8X7oz/c1lnvE3zQ== +detective-stylus@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/detective-stylus/-/detective-stylus-3.0.0.tgz#c869795a7d6df7043ab6aee8b1a6f3dd66764232" + integrity sha512-1xYTzbrduExqMYmte7Qk99IRA3Aa6oV7PYzd+3yDcQXkmENvyGF/arripri6lxRDdNYEb4fZFuHtNRAXbz3iAA== + detective-typescript@^7.0.0: version "7.0.2" resolved "https://registry.yarnpkg.com/detective-typescript/-/detective-typescript-7.0.2.tgz#c6e00b4c28764741ef719662250e6b014a5f3c8e" @@ -2819,15 +2876,15 @@ detective-typescript@^7.0.0: node-source-walk "^4.2.0" typescript "^3.9.10" -detective-typescript@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/detective-typescript/-/detective-typescript-9.0.0.tgz#57d674cec49ec775460ab975b5bcbb5c2d32ff8e" - integrity sha512-lR78AugfUSBojwlSRZBeEqQ1l8LI7rbxOl1qTUnGLcjZQDjZmrZCb7R46rK8U8B5WzFvJrxa7fEBA8FoD/n5fA== +detective-typescript@^9.0.0, detective-typescript@^9.1.1: + version "9.1.1" + resolved "https://registry.yarnpkg.com/detective-typescript/-/detective-typescript-9.1.1.tgz#b99c0122cbb35b39de2c5f58447f1e93ac28c6d5" + integrity sha512-Uc1yVutTF0RRm1YJ3g//i1Cn2vx1kwHj15cnzQP6ff5koNzQ0idc1zAC73ryaWEulA0ElRXFTq6wOqe8vUQ3MA== dependencies: - "@typescript-eslint/typescript-estree" "^5.13.0" - ast-module-types "^3.0.0" - node-source-walk "^5.0.0" - typescript "^4.5.5" + "@typescript-eslint/typescript-estree" "^5.55.0" + ast-module-types "^4.0.0" + node-source-walk "^5.0.1" + typescript "^4.9.5" diff@^4.0.1: version "4.0.2" @@ -2914,9 +2971,9 @@ engine.io-parser@~5.0.3: integrity sha512-tjuoZDMAdEhVnSFleYPCtdL2GXwVTGtNjoeJd9IhIG3C1xs9uwxqRNEu5WpnDZCaozwVlK/nuQhpodhXSIMaxw== enhanced-resolve@^5.8.3: - version "5.12.0" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz#300e1c90228f5b570c4d35babf263f6da7155634" - integrity sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ== + version "5.13.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.13.0.tgz#26d1ecc448c02de997133217b5c1053f34a0a275" + integrity sha512-eyV8f0y1+bzyfh8xAwW/WTSZpLbjhqc4ne9eGSH4Zo2ejdyiNG9pU6mf9DG8a7+Auk6MFTlNOT4Y2y/9k8GKVg== dependencies: graceful-fs "^4.2.4" tapable "^2.2.0" @@ -2929,17 +2986,17 @@ error-ex@^1.3.1: is-arrayish "^0.2.1" es-abstract@^1.19.0, es-abstract@^1.20.4: - version "1.21.1" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.21.1.tgz#e6105a099967c08377830a0c9cb589d570dd86c6" - integrity sha512-QudMsPOz86xYz/1dG1OuGBKOELjCh99IIWHLzy5znUB6j8xG2yMA7bfTV86VSqKF+Y/H08vQPR+9jyXpuC6hfg== + version "1.21.2" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.21.2.tgz#a56b9695322c8a185dc25975aa3b8ec31d0e7eff" + integrity sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg== dependencies: + array-buffer-byte-length "^1.0.0" available-typed-arrays "^1.0.5" call-bind "^1.0.2" es-set-tostringtag "^2.0.1" es-to-primitive "^1.2.1" - function-bind "^1.1.1" function.prototype.name "^1.1.5" - get-intrinsic "^1.1.3" + get-intrinsic "^1.2.0" get-symbol-description "^1.0.0" globalthis "^1.0.3" gopd "^1.0.1" @@ -2947,8 +3004,8 @@ es-abstract@^1.19.0, es-abstract@^1.20.4: has-property-descriptors "^1.0.0" has-proto "^1.0.1" has-symbols "^1.0.3" - internal-slot "^1.0.4" - is-array-buffer "^3.0.1" + internal-slot "^1.0.5" + is-array-buffer "^3.0.2" is-callable "^1.2.7" is-negative-zero "^2.0.2" is-regex "^1.1.4" @@ -2956,11 +3013,12 @@ es-abstract@^1.19.0, es-abstract@^1.20.4: is-string "^1.0.7" is-typed-array "^1.1.10" is-weakref "^1.0.2" - object-inspect "^1.12.2" + object-inspect "^1.12.3" object-keys "^1.1.1" object.assign "^4.1.4" regexp.prototype.flags "^1.4.3" safe-regex-test "^1.0.0" + string.prototype.trim "^1.2.7" string.prototype.trimend "^1.0.6" string.prototype.trimstart "^1.0.6" typed-array-length "^1.0.4" @@ -2992,33 +3050,33 @@ es-to-primitive@^1.2.1: is-date-object "^1.0.1" is-symbol "^1.0.2" -esbuild@^0.16.14: - version "0.16.17" - resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.16.17.tgz#fc2c3914c57ee750635fee71b89f615f25065259" - integrity sha512-G8LEkV0XzDMNwXKgM0Jwu3nY3lSTwSGY6XbxM9cr9+s0T/qSV1q1JVPBGzm3dcjhCic9+emZDmMffkwgPeOeLg== +esbuild@^0.17.5: + version "0.17.18" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.17.18.tgz#f4f8eb6d77384d68cd71c53eb6601c7efe05e746" + integrity sha512-z1lix43jBs6UKjcZVKOw2xx69ffE2aG0PygLL5qJ9OS/gy0Ewd1gW/PUQIOIQGXBHWNywSc0floSKoMFF8aK2w== optionalDependencies: - "@esbuild/android-arm" "0.16.17" - "@esbuild/android-arm64" "0.16.17" - "@esbuild/android-x64" "0.16.17" - "@esbuild/darwin-arm64" "0.16.17" - "@esbuild/darwin-x64" "0.16.17" - "@esbuild/freebsd-arm64" "0.16.17" - "@esbuild/freebsd-x64" "0.16.17" - "@esbuild/linux-arm" "0.16.17" - "@esbuild/linux-arm64" "0.16.17" - "@esbuild/linux-ia32" "0.16.17" - "@esbuild/linux-loong64" "0.16.17" - "@esbuild/linux-mips64el" "0.16.17" - "@esbuild/linux-ppc64" "0.16.17" - "@esbuild/linux-riscv64" "0.16.17" - "@esbuild/linux-s390x" "0.16.17" - "@esbuild/linux-x64" "0.16.17" - "@esbuild/netbsd-x64" "0.16.17" - "@esbuild/openbsd-x64" "0.16.17" - "@esbuild/sunos-x64" "0.16.17" - "@esbuild/win32-arm64" "0.16.17" - "@esbuild/win32-ia32" "0.16.17" - "@esbuild/win32-x64" "0.16.17" + "@esbuild/android-arm" "0.17.18" + "@esbuild/android-arm64" "0.17.18" + "@esbuild/android-x64" "0.17.18" + "@esbuild/darwin-arm64" "0.17.18" + "@esbuild/darwin-x64" "0.17.18" + "@esbuild/freebsd-arm64" "0.17.18" + "@esbuild/freebsd-x64" "0.17.18" + "@esbuild/linux-arm" "0.17.18" + "@esbuild/linux-arm64" "0.17.18" + "@esbuild/linux-ia32" "0.17.18" + "@esbuild/linux-loong64" "0.17.18" + "@esbuild/linux-mips64el" "0.17.18" + "@esbuild/linux-ppc64" "0.17.18" + "@esbuild/linux-riscv64" "0.17.18" + "@esbuild/linux-s390x" "0.17.18" + "@esbuild/linux-x64" "0.17.18" + "@esbuild/netbsd-x64" "0.17.18" + "@esbuild/openbsd-x64" "0.17.18" + "@esbuild/sunos-x64" "0.17.18" + "@esbuild/win32-arm64" "0.17.18" + "@esbuild/win32-ia32" "0.17.18" + "@esbuild/win32-x64" "0.17.18" escalade@^3.1.1: version "3.1.1" @@ -3052,10 +3110,10 @@ escodegen@^2.0.0: optionalDependencies: source-map "~0.6.1" -eslint-config-prettier@^8.6.0: - version "8.6.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.6.0.tgz#dec1d29ab728f4fa63061774e1672ac4e363d207" - integrity sha512-bAF0eLpLVqP5oEVUFKpMA+NnRFICwn9X8B5jrR9FcqnYBuPbqWEjTEspPWMj5ye6czoSLDweCzSo3Ko7gGrZaA== +eslint-config-prettier@^8.8.0: + version "8.8.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz#bfda738d412adc917fd7b038857110efe98c9348" + integrity sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA== eslint-plugin-prettier@^4.2.1: version "4.2.1" @@ -3098,38 +3156,33 @@ eslint-scope@^5.1.1: esrecurse "^4.3.0" estraverse "^4.1.1" -eslint-scope@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.1.1.tgz#fff34894c2f65e5226d3041ac480b4513a163642" - integrity sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw== +eslint-scope@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.0.tgz#f21ebdafda02352f103634b96dd47d9f81ca117b" + integrity sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw== dependencies: esrecurse "^4.3.0" estraverse "^5.2.0" -eslint-utils@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672" - integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== - dependencies: - eslint-visitor-keys "^2.0.0" - eslint-visitor-keys@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== -eslint-visitor-keys@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" - integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== +eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.0.tgz#c7f0f956124ce677047ddbc192a68f999454dedc" + integrity sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ== -eslint@^8.34.0: - version "8.35.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.35.0.tgz#fffad7c7e326bae606f0e8f436a6158566d42323" - integrity sha512-BxAf1fVL7w+JLRQhWl2pzGeSiGqbWumV4WNvc9Rhp6tiCtm4oHnyPBSEtMGZwrQgudFQ+otqzWoPB7x+hxoWsw== +eslint@^8.39.0: + version "8.39.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.39.0.tgz#7fd20a295ef92d43809e914b70c39fd5a23cf3f1" + integrity sha512-mwiok6cy7KTW7rBpo05k6+p4YVZByLNjAZ/ACB9DRCu4YDRwjXI01tWHp6KAUWelsBetTxKK/2sHB0vdS8Z2Og== dependencies: - "@eslint/eslintrc" "^2.0.0" - "@eslint/js" "8.35.0" + "@eslint-community/eslint-utils" "^4.2.0" + "@eslint-community/regexpp" "^4.4.0" + "@eslint/eslintrc" "^2.0.2" + "@eslint/js" "8.39.0" "@humanwhocodes/config-array" "^0.11.8" "@humanwhocodes/module-importer" "^1.0.1" "@nodelib/fs.walk" "^1.2.8" @@ -3139,10 +3192,9 @@ eslint@^8.34.0: debug "^4.3.2" doctrine "^3.0.0" escape-string-regexp "^4.0.0" - eslint-scope "^7.1.1" - eslint-utils "^3.0.0" - eslint-visitor-keys "^3.3.0" - espree "^9.4.0" + eslint-scope "^7.2.0" + eslint-visitor-keys "^3.4.0" + espree "^9.5.1" esquery "^1.4.2" esutils "^2.0.2" fast-deep-equal "^3.1.3" @@ -3164,19 +3216,18 @@ eslint@^8.34.0: minimatch "^3.1.2" natural-compare "^1.4.0" optionator "^0.9.1" - regexpp "^3.2.0" strip-ansi "^6.0.1" strip-json-comments "^3.1.0" text-table "^0.2.0" -espree@^9.4.0: - version "9.4.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-9.4.1.tgz#51d6092615567a2c2cff7833445e37c28c0065bd" - integrity sha512-XwctdmTO6SIvCzd9810yyNzIrOrqNYV9Koizx4C/mRhf9uq0o4yHoCEU/670pOxOL/MSraektvSAji79kX90Vg== +espree@^9.5.1: + version "9.5.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-9.5.1.tgz#4f26a4d5f18905bf4f2e0bd99002aab807e96dd4" + integrity sha512-5yxtHSZXRSW5pvv3hAlXM5+/Oswi1AUFqBmbibKb5s6bp3rGIDkyXU6xCoyuuLhijr4SFwPrXRoZjz0AZDN9tg== dependencies: acorn "^8.8.0" acorn-jsx "^5.3.2" - eslint-visitor-keys "^3.3.0" + eslint-visitor-keys "^3.4.0" esprima@^4.0.0, esprima@^4.0.1: version "4.0.1" @@ -3217,14 +3268,14 @@ esutils@^2.0.2: resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== -execa@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-6.1.0.tgz#cea16dee211ff011246556388effa0818394fb20" - integrity sha512-QVWlX2e50heYJcCPG0iWtf8r0xjEYfz/OYLGDYH+IyjWezzPNxz63qNFOu0l4YftGWuizFVZHHs8PrLU5p2IDA== +execa@^7.0.0: + version "7.1.1" + resolved "https://registry.yarnpkg.com/execa/-/execa-7.1.1.tgz#3eb3c83d239488e7b409d48e8813b76bb55c9c43" + integrity sha512-wH0eMf/UXckdUYnO21+HDztteVv05rq2GXksxT4fCGeHkBhw1DROXh40wcjMcRqDOWE7iPJ4n3M7e2+YFP+76Q== dependencies: cross-spawn "^7.0.3" get-stream "^6.0.1" - human-signals "^3.0.1" + human-signals "^4.3.0" is-stream "^3.0.0" merge-stream "^2.0.0" npm-run-path "^5.1.0" @@ -3285,9 +3336,9 @@ file-selector@^0.6.0: tslib "^2.4.0" filing-cabinet@^3.0.1: - version "3.3.0" - resolved "https://registry.yarnpkg.com/filing-cabinet/-/filing-cabinet-3.3.0.tgz#365294d2d3d6ab01b4273e62fb6d23388a70cc0f" - integrity sha512-Tnbpbme1ONaHXV5DGcw0OFpcfP3p2itRf5VXO1bguBXdIewDbK6ZFBK//DGKM0BuCzaQLQNY4f5gljzxY1VCUw== + version "3.3.1" + resolved "https://registry.yarnpkg.com/filing-cabinet/-/filing-cabinet-3.3.1.tgz#45d87bb273a0e0a7dd6ac6bac9111059186e2e9c" + integrity sha512-renEK4Hh6DUl9Vl22Y3cxBq1yh8oNvbAdXnhih0wVpmea+uyKjC9K4QeRjUaybIiIewdzfum+Fg15ZqJ/GyCaA== dependencies: app-module-path "^2.2.0" commander "^2.20.3" @@ -3389,10 +3440,10 @@ formik@^2.2.9: tiny-warning "^1.0.2" tslib "^1.10.0" -framer-motion@^9.0.4: - version "9.1.7" - resolved "https://registry.yarnpkg.com/framer-motion/-/framer-motion-9.1.7.tgz#1dc7dbd5bca086c90d09847c3fcaec3ecb7906af" - integrity sha512-nKxBkIO4IPkMEqcBbbATxsVjwPYShKl051yhBv9628iAH6JLeHD0siBHxkL62oQzMC1+GNX73XtPjgP753ufuw== +framer-motion@^10.12.4: + version "10.12.4" + resolved "https://registry.yarnpkg.com/framer-motion/-/framer-motion-10.12.4.tgz#905fdfa5b63dae53a63d2549b29aef6193eb78c7" + integrity sha512-9gLtv8T6dui0tujHROR+VM3kdJyKiFCFiD94IQE+0OuX6LaIyXtdVpviokVdrHSb1giWhmmX4yzoucALMx6mtw== dependencies: tslib "^2.4.0" optionalDependencies: @@ -3405,10 +3456,10 @@ framesync@6.1.2: dependencies: tslib "2.4.0" -fs-extra@^10.1.0: - version "10.1.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" - integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ== +fs-extra@^11.1.1: + version "11.1.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.1.1.tgz#da69f7c39f3b002378b0954bb6ae7efdc0876e2d" + integrity sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ== dependencies: graceful-fs "^4.2.0" jsonfile "^6.0.1" @@ -3449,7 +3500,7 @@ function.prototype.name@^1.1.5: es-abstract "^1.19.0" functions-have-names "^1.2.2" -functions-have-names@^1.2.2: +functions-have-names@^1.2.2, functions-have-names@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== @@ -3467,13 +3518,13 @@ get-amd-module-type@^3.0.0: ast-module-types "^3.0.0" node-source-walk "^4.2.2" -get-amd-module-type@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/get-amd-module-type/-/get-amd-module-type-4.0.0.tgz#3d4e5b44eec81f8337157d7c52c4fa9389aff78b" - integrity sha512-GbBawUCuA2tY8ztiMiVo3e3P95gc2TVrfYFfpUHdHQA8WyxMCckK29bQsVKhYX8SUf+w6JLhL2LG8tSC0ANt9Q== +get-amd-module-type@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/get-amd-module-type/-/get-amd-module-type-4.1.0.tgz#af1396d02cd935cb6fafdc4a5282395db3422db6" + integrity sha512-0e/eK6vTGCnSfQ6eYs3wtH05KotJYIP7ZIZEueP/KlA+0dIAEs8bYFvOd/U56w1vfjhJqBagUxVMyy9Tr/cViQ== dependencies: - ast-module-types "^3.0.0" - node-source-walk "^5.0.0" + ast-module-types "^4.0.0" + node-source-walk "^5.0.1" get-caller-file@^2.0.5: version "2.0.5" @@ -3622,9 +3673,9 @@ got@^9.6.0: url-parse-lax "^3.0.0" graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4: - version "4.2.10" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" - integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== grapheme-splitter@^1.0.4: version "1.0.4" @@ -3713,10 +3764,10 @@ http-cache-semantics@^4.0.0: resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== -human-signals@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-3.0.1.tgz#c740920859dafa50e5a3222da9d3bf4bb0e5eef5" - integrity sha512-rQLskxnM/5OCldHo+wNXbpVgDn5A17CUoKX+7Sokwaknlq7CdSnphy0W39GU8dw59XiCXmFXDg4fRuckQRKewQ== +human-signals@^4.3.0: + version "4.3.1" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-4.3.1.tgz#ab7f811e851fca97ffbd2c1fe9a958964de321b2" + integrity sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ== husky@^8.0.3: version "8.0.3" @@ -3730,17 +3781,17 @@ i18next-browser-languagedetector@^7.0.1: dependencies: "@babel/runtime" "^7.19.4" -i18next-http-backend@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/i18next-http-backend/-/i18next-http-backend-2.1.1.tgz#72a21d61c2e96eea9ad45ba1b9dd0090e119709a" - integrity sha512-jByfUCDVgQ8+/Wens7queQhYYvMcGTW/lR4IJJNEDDXnmqjLrwi8ubXKpmp76/JIWEZHffNdWqnxFJcTVGeaOw== +i18next-http-backend@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/i18next-http-backend/-/i18next-http-backend-2.2.0.tgz#f77c06dc8e766c7588bb38da2f5fa0614ba67b3f" + integrity sha512-Z4sM7R6tzdLknSPER9GisEBxKPg5FkI07UrQniuroZmS15PHQrcCPLyuGKj8SS68tf+O2aEDYSUnmy1TZqZSbw== dependencies: cross-fetch "3.1.5" -i18next@^22.4.10: - version "22.4.10" - resolved "https://registry.yarnpkg.com/i18next/-/i18next-22.4.10.tgz#cfbfc412c6bc83e3c16564f47e6a5c145255960e" - integrity sha512-3EqgGK6fAJRjnGgfkNSStl4mYLCjUoJID338yVyLMj5APT67HUtWoqSayZewiiC5elzMUB1VEUwcmSCoeQcNEA== +i18next@^22.4.15: + version "22.4.15" + resolved "https://registry.yarnpkg.com/i18next/-/i18next-22.4.15.tgz#951882b751872994f8502b5a6ef6f796e6a7d7f8" + integrity sha512-yYudtbFrrmWKLEhl6jvKUYyYunj4bTBCe2qIUYAxbXoPusY7YmdwPvOE6fx6UIfWvmlbCWDItr7wIs8KEBZ5Zg== dependencies: "@babel/runtime" "^7.20.6" @@ -3754,10 +3805,10 @@ ignore@^5.2.0: resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324" integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== -immer@^9.0.16: - version "9.0.19" - resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.19.tgz#67fb97310555690b5f9cd8380d38fc0aabb6b38b" - integrity sha512-eY+Y0qcsB4TZKwgQzLaE/lqYMlKhv5J9dyd2RhhtGhNo2njPXDqU9XPfcNfa3MIDsdtZt5KlkIsirlo4dHsWdQ== +immer@^9.0.21: + version "9.0.21" + resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.21.tgz#1e025ea31a40f24fb064f1fef23e931496330176" + integrity sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA== import-fresh@^3.0.0, import-fresh@^3.2.1: version "3.3.0" @@ -3810,7 +3861,7 @@ ini@~1.3.0: resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== -internal-slot@^1.0.3, internal-slot@^1.0.4: +internal-slot@^1.0.3, internal-slot@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.5.tgz#f2a2ee21f668f8627a4667f309dc0f4fb6674986" integrity sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ== @@ -3826,7 +3877,7 @@ invariant@^2.2.4: dependencies: loose-envify "^1.0.0" -is-array-buffer@^3.0.1: +is-array-buffer@^3.0.1, is-array-buffer@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.2.tgz#f2653ced8412081638ecb0ebbd0c41c6e0aecbbe" integrity sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w== @@ -3874,10 +3925,10 @@ is-ci@^2.0.0: dependencies: ci-info "^2.0.0" -is-core-module@^2.9.0: - version "2.11.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144" - integrity sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw== +is-core-module@^2.11.0, is-core-module@^2.9.0: + version "2.12.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.12.0.tgz#36ad62f6f73c8253fd6472517a12483cf03e7ec4" + integrity sha512-RECHCBCd/viahWmwj6enj19sKbHfJrddi/6cBDsNTKbNq0f7VeaUkBo60BqzvPqo/W54ChS62Z5qyun7cfOMqQ== dependencies: has "^1.0.3" @@ -4091,16 +4142,16 @@ isexe@^2.0.0: integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== its-fine@^1.0.6: - version "1.0.9" - resolved "https://registry.yarnpkg.com/its-fine/-/its-fine-1.0.9.tgz#f4ca0ad5bdbf896764d35f7cf24c16287b6c6d31" - integrity sha512-Ph+vcp1R100JOM4raXmDx/wCTi4kMkMXiFE108qGzsLdghXFPqad82UJJtqT1jwdyWYkTU6eDpDnol/ZIzW+1g== + version "1.1.1" + resolved "https://registry.yarnpkg.com/its-fine/-/its-fine-1.1.1.tgz#e74b93fddd487441f978a50f64f0f5af4d2fc38e" + integrity sha512-v1Ia1xl20KbuSGlwoaGsW0oxsw8Be+TrXweidxD9oT/1lAh6O3K3/GIM95Tt6WCiv6W+h2M7RB1TwdoAjQyyKw== dependencies: "@types/react-reconciler" "^0.28.0" js-sdsl@^4.1.4: - version "4.3.0" - resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.3.0.tgz#aeefe32a451f7af88425b11fdb5f58c90ae1d711" - integrity sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ== + version "4.4.0" + resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.4.0.tgz#8b437dbe642daa95760400b602378ed8ffea8430" + integrity sha512-FfVSdx6pJ41Oa+CF7RDaFmTnCaFhua+SNYQX74riGOpl96x+2jQCqEfQ2bnXu/5DPCqlRuiqyvTJM0Qjz26IVg== "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" @@ -4184,10 +4235,10 @@ klaw-sync@^6.0.0: dependencies: graceful-fs "^4.1.11" -konva@^8.4.2: - version "8.4.2" - resolved "https://registry.yarnpkg.com/konva/-/konva-8.4.2.tgz#6de2b9d54f2b56b8c7c76eba66955f7255dd9afb" - integrity sha512-4VQcrgj/PI8ydJjtLcTuinHBE8o0WGX0YoRwbiN5mpYQiC52aOzJ0XbpKNDJdRvORQphK5LP+jeM0hQJEYIuUA== +konva@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/konva/-/konva-9.0.1.tgz#92b4171beaa94273b108bd87b08c4d3e51a0da22" + integrity sha512-wzpkprJ8idE42TDF9Lu9RNjVVYNXrj0apvTK3pujdHQhX1iNV+MUquSxYN8HqjYSG95QQ51jhFzRLWhnhf44Mw== latest-version@^5.1.0: version "5.1.0" @@ -4212,39 +4263,39 @@ levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" -lilconfig@2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.0.6.tgz#32a384558bd58af3d4c6e077dd1ad1d397bc69d4" - integrity sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg== +lilconfig@2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.1.0.tgz#78e23ac89ebb7e1bfbf25b18043de756548e7f52" + integrity sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ== lines-and-columns@^1.1.6: version "1.2.4" resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== -lint-staged@^13.1.2: - version "13.1.2" - resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-13.1.2.tgz#443636a0cfd834d5518d57d228130dc04c83d6fb" - integrity sha512-K9b4FPbWkpnupvK3WXZLbgu9pchUJ6N7TtVZjbaPsoizkqFUDkUReUL25xdrCljJs7uLUF3tZ7nVPeo/6lp+6w== +lint-staged@^13.2.2: + version "13.2.2" + resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-13.2.2.tgz#5e711d3139c234f73402177be2f8dd312e6508ca" + integrity sha512-71gSwXKy649VrSU09s10uAT0rWCcY3aewhMaHyl2N84oBk4Xs9HgxvUp3AYu+bNsK4NrOYYxvSgg7FyGJ+jGcA== dependencies: + chalk "5.2.0" cli-truncate "^3.1.0" - colorette "^2.0.19" - commander "^9.4.1" + commander "^10.0.0" debug "^4.3.4" - execa "^6.1.0" - lilconfig "2.0.6" - listr2 "^5.0.5" + execa "^7.0.0" + lilconfig "2.1.0" + listr2 "^5.0.7" micromatch "^4.0.5" normalize-path "^3.0.0" - object-inspect "^1.12.2" + object-inspect "^1.12.3" pidtree "^0.6.0" string-argv "^0.3.1" - yaml "^2.1.3" + yaml "^2.2.2" -listr2@^5.0.5: - version "5.0.7" - resolved "https://registry.yarnpkg.com/listr2/-/listr2-5.0.7.tgz#de69ccc4caf6bea7da03c74f7a2ffecf3904bd53" - integrity sha512-MD+qXHPmtivrHIDRwPYdfNkrzqDiuaKU/rfBcec3WMyMF3xylQj3jMq344OtvQxz7zaCFViRAeqlr2AFhPvXHw== +listr2@^5.0.7: + version "5.0.8" + resolved "https://registry.yarnpkg.com/listr2/-/listr2-5.0.8.tgz#a9379ffeb4bd83a68931a65fb223a11510d6ba23" + integrity sha512-mC73LitKHj9w6v30nLNGPetZIlfpUniNSsxxrbaPcWOjDb92SHPzJPi/t+v1YC/lxKz/AJ9egOjww0qUuFxBpA== dependencies: cli-truncate "^2.1.0" colorette "^2.0.19" @@ -4442,13 +4493,13 @@ module-definition@^3.3.1: ast-module-types "^3.0.0" node-source-walk "^4.0.0" -module-definition@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/module-definition/-/module-definition-4.0.0.tgz#5b39cca9be28c5b0fec768eb2d9fd8de08a2550b" - integrity sha512-wntiAHV4lDn24BQn2kX6LKq0y85phHLHiv3aOPDF+lIs06kVjEMTe/ZTdrbVLnQV5FQsjik21taknvMhKY1Cug== +module-definition@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/module-definition/-/module-definition-4.1.0.tgz#148ff9348e3401867229dcbe5947f4f6d5ccd3a2" + integrity sha512-rHXi/DpMcD2qcKbPCTklDbX9lBKJrUSl971TW5l6nMpqKCIlzJqmQ8cfEF5M923h2OOLHPDVlh5pJxNyV+AJlw== dependencies: - ast-module-types "^3.0.0" - node-source-walk "^5.0.0" + ast-module-types "^4.0.0" + node-source-walk "^5.0.1" module-lookup-amd@^7.0.1: version "7.0.1" @@ -4466,10 +4517,10 @@ ms@2.1.2: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -nanoid@^3.3.4: - version "3.3.4" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab" - integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw== +nanoid@^3.3.6: + version "3.3.6" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.6.tgz#443380c856d6e9f9824267d960b4236ad583ea4c" + integrity sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA== natural-compare-lite@^1.4.0: version "1.4.0" @@ -4486,11 +4537,6 @@ neo-async@^2.6.0: resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== -nice-try@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" - integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== - node-fetch@2.6.7: version "2.6.7" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" @@ -4505,12 +4551,12 @@ node-source-walk@^4.0.0, node-source-walk@^4.2.0, node-source-walk@^4.2.2: dependencies: "@babel/parser" "^7.0.0" -node-source-walk@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/node-source-walk/-/node-source-walk-5.0.0.tgz#7cf93a0d12408081531fc440a00d7019eb3d5665" - integrity sha512-58APXoMXpmmU+oVBJFajhTCoD8d/OGtngnVAWzIo2A8yn0IXwBzvIVIsTzoie/SrA37u+1hnpNz2HMWx/VIqlw== +node-source-walk@^5.0.0, node-source-walk@^5.0.1: + version "5.0.2" + resolved "https://registry.yarnpkg.com/node-source-walk/-/node-source-walk-5.0.2.tgz#0eb439ce378946ce531e07a6a0073d06288396dd" + integrity sha512-Y4jr/8SRS5hzEdZ7SGuvZGwfORvNsSsNRwDXx5WisiqzsVfeftDvRgfeqWNgZvWSJbgubTRVRYBzK6UO+ErqjA== dependencies: - "@babel/parser" "^7.0.0" + "@babel/parser" "^7.21.4" normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" @@ -4534,7 +4580,7 @@ object-assign@^4.1.1: resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== -object-inspect@^1.12.2, object-inspect@^1.9.0: +object-inspect@^1.12.3, object-inspect@^1.9.0: version "1.12.3" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== @@ -4632,14 +4678,14 @@ openapi-types@^12.1.0: resolved "https://registry.yarnpkg.com/openapi-types/-/openapi-types-12.1.0.tgz#bd01acc937b73c9f6db2ac2031bf0231e21ebff0" integrity sha512-XpeCy01X6L5EpP+6Hc3jWN7rMZJ+/k1lwki/kTmWzbVhdPie3jd5O2ZtedEx8Yp58icJ0osVldLMrTB/zslQXA== -openapi-typescript-codegen@^0.23.0: - version "0.23.0" - resolved "https://registry.yarnpkg.com/openapi-typescript-codegen/-/openapi-typescript-codegen-0.23.0.tgz#702a651eefc536b27e87e4ad54a80a31d36487f0" - integrity sha512-gOJXy5g3H3HlLpVNN+USrNK2i2KYBmDczk9Xk34u6JorwrGiDJZUj+al4S+i9TXdfUQ/ZaLxE59Xf3wqkxGfqA== +openapi-typescript-codegen@^0.24.0: + version "0.24.0" + resolved "https://registry.yarnpkg.com/openapi-typescript-codegen/-/openapi-typescript-codegen-0.24.0.tgz#b3e6ade5bae75cd47868e5e3e4dc3bcf899cadab" + integrity sha512-rSt8t1XbMWhv6Db7GUI24NNli7FU5kzHLxcE8BpzgGWRdWyWt9IB2YoLyPahxNrVA7yOaVgnXPkrcTDRMQtJYg== dependencies: camelcase "^6.3.0" - commander "^9.3.0" - fs-extra "^10.1.0" + commander "^10.0.0" + fs-extra "^11.1.1" handlebars "^4.7.7" json-schema-ref-parser "^9.0.9" @@ -4745,17 +4791,17 @@ parse-ms@^2.1.0: resolved "https://registry.yarnpkg.com/parse-ms/-/parse-ms-2.1.0.tgz#348565a753d4391fa524029956b172cb7753097d" integrity sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA== -patch-package@^6.5.1: - version "6.5.1" - resolved "https://registry.yarnpkg.com/patch-package/-/patch-package-6.5.1.tgz#3e5d00c16997e6160291fee06a521c42ac99b621" - integrity sha512-I/4Zsalfhc6bphmJTlrLoOcAF87jcxko4q0qsv4bGcurbr8IskEOtdnt9iCmsQVGL1B+iUhSQqweyTLJfCF9rA== +patch-package@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/patch-package/-/patch-package-7.0.0.tgz#5c646b6b4b4bf37e5184a6950777b21dea6bb66e" + integrity sha512-eYunHbnnB2ghjTNc5iL1Uo7TsGMuXk0vibX3RFcE/CdVdXzmdbMsG/4K4IgoSuIkLTI5oHrMQk4+NkFqSed0BQ== dependencies: "@yarnpkg/lockfile" "^1.1.0" chalk "^4.1.2" - cross-spawn "^6.0.5" + ci-info "^3.7.0" + cross-spawn "^7.0.3" find-yarn-workspace-root "^2.0.0" fs-extra "^9.0.0" - is-ci "^2.0.0" klaw-sync "^6.0.0" minimist "^1.2.6" open "^7.4.2" @@ -4763,7 +4809,7 @@ patch-package@^6.5.1: semver "^5.6.0" slash "^2.0.0" tmp "^0.0.33" - yaml "^1.10.2" + yaml "^2.2.2" path-exists@^4.0.0: version "4.0.0" @@ -4775,11 +4821,6 @@ path-is-absolute@^1.0.0: resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== -path-key@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" - integrity sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw== - path-key@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" @@ -4838,12 +4879,12 @@ postcss-values-parser@^6.0.2: is-url-superb "^4.0.0" quote-unquote "^1.0.0" -postcss@^8.1.7, postcss@^8.4.12, postcss@^8.4.21: - version "8.4.21" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.21.tgz#c639b719a57efc3187b13a1d765675485f4134f4" - integrity sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg== +postcss@^8.1.7, postcss@^8.4.23: + version "8.4.23" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.23.tgz#df0aee9ac7c5e53e1075c24a3613496f9e6552ab" + integrity sha512-bQ3qMcpF6A/YjR55xtoTr0jGOlnPOKAIMdOWiv0EIT6HVPEaJiJB4NLljSbiHoC2RX7DN5Uvjtpbg1NPdwv1oA== dependencies: - nanoid "^3.3.4" + nanoid "^3.3.6" picocolors "^1.0.0" source-map-js "^1.0.2" @@ -4872,22 +4913,22 @@ precinct@^8.1.0: node-source-walk "^4.2.0" precinct@^9.0.0: - version "9.0.1" - resolved "https://registry.yarnpkg.com/precinct/-/precinct-9.0.1.tgz#64e7ea0de4bea1b73572e50531dfe297c7b8a7c7" - integrity sha512-hVNS6JvfvlZ64B3ezKeGAcVhIuOvuAiSVzagHX/+KjVPkYWoCNkfyMgCl1bjDtAFQSlzi95NcS9ykUWrl1L1vA== + version "9.2.1" + resolved "https://registry.yarnpkg.com/precinct/-/precinct-9.2.1.tgz#db0a67abff7b0a9a3b2b1ac33d170e8a5fcac7b2" + integrity sha512-uzKHaTyiVejWW7VJtHInb9KBUq9yl9ojxXGujhjhDmPon2wgZPBKQIKR+6csGqSlUeGXAA4MEFnU6DesxZib+A== dependencies: - commander "^9.1.0" - detective-amd "^4.0.1" - detective-cjs "^4.0.0" - detective-es6 "^3.0.0" - detective-less "^1.0.2" - detective-postcss "^6.0.1" - detective-sass "^4.0.1" - detective-scss "^3.0.0" - detective-stylus "^2.0.0" - detective-typescript "^9.0.0" - module-definition "^4.0.0" - node-source-walk "^5.0.0" + "@dependents/detective-less" "^3.0.1" + commander "^9.5.0" + detective-amd "^4.1.0" + detective-cjs "^4.1.0" + detective-es6 "^3.0.1" + detective-postcss "^6.1.1" + detective-sass "^4.1.1" + detective-scss "^3.0.1" + detective-stylus "^3.0.0" + detective-typescript "^9.1.1" + module-definition "^4.1.0" + node-source-walk "^5.0.1" prelude-ls@^1.2.1: version "1.2.1" @@ -4911,10 +4952,10 @@ prettier-linter-helpers@^1.0.0: dependencies: fast-diff "^1.1.2" -prettier@^2.0.5, prettier@^2.7.1, prettier@^2.8.4: - version "2.8.4" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.4.tgz#34dd2595629bfbb79d344ac4a91ff948694463c3" - integrity sha512-vIS4Rlc2FNh0BySk3Wkd6xmwxB0FpOndW5fisM5H8hsZSxU2VWVB5CWIkIjWvrHjIhxk2g3bfMKM87zNTrZddw== +prettier@^2.0.5, prettier@^2.7.1, prettier@^2.8.8: + version "2.8.8" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" + integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== pretty-ms@^7.0.1: version "7.0.1" @@ -5011,10 +5052,10 @@ react-dropzone@^14.2.3: file-selector "^0.6.0" prop-types "^15.8.1" -react-fast-compare@3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.0.tgz#641a9da81b6a6320f270e89724fb45a0b39e43bb" - integrity sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA== +react-fast-compare@3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.1.tgz#53933d9e14f364281d6cba24bfed7a4afb808b5f" + integrity sha512-xTYf9zFim2pEif/Fw16dBiXpe0hoy5PxcD8+OwBnTtNLfIm3g6WxhKNurY+6OmdH1u6Ta/W/Vl6vjbYP1MFnDg== react-fast-compare@^2.0.1: version "2.0.4" @@ -5033,15 +5074,15 @@ react-focus-lock@^2.9.2: use-callback-ref "^1.3.0" use-sidecar "^1.1.2" -react-hotkeys-hook@4.3.5: - version "4.3.5" - resolved "https://registry.yarnpkg.com/react-hotkeys-hook/-/react-hotkeys-hook-4.3.5.tgz#d77d62b839f54042d255bc111878967fd4958253" - integrity sha512-tfwTwKP3ga7n4naNS/JOByaEwEkTCoXYCepDuhXpj8mBx+sFszV5JecRWM2dv+PbOowmmBpHAFtTXTnG/p8UkQ== +react-hotkeys-hook@4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/react-hotkeys-hook/-/react-hotkeys-hook-4.4.0.tgz#e7c55bb13ecb6ffb447e90ca5525403a5a3ac7b8" + integrity sha512-wOaCWLwgT/f895CMJrR9hmzVf+gfL8IpjWDXWXKngBp9i6Xqzf0tvLv4VI8l3Vlsg/cc4C/Iik3Ck76L/Hj0tw== -react-i18next@^12.1.5: - version "12.2.0" - resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-12.2.0.tgz#010e3f6070b8d700442947233352ebe4b252d7a1" - integrity sha512-5XeVgSygaGfyFmDd2WcXvINRw2WEC1XviW1LXY/xLOEMzsCFRwKqfnHN+hUjla8ZipbVJR27GCMSuTr0BhBBBQ== +react-i18next@^12.2.2: + version "12.2.2" + resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-12.2.2.tgz#38a6fad11acf4f2abfc5611bdb6b1918d0f47578" + integrity sha512-KBB6buBmVKXUWNxXHdnthp+38gPyBT46hJCAIQ8rX19NFL/m2ahte2KARfIDf2tMnSAL7wwck6eDOd/9zn6aFg== dependencies: "@babel/runtime" "^7.20.6" html-parse-stringify "^3.0.1" @@ -5061,18 +5102,18 @@ react-is@^18.0.0: resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== -react-konva-utils@^0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/react-konva-utils/-/react-konva-utils-0.3.2.tgz#7641f437d9ed97a4dc829dbb47d2de75c07f8f5d" - integrity sha512-BocSYCPd58rCumFAL9sUs5aum+eRD53Amknd78Mm2BQln/XMZZS8zHq35HPbiZkSMcj5Q6fZ4foHa9aMLcPRIQ== +react-konva-utils@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/react-konva-utils/-/react-konva-utils-1.0.4.tgz#bce739a207f02fc5f0246f6ab16a0e295f5544af" + integrity sha512-K1J1K9MoVNGFrUxYt+dn7TUVqpppW3Y0fRcf42Ws1wzTQ2Od4qicCom9jnGxLiwh8zyhYaHAUn3hztgfTyYF7g== dependencies: react-konva "^18.0.0-0" use-image "^1.1.0" -react-konva@^18.0.0-0, react-konva@^18.2.4: - version "18.2.5" - resolved "https://registry.yarnpkg.com/react-konva/-/react-konva-18.2.5.tgz#592692619c5f4a9c14726e146574ddc8bc468a7c" - integrity sha512-lTqJStcHnpGSXB9RlV7p5at3MpRML/TujzbuUDZRIInsLocJ/I4Nhhg3w6yJm9UV05kcwr88OY6LO+2zRyzXog== +react-konva@^18.0.0-0, react-konva@^18.2.7: + version "18.2.7" + resolved "https://registry.yarnpkg.com/react-konva/-/react-konva-18.2.7.tgz#f01735ac9ae35a7cd0f3ca359a898374ce791d04" + integrity sha512-Q52ghaIR+2g3x14V5aIyt7VWNqPnWRotILo0Nj4YWVbNQisozrTJJ3/w68qb5Ar2fsYo7yXb4T6Nt4yZcGd2yg== dependencies: "@types/react-reconciler" "^0.28.2" its-fine "^1.0.6" @@ -5137,10 +5178,10 @@ react-transition-group@^4.4.5: loose-envify "^1.4.0" prop-types "^15.6.2" -react-zoom-pan-pinch@^2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/react-zoom-pan-pinch/-/react-zoom-pan-pinch-2.6.1.tgz#5719fdd9515dc1f379a23350cbf99edd540b1281" - integrity sha512-4Cgdnn6OwN4DomY/E9NpAf0TyCtslEgwdYn96ZV/f5LKuw/FE3gcIBJiaKFmMGThDGV0yKN5mzO8noi34+UE4Q== +react-zoom-pan-pinch@^3.0.7: + version "3.0.7" + resolved "https://registry.yarnpkg.com/react-zoom-pan-pinch/-/react-zoom-pan-pinch-3.0.7.tgz#def52f6886bc11e1b160dedf4250aae95470b94d" + integrity sha512-UJkk1Z7BMPIgfY+Qu4jGTlj+UyZQhrpJeCuK1gg31x57i3p8h4ZXfYWu3dFIiR+uRgfoe/koziwgCjA//T1rKA== react@^18.2.0: version "18.2.0" @@ -5162,9 +5203,9 @@ reactflow@^11.7.0: "@reactflow/node-toolbar" "1.1.11" readable-stream@^3.4.0: - version "3.6.1" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.1.tgz#f9f9b5f536920253b3d26e7660e7da4ccff9bb62" - integrity sha512-+rQmrWMYGA90yenhTYsLWAsLsqVC8osOw6PKE1HDYiO0gdPeKe/xDHNzIAIn4C91YQ6oenEhfYqqc1883qHbjQ== + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== dependencies: inherits "^2.0.3" string_decoder "^1.1.1" @@ -5197,7 +5238,7 @@ redux-thunk@^2.4.2: resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.4.2.tgz#b9d05d11994b99f7a91ea223e8b04cf0afa5ef3b" integrity sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q== -redux@^4.2.0: +redux@^4.2.1: version "4.2.1" resolved "https://registry.yarnpkg.com/redux/-/redux-4.2.1.tgz#c08f4306826c49b5e9dc901dee0452ea8fce6197" integrity sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w== @@ -5210,18 +5251,13 @@ regenerator-runtime@^0.13.11, regenerator-runtime@^0.13.7: integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== regexp.prototype.flags@^1.4.3: - version "1.4.3" - resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz#87cab30f80f66660181a3bb7bf5981a872b367ac" - integrity sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA== + version "1.5.0" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz#fe7ce25e7e4cca8db37b6634c8a2c7009199b9cb" + integrity sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA== dependencies: call-bind "^1.0.2" - define-properties "^1.1.3" - functions-have-names "^1.2.2" - -regexpp@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" - integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== + define-properties "^1.2.0" + functions-have-names "^1.2.3" registry-auth-token@^4.0.0: version "4.2.2" @@ -5255,10 +5291,10 @@ requirejs@^2.3.5: resolved "https://registry.yarnpkg.com/requirejs/-/requirejs-2.3.6.tgz#e5093d9601c2829251258c0b9445d4d19fa9e7c9" integrity sha512-ipEzlWQe6RK3jkzikgCupiTbTvm4S0/CAU5GlgptkN5SO6F3u0UD0K18wy6ErDqiCyP4J4YYe1HuAShvsxePLg== -reselect@^4.1.7: - version "4.1.7" - resolved "https://registry.yarnpkg.com/reselect/-/reselect-4.1.7.tgz#56480d9ff3d3188970ee2b76527bd94a95567a42" - integrity sha512-Zu1xbUt3/OPwsXL46hvOOoQrap2azE7ZQbokq61BQfiXvhewsKDwhMeZjTX9sX0nvw1t/U5Audyn1I9P/m9z0A== +reselect@^4.1.8: + version "4.1.8" + resolved "https://registry.yarnpkg.com/reselect/-/reselect-4.1.8.tgz#3f5dc671ea168dccdeb3e141236f69f02eaec524" + integrity sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ== resolve-dependency-path@^2.0.0: version "2.0.0" @@ -5270,12 +5306,12 @@ resolve-from@^4.0.0: resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== -resolve@^1.19.0, resolve@^1.21.0, resolve@^1.22.1: - version "1.22.1" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" - integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== +resolve@^1.19.0, resolve@^1.21.0: + version "1.22.2" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.2.tgz#0ed0943d4e301867955766c9f3e1ae6d01c6845f" + integrity sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g== dependencies: - is-core-module "^2.9.0" + is-core-module "^2.11.0" path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" @@ -5344,10 +5380,10 @@ rollup@^2.77.2: optionalDependencies: fsevents "~2.3.2" -rollup@^3.10.0: - version "3.18.0" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-3.18.0.tgz#2354ba63ba66d6a09c652c3ea0dbcd9dad72bbde" - integrity sha512-J8C6VfEBjkvYPESMQYxKHxNOh4A5a3FlP+0BETGo34HEcE4eTlgCrO2+eWzlu2a/sHs2QUkZco+wscH7jhhgWg== +rollup@^3.21.0: + version "3.21.0" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-3.21.0.tgz#0a71517db56e150222670f88e5e7acfa4fede7c8" + integrity sha512-ANPhVcyeHvYdQMUyCbczy33nbLzI7RzrBje4uvNiTDJGIMtlKoOStmympwr9OtS1LZxiDmE2wvxHyVhoLtf1KQ== optionalDependencies: fsevents "~2.3.2" @@ -5358,10 +5394,10 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" -rxjs@^7.0.0, rxjs@^7.8.0: - version "7.8.0" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.0.tgz#90a938862a82888ff4c7359811a595e14e1e09a4" - integrity sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg== +rxjs@^7.8.0: + version "7.8.1" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543" + integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg== dependencies: tslib "^2.1.0" @@ -5400,7 +5436,7 @@ semver-diff@^3.1.1: dependencies: semver "^6.3.0" -semver@^5.5.0, semver@^5.6.0: +semver@^5.6.0: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== @@ -5411,19 +5447,12 @@ semver@^6.0.0, semver@^6.2.0, semver@^6.3.0: integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== semver@^7.3.4, semver@^7.3.5, semver@^7.3.7: - version "7.3.8" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798" - integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A== + version "7.5.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.0.tgz#ed8c5dc8efb6c629c88b23d41dc9bf40c1d96cd0" + integrity sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA== dependencies: lru-cache "^6.0.0" -shebang-command@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" - integrity sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg== - dependencies: - shebang-regex "^1.0.0" - shebang-command@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" @@ -5431,20 +5460,15 @@ shebang-command@^2.0.0: dependencies: shebang-regex "^3.0.0" -shebang-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" - integrity sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ== - shebang-regex@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== -shell-quote@^1.7.3: - version "1.8.0" - resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.8.0.tgz#20d078d0eaf71d54f43bd2ba14a1b5b9bfa5c8ba" - integrity sha512-QHsz8GgQIGKlRi24yFc6a6lN69Idnx634w49ay6+jA5yFh7a1UY+4Rp6HPx/L/1zcEDPEij8cIsiqR6bQsE5VQ== +shell-quote@^1.8.0: + version "1.8.1" + resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.8.1.tgz#6dbf4db75515ad5bac63b4f1894c3a154c766680" + integrity sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA== side-channel@^1.0.4: version "1.0.4" @@ -5542,7 +5566,7 @@ source-map@^0.7.4: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.4.tgz#a9bbe705c9d8846f4e08ff6765acf0f1b0898656" integrity sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA== -spawn-command@^0.0.2-1: +spawn-command@0.0.2-1: version "0.0.2-1" resolved "https://registry.yarnpkg.com/spawn-command/-/spawn-command-0.0.2-1.tgz#62f5e9466981c1b796dc5929937e11c9c6921bd0" integrity sha512-n98l9E2RMSJ9ON1AKisHzz7V42VDiBQGY6PB1BwRglz99wpVsSuGzQ+jOi6lFXBGVTCrRpltvjm+/XA+tpeJrg== @@ -5591,6 +5615,15 @@ string.prototype.matchall@^4.0.8: regexp.prototype.flags "^1.4.3" side-channel "^1.0.4" +string.prototype.trim@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz#a68352740859f6893f14ce3ef1bb3037f7a90533" + integrity sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + string.prototype.trimend@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz#c4a27fa026d979d79c04f17397f250a462944533" @@ -5686,7 +5719,7 @@ supports-color@^7.1.0: dependencies: has-flag "^4.0.0" -supports-color@^8.1.0: +supports-color@^8.1.1: version "8.1.1" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== @@ -5703,10 +5736,10 @@ tapable@^2.2.0: resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== -terser@^5.16.4: - version "5.16.5" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.16.5.tgz#1c285ca0655f467f92af1bbab46ab72d1cb08e5a" - integrity sha512-qcwfg4+RZa3YvlFh0qjifnzBHjKGNbtDo9yivMqMFDy9Q6FSaQWSB/j1xKhsoUFJIqDOM3TsN6D5xbrMrFcHbg== +terser@^5.17.1: + version "5.17.1" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.17.1.tgz#948f10830454761e2eeedc6debe45c532c83fd69" + integrity sha512-hVl35zClmpisy6oaoKALOpS0rDYLxRFLHhRuDlEGTKey9qHjS1w9GMORjuwIMt70Wan4lwsLYyWDVnWgF+KUEw== dependencies: "@jridgewell/source-map" "^0.3.2" acorn "^8.5.0" @@ -5773,9 +5806,9 @@ tree-kill@^1.2.2: integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== ts-graphviz@^1.5.0: - version "1.5.5" - resolved "https://registry.yarnpkg.com/ts-graphviz/-/ts-graphviz-1.5.5.tgz#b5e9079c18289fb36b6b53f3d81da96445c37514" - integrity sha512-abon0Tlcgvxcqr8x+p8QH1fTbR2R4cEXKGZfT4OJONZWah2YfqkmERb6hrr82omAc1IHwk5PlF8g4BS/ECYvwQ== + version "1.6.1" + resolved "https://registry.yarnpkg.com/ts-graphviz/-/ts-graphviz-1.6.1.tgz#f44525c048cb8c8c188b7324d2a91015fd31ceaf" + integrity sha512-9aZKR7hoQAHXlgb7HvUND3y5VhEI5PMNVv/BfelPXebcsxdwZhBYbM8XpnV4NfiHV9O0/sAI9sQVuce0gogzlA== ts-node@^10.7.0: version "10.9.1" @@ -5801,10 +5834,10 @@ ts-toolbelt@^9.6.0: resolved "https://registry.yarnpkg.com/ts-toolbelt/-/ts-toolbelt-9.6.0.tgz#50a25426cfed500d4a09bd1b3afb6f28879edfd5" integrity sha512-nsZd8ZeNUzukXPlJmTBwUAuABDe/9qtVDelJeT/qW0ow3ZS3BsQJtNkan1802aM9Uf68/Y8ljw86Hu0h5IUW3w== -tsconfck@^2.0.1: - version "2.0.3" - resolved "https://registry.yarnpkg.com/tsconfck/-/tsconfck-2.0.3.tgz#47b79fc6be3c5ec6ec9b3862d1c959e85038b117" - integrity sha512-o3DsPZO1+C98KqHMdAbWs30zpxD30kj8r9OLA4ML1yghx4khNDzaaShNalfluh8ZPPhzKe3qyVCP1HiZszSAsw== +tsconfck@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/tsconfck/-/tsconfck-2.1.1.tgz#9b51603d2712d1f4740fa14748ca886a2e1893e5" + integrity sha512-ZPCkJBKASZBmBUNqGHmRhdhM8pJYDdOXp4nRgj/O0JwUwsMq50lCDRQP/M5GBNAA0elPrq4gAeu4dkaVCuKWww== tsconfig-paths@^3.10.1: version "3.14.2" @@ -5817,9 +5850,9 @@ tsconfig-paths@^3.10.1: strip-bom "^3.0.0" tsconfig-paths@^4.0.0: - version "4.1.2" - resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-4.1.2.tgz#4819f861eef82e6da52fb4af1e8c930a39ed979a" - integrity sha512-uhxiMgnXQp1IR622dUXI+9Ehnws7i/y6xvpZB9IbUVOPy0muvdvgXeZOn88UcGPiT98Vp3rJPTa8bFoalZ3Qhw== + version "4.2.0" + resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz#ef78e19039133446d244beac0fd6a1632e2d107c" + integrity sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg== dependencies: json5 "^2.2.2" minimist "^1.2.6" @@ -5887,16 +5920,16 @@ typedarray-to-buffer@^3.1.5: dependencies: is-typedarray "^1.0.0" -typescript@4.9.5, typescript@^4.0.0, typescript@^4.5.5: - version "4.9.5" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" - integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== - typescript@^3.9.10, typescript@^3.9.5, typescript@^3.9.7: version "3.9.10" resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.10.tgz#70f3910ac7a51ed6bef79da7800690b19bf778b8" integrity sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q== +typescript@^4.0.0, typescript@^4.9.5: + version "4.9.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" + integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== + uglify-js@^3.1.4: version "3.17.4" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.17.4.tgz#61678cf5fa3f5b7eb789bb345df29afb8257c22c" @@ -6012,24 +6045,23 @@ vite-plugin-eslint@^1.8.1: "@types/eslint" "^8.4.5" rollup "^2.77.2" -vite-tsconfig-paths@^4.0.5: - version "4.0.5" - resolved "https://registry.yarnpkg.com/vite-tsconfig-paths/-/vite-tsconfig-paths-4.0.5.tgz#c7c54e2cf7ccc5e600db565cecd7b368a1fa8889" - integrity sha512-/L/eHwySFYjwxoYt1WRJniuK/jPv+WGwgRGBYx3leciR5wBeqntQpUE6Js6+TJemChc+ter7fDBKieyEWDx4yQ== +vite-tsconfig-paths@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/vite-tsconfig-paths/-/vite-tsconfig-paths-4.2.0.tgz#bd2647d3eadafb65a10fc98a2ca565211f2eaf63" + integrity sha512-jGpus0eUy5qbbMVGiTxCL1iB9ZGN6Bd37VGLJU39kTDD6ZfULTTb1bcc5IeTWqWJKiWV5YihCaibeASPiGi8kw== dependencies: debug "^4.1.1" globrex "^0.1.2" - tsconfck "^2.0.1" + tsconfck "^2.1.0" -vite@^4.1.2: - version "4.1.4" - resolved "https://registry.yarnpkg.com/vite/-/vite-4.1.4.tgz#170d93bcff97e0ebc09764c053eebe130bfe6ca0" - integrity sha512-3knk/HsbSTKEin43zHu7jTwYWv81f8kgAL99G5NWBcA1LKvtvcVAC4JjBH1arBunO9kQka+1oGbrMKOjk4ZrBg== +vite@^4.3.3: + version "4.3.3" + resolved "https://registry.yarnpkg.com/vite/-/vite-4.3.3.tgz#26adb4aa01439fc4546c480ea547674d87289396" + integrity sha512-MwFlLBO4udZXd+VBcezo3u8mC77YQk+ik+fbc0GZWGgzfbPP+8Kf0fldhARqvSYmtIWoAJ5BXPClUbMTlqFxrA== dependencies: - esbuild "^0.16.14" - postcss "^8.4.21" - resolve "^1.22.1" - rollup "^3.10.0" + esbuild "^0.17.5" + postcss "^8.4.23" + rollup "^3.21.0" optionalDependencies: fsevents "~2.3.2" @@ -6086,13 +6118,6 @@ which-typed-array@^1.1.9: has-tostringtag "^1.0.0" is-typed-array "^1.1.10" -which@^1.2.9: - version "1.3.1" - resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" - integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== - dependencies: - isexe "^2.0.0" - which@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" @@ -6175,25 +6200,25 @@ yallist@^4.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== -yaml@^1.10.0, yaml@^1.10.2: +yaml@^1.10.0: version "1.10.2" resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== -yaml@^2.1.3: - version "2.2.1" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.2.1.tgz#3014bf0482dcd15147aa8e56109ce8632cd60ce4" - integrity sha512-e0WHiYql7+9wr4cWMx3TVQrNwejKaEe7/rHNmQmqRjazfOP5W8PB6Jpebb5o6fIapbz9o9+2ipcaTM2ZwDI6lw== +yaml@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.2.2.tgz#ec551ef37326e6d42872dad1970300f8eb83a073" + integrity sha512-CBKFWExMn46Foo4cldiChEzn7S7SRV+wqiluAb6xmueD/fGyRHIhX8m14vVGgeFWjN540nKCNVj6P21eQjgTuA== yargs-parser@^21.1.1: version "21.1.1" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== -yargs@^17.3.1, yargs@^17.5.1: - version "17.7.1" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.1.tgz#34a77645201d1a8fc5213ace787c220eabbd0967" - integrity sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw== +yargs@^17.5.1, yargs@^17.7.1: + version "17.7.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" + integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== dependencies: cliui "^8.0.1" escalade "^3.1.1" From d5829494880d8860c277f0268c5f7ce84145e100 Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Fri, 28 Apr 2023 14:27:17 +1000 Subject: [PATCH 18/68] feat(ui): rename main app components --- .../frontend/web/src/app/components/App.tsx | 166 ++++++++++++------ .../web/src/app/components/InvokeAIUI.tsx | 166 ++++++------------ invokeai/frontend/web/src/main.tsx | 4 +- 3 files changed, 168 insertions(+), 168 deletions(-) diff --git a/invokeai/frontend/web/src/app/components/App.tsx b/invokeai/frontend/web/src/app/components/App.tsx index 8dfdc9f183..7cdbe830bb 100644 --- a/invokeai/frontend/web/src/app/components/App.tsx +++ b/invokeai/frontend/web/src/app/components/App.tsx @@ -1,70 +1,126 @@ -import React, { lazy, memo, PropsWithChildren, useEffect } from 'react'; -import { Provider } from 'react-redux'; -import { PersistGate } from 'redux-persist/integration/react'; -import { buildMiddleware, store } from 'app/store/store'; -import { persistor } from '../store/persistor'; -import { OpenAPI } from 'services/api'; -import '@fontsource/inter/100.css'; -import '@fontsource/inter/200.css'; -import '@fontsource/inter/300.css'; -import '@fontsource/inter/400.css'; -import '@fontsource/inter/500.css'; -import '@fontsource/inter/600.css'; -import '@fontsource/inter/700.css'; -import '@fontsource/inter/800.css'; -import '@fontsource/inter/900.css'; +import ImageUploader from 'common/components/ImageUploader'; +import Console from 'features/system/components/Console'; +import ProgressBar from 'features/system/components/ProgressBar'; +import SiteHeader from 'features/system/components/SiteHeader'; +import InvokeTabs from 'features/ui/components/InvokeTabs'; -import Loading from '../../common/components/Loading/Loading'; -import { addMiddleware, resetMiddlewares } from 'redux-dynamic-middlewares'; +import useToastWatcher from 'features/system/hooks/useToastWatcher'; + +import FloatingGalleryButton from 'features/ui/components/FloatingGalleryButton'; +import FloatingParametersPanelButtons from 'features/ui/components/FloatingParametersPanelButtons'; +import { Box, Flex, Grid, Portal, useColorMode } from '@chakra-ui/react'; +import { APP_HEIGHT, APP_WIDTH } from 'theme/util/constants'; +import ImageGalleryPanel from 'features/gallery/components/ImageGalleryPanel'; +import Lightbox from 'features/lightbox/components/Lightbox'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; +import { + memo, + PropsWithChildren, + useCallback, + useEffect, + useState, +} from 'react'; +import { motion, AnimatePresence } from 'framer-motion'; +import Loading from 'common/components/Loading/Loading'; +import { useIsApplicationReady } from 'features/system/hooks/useIsApplicationReady'; import { PartialAppConfig } from 'app/types/invokeai'; - -import '../../i18n'; - -const InvokeAIUI = lazy(() => import('./InvokeAIUI')); -const ThemeLocaleProvider = lazy(() => import('./ThemeLocaleProvider')); +import { useGlobalHotkeys } from 'common/hooks/useGlobalHotkeys'; +import { configChanged } from 'features/system/store/configSlice'; +import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus'; interface Props extends PropsWithChildren { - apiUrl?: string; - token?: string; config?: PartialAppConfig; } -const App = ({ apiUrl, token, config, children }: Props) => { +const App = ({ config = {}, children }: Props) => { + useToastWatcher(); + useGlobalHotkeys(); + + const currentTheme = useAppSelector((state) => state.ui.currentTheme); + + const isLightboxEnabled = useFeatureStatus('lightbox').isFeatureEnabled; + + const isApplicationReady = useIsApplicationReady(); + + const [loadingOverridden, setLoadingOverridden] = useState(false); + + const { setColorMode } = useColorMode(); + const dispatch = useAppDispatch(); + useEffect(() => { - // configure API client token - if (token) { - OpenAPI.TOKEN = token; - } + console.log('Received config: ', config); + dispatch(configChanged(config)); + }, [dispatch, config]); - // configure API client base url - if (apiUrl) { - OpenAPI.BASE = apiUrl; - } + useEffect(() => { + setColorMode(['light'].includes(currentTheme) ? 'light' : 'dark'); + }, [setColorMode, currentTheme]); - // reset dynamically added middlewares - resetMiddlewares(); - - // TODO: at this point, after resetting the middleware, we really ought to clean up the socket - // stuff by calling `dispatch(socketReset())`. but we cannot dispatch from here as we are - // outside the provider. it's not needed until there is the possibility that we will change - // the `apiUrl`/`token` dynamically. - - // rebuild socket middleware with token and apiUrl - addMiddleware(buildMiddleware()); - }, [apiUrl, token]); + const handleOverrideClicked = useCallback(() => { + setLoadingOverridden(true); + }, []); return ( - - - } persistor={persistor}> - }> - - {children} - - - - - + + {isLightboxEnabled && } + + + + {children || } + + + + + + + + + {!isApplicationReady && !loadingOverridden && ( + + + + + + + )} + + + + + + + + + + + + ); }; diff --git a/invokeai/frontend/web/src/app/components/InvokeAIUI.tsx b/invokeai/frontend/web/src/app/components/InvokeAIUI.tsx index b491265ef5..a66f2ef2a3 100644 --- a/invokeai/frontend/web/src/app/components/InvokeAIUI.tsx +++ b/invokeai/frontend/web/src/app/components/InvokeAIUI.tsx @@ -1,126 +1,70 @@ -import ImageUploader from 'common/components/ImageUploader'; -import Console from 'features/system/components/Console'; -import ProgressBar from 'features/system/components/ProgressBar'; -import SiteHeader from 'features/system/components/SiteHeader'; -import InvokeTabs from 'features/ui/components/InvokeTabs'; +import React, { lazy, memo, PropsWithChildren, useEffect } from 'react'; +import { Provider } from 'react-redux'; +import { PersistGate } from 'redux-persist/integration/react'; +import { buildMiddleware, store } from 'app/store/store'; +import { persistor } from '../store/persistor'; +import { OpenAPI } from 'services/api'; +import '@fontsource/inter/100.css'; +import '@fontsource/inter/200.css'; +import '@fontsource/inter/300.css'; +import '@fontsource/inter/400.css'; +import '@fontsource/inter/500.css'; +import '@fontsource/inter/600.css'; +import '@fontsource/inter/700.css'; +import '@fontsource/inter/800.css'; +import '@fontsource/inter/900.css'; -import useToastWatcher from 'features/system/hooks/useToastWatcher'; - -import FloatingGalleryButton from 'features/ui/components/FloatingGalleryButton'; -import FloatingParametersPanelButtons from 'features/ui/components/FloatingParametersPanelButtons'; -import { Box, Flex, Grid, Portal, useColorMode } from '@chakra-ui/react'; -import { APP_HEIGHT, APP_WIDTH } from 'theme/util/constants'; -import ImageGalleryPanel from 'features/gallery/components/ImageGalleryPanel'; -import Lightbox from 'features/lightbox/components/Lightbox'; -import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; -import { - memo, - PropsWithChildren, - useCallback, - useEffect, - useState, -} from 'react'; -import { motion, AnimatePresence } from 'framer-motion'; -import Loading from 'common/components/Loading/Loading'; -import { useIsApplicationReady } from 'features/system/hooks/useIsApplicationReady'; +import Loading from '../../common/components/Loading/Loading'; +import { addMiddleware, resetMiddlewares } from 'redux-dynamic-middlewares'; import { PartialAppConfig } from 'app/types/invokeai'; -import { useGlobalHotkeys } from 'common/hooks/useGlobalHotkeys'; -import { configChanged } from 'features/system/store/configSlice'; -import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus'; + +import '../../i18n'; + +const App = lazy(() => import('./App')); +const ThemeLocaleProvider = lazy(() => import('./ThemeLocaleProvider')); interface Props extends PropsWithChildren { + apiUrl?: string; + token?: string; config?: PartialAppConfig; } -const InvokeAIUI = ({ config = {}, children }: Props) => { - useToastWatcher(); - useGlobalHotkeys(); - - const currentTheme = useAppSelector((state) => state.ui.currentTheme); - - const isLightboxEnabled = useFeatureStatus('lightbox').isFeatureEnabled; - - const isApplicationReady = useIsApplicationReady(); - - const [loadingOverridden, setLoadingOverridden] = useState(false); - - const { setColorMode } = useColorMode(); - const dispatch = useAppDispatch(); - +const InvokeAIUI = ({ apiUrl, token, config, children }: Props) => { useEffect(() => { - console.log('Received config: ', config); - dispatch(configChanged(config)); - }, [dispatch, config]); + // configure API client token + if (token) { + OpenAPI.TOKEN = token; + } - useEffect(() => { - setColorMode(['light'].includes(currentTheme) ? 'light' : 'dark'); - }, [setColorMode, currentTheme]); + // configure API client base url + if (apiUrl) { + OpenAPI.BASE = apiUrl; + } - const handleOverrideClicked = useCallback(() => { - setLoadingOverridden(true); - }, []); + // reset dynamically added middlewares + resetMiddlewares(); + + // TODO: at this point, after resetting the middleware, we really ought to clean up the socket + // stuff by calling `dispatch(socketReset())`. but we cannot dispatch from here as we are + // outside the provider. it's not needed until there is the possibility that we will change + // the `apiUrl`/`token` dynamically. + + // rebuild socket middleware with token and apiUrl + addMiddleware(buildMiddleware()); + }, [apiUrl, token]); return ( - - {isLightboxEnabled && } - - - - {children || } - - - - - - - - - {!isApplicationReady && !loadingOverridden && ( - - - - - - - )} - - - - - - - - - - - - + + + } persistor={persistor}> + }> + + {children} + + + + + ); }; diff --git a/invokeai/frontend/web/src/main.tsx b/invokeai/frontend/web/src/main.tsx index 4a57f73eeb..c07decae63 100644 --- a/invokeai/frontend/web/src/main.tsx +++ b/invokeai/frontend/web/src/main.tsx @@ -1,7 +1,7 @@ import ReactDOM from 'react-dom/client'; -import App from './app/components/App'; +import InvokeAIUI from './app/components/InvokeAIUI'; ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( - + ); From 61fbb24e365f5b1381209e665f2a8f31213e9ba2 Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Fri, 28 Apr 2023 15:44:27 +1000 Subject: [PATCH 19/68] feat(ui): set up for packaging --- .../frontend/web/config/vite.app.config.ts | 17 + .../frontend/web/config/vite.common.config.ts | 54 ++++ .../web/config/vite.package.config.ts | 35 +++ invokeai/frontend/web/package.json | 17 +- .../app/types/{invokeai.d.ts => invokeai.ts} | 111 ++++--- invokeai/frontend/web/src/exports.tsx | 22 -- invokeai/frontend/web/src/index.ts | 9 + invokeai/frontend/web/tsconfig.node.json | 7 +- invokeai/frontend/web/vite.config.ts | 87 +----- invokeai/frontend/web/yarn.lock | 292 +++++++++++++++++- 10 files changed, 482 insertions(+), 169 deletions(-) create mode 100644 invokeai/frontend/web/config/vite.app.config.ts create mode 100644 invokeai/frontend/web/config/vite.common.config.ts create mode 100644 invokeai/frontend/web/config/vite.package.config.ts rename invokeai/frontend/web/src/app/types/{invokeai.d.ts => invokeai.ts} (73%) delete mode 100644 invokeai/frontend/web/src/exports.tsx create mode 100644 invokeai/frontend/web/src/index.ts diff --git a/invokeai/frontend/web/config/vite.app.config.ts b/invokeai/frontend/web/config/vite.app.config.ts new file mode 100644 index 0000000000..e6725e98c8 --- /dev/null +++ b/invokeai/frontend/web/config/vite.app.config.ts @@ -0,0 +1,17 @@ +import react from '@vitejs/plugin-react-swc'; +import { visualizer } from 'rollup-plugin-visualizer'; +import { PluginOption, UserConfig } from 'vite'; +import eslint from 'vite-plugin-eslint'; +import tsconfigPaths from 'vite-tsconfig-paths'; + +export const appConfig: UserConfig = { + plugins: [ + react(), + eslint(), + tsconfigPaths(), + visualizer() as unknown as PluginOption, + ], + build: { + chunkSizeWarningLimit: 1500, + }, +}; diff --git a/invokeai/frontend/web/config/vite.common.config.ts b/invokeai/frontend/web/config/vite.common.config.ts new file mode 100644 index 0000000000..dbd8ae4b8d --- /dev/null +++ b/invokeai/frontend/web/config/vite.common.config.ts @@ -0,0 +1,54 @@ +import react from '@vitejs/plugin-react-swc'; +import { visualizer } from 'rollup-plugin-visualizer'; +import { PluginOption, UserConfig } from 'vite'; +import eslint from 'vite-plugin-eslint'; +import tsconfigPaths from 'vite-tsconfig-paths'; + +export const commonConfig: UserConfig = { + base: './', + server: { + // Proxy HTTP requests to the flask server + proxy: { + '/outputs': { + target: 'http://127.0.0.1:9090/outputs', + changeOrigin: true, + rewrite: (path) => path.replace(/^\/outputs/, ''), + }, + '/upload': { + target: 'http://127.0.0.1:9090/upload', + changeOrigin: true, + rewrite: (path) => path.replace(/^\/upload/, ''), + }, + '/flaskwebgui-keep-server-alive': { + target: 'http://127.0.0.1:9090/flaskwebgui-keep-server-alive', + changeOrigin: true, + rewrite: (path) => path.replace(/^\/flaskwebgui-keep-server-alive/, ''), + }, + // Proxy socket.io to the flask-socketio server + '/socket.io': { + target: 'ws://127.0.0.1:9090', + ws: true, + }, + // Proxy socket.io to the nodes socketio server + '/ws/socket.io': { + target: 'ws://127.0.0.1:9090', + ws: true, + }, + // Proxy openapi schema definiton + '/openapi.json': { + target: 'http://127.0.0.1:9090/openapi.json', + rewrite: (path) => path.replace(/^\/openapi.json/, ''), + changeOrigin: true, + }, + // proxy nodes api + '/api/v1': { + target: 'http://127.0.0.1:9090/api/v1', + rewrite: (path) => path.replace(/^\/api\/v1/, ''), + changeOrigin: true, + }, + }, + }, + build: { + chunkSizeWarningLimit: 1500, + }, +}; diff --git a/invokeai/frontend/web/config/vite.package.config.ts b/invokeai/frontend/web/config/vite.package.config.ts new file mode 100644 index 0000000000..906af84887 --- /dev/null +++ b/invokeai/frontend/web/config/vite.package.config.ts @@ -0,0 +1,35 @@ +import react from '@vitejs/plugin-react-swc'; +import path from 'path'; +import { visualizer } from 'rollup-plugin-visualizer'; +import { PluginOption, UserConfig } from 'vite'; +import eslint from 'vite-plugin-eslint'; +import tsconfigPaths from 'vite-tsconfig-paths'; +import dts from 'vite-plugin-dts'; + +export const packageConfig: UserConfig = { + plugins: [ + react(), + eslint(), + tsconfigPaths(), + visualizer() as unknown as PluginOption, + dts({ + insertTypesEntry: true, + }), + ], + build: { + chunkSizeWarningLimit: 1500, + lib: { + entry: path.resolve(__dirname, '../src/index.ts'), + name: 'InvokeAIUI', + fileName: (format) => `invoke-ai-ui.${format}.js`, + }, + rollupOptions: { + external: ['react', 'react-dom'], + output: { + globals: { + react: 'React', + }, + }, + }, + }, +}; diff --git a/invokeai/frontend/web/package.json b/invokeai/frontend/web/package.json index 75609a1da8..9932fb3ad3 100644 --- a/invokeai/frontend/web/package.json +++ b/invokeai/frontend/web/package.json @@ -1,7 +1,20 @@ { - "name": "invoke-ai-ui", + "name": "@invoke-ai/invoke-ai-ui", "private": true, "version": "0.0.1", + "publishConfig": { + "access": "restricted", + "registry": "https://npm.pkg.github.com" + }, + "main": "./dist/invoke-ai-ui.umd.js", + "module": "./dist/invoke-ai-ui.es.js", + "exports": { + ".": { + "import": "./dist/invoke-ai-ui.es.js", + "require": "./dist/invoke-ai-ui.umd.js" + } + }, + "types": "./dist/index.d.ts", "scripts": { "prepare": "cd ../../../ && husky install invokeai/frontend/web/.husky", "dev": "concurrently \"vite dev\" \"yarn run theme:watch\"", @@ -85,6 +98,7 @@ "devDependencies": { "@types/dateformat": "^5.0.0", "@types/lodash": "^4.14.194", + "@types/node": "^18.16.2", "@types/react": "^18.2.0", "@types/react-dom": "^18.2.1", "@types/react-transition-group": "^4.4.5", @@ -112,6 +126,7 @@ "terser": "^5.17.1", "ts-toolbelt": "^9.6.0", "vite": "^4.3.3", + "vite-plugin-dts": "^2.3.0", "vite-plugin-eslint": "^1.8.1", "vite-tsconfig-paths": "^4.2.0", "yarn": "^1.22.19" diff --git a/invokeai/frontend/web/src/app/types/invokeai.d.ts b/invokeai/frontend/web/src/app/types/invokeai.ts similarity index 73% rename from invokeai/frontend/web/src/app/types/invokeai.d.ts rename to invokeai/frontend/web/src/app/types/invokeai.ts index 0e7fa55a36..27ca9dc4a6 100644 --- a/invokeai/frontend/web/src/app/types/invokeai.d.ts +++ b/invokeai/frontend/web/src/app/types/invokeai.ts @@ -12,10 +12,11 @@ * 'gfpgan'. */ +import { GalleryCategory } from 'features/gallery/store/gallerySlice'; import { FacetoolType } from 'features/parameters/store/postprocessingSlice'; import { InvokeTabName } from 'features/ui/store/tabMap'; import { IRect } from 'konva/lib/types'; -import { ImageMetadata, ImageType } from 'services/api'; +import { ImageResponseMetadata, ImageType } from 'services/api'; import { AnyInvocation } from 'services/events/types'; import { O } from 'ts-toolbelt'; @@ -28,24 +29,24 @@ import { O } from 'ts-toolbelt'; * TODO: Better documentation of types. */ -export declare type PromptItem = { +export type PromptItem = { prompt: string; weight: number; }; // TECHDEBT: We need to retain compatibility with plain prompt strings and the structure Prompt type -export declare type Prompt = Array | string; +export type Prompt = Array | string; -export declare type SeedWeightPair = { +export type SeedWeightPair = { seed: number; weight: number; }; -export declare type SeedWeights = Array; +export type SeedWeights = Array; // All generated images contain these metadata. -export declare type CommonGeneratedImageMetadata = { - postprocessing: null | Array; +export type CommonGeneratedImageMetadata = { + postprocessing: null | Array; sampler: | 'ddim' | 'k_dpm_2_a' @@ -70,11 +71,11 @@ export declare type CommonGeneratedImageMetadata = { }; // txt2img and img2img images have some unique attributes. -export declare type Txt2ImgMetadata = GeneratedImageMetadata & { +export type Txt2ImgMetadata = CommonGeneratedImageMetadata & { type: 'txt2img'; }; -export declare type Img2ImgMetadata = GeneratedImageMetadata & { +export type Img2ImgMetadata = CommonGeneratedImageMetadata & { type: 'img2img'; orig_hash: string; strength: number; @@ -84,40 +85,38 @@ export declare type Img2ImgMetadata = GeneratedImageMetadata & { }; // Superset of generated image metadata types. -export declare type GeneratedImageMetadata = Txt2ImgMetadata | Img2ImgMetadata; +export type GeneratedImageMetadata = Txt2ImgMetadata | Img2ImgMetadata; // All post processed images contain these metadata. -export declare type CommonPostProcessedImageMetadata = { +export type CommonPostProcessedImageMetadata = { orig_path: string; orig_hash: string; }; // esrgan and gfpgan images have some unique attributes. -export declare type ESRGANMetadata = CommonPostProcessedImageMetadata & { +export type ESRGANMetadata = CommonPostProcessedImageMetadata & { type: 'esrgan'; scale: 2 | 4; strength: number; denoise_str: number; }; -export declare type FacetoolMetadata = CommonPostProcessedImageMetadata & { +export type FacetoolMetadata = CommonPostProcessedImageMetadata & { type: 'gfpgan' | 'codeformer'; strength: number; fidelity?: number; }; // Superset of all postprocessed image metadata types.. -export declare type PostProcessedImageMetadata = - | ESRGANMetadata - | FacetoolMetadata; +export type PostProcessedImageMetadata = ESRGANMetadata | FacetoolMetadata; // Metadata includes the system config and image metadata. -export declare type Metadata = SystemGenerationMetadata & { +export type Metadata = SystemGenerationMetadata & { image: GeneratedImageMetadata | PostProcessedImageMetadata; }; // An Image has a UUID, url, modified timestamp, width, height and maybe metadata -export declare type _Image = { +export type _Image = { uuid: string; url: string; thumbnail: string; @@ -134,16 +133,16 @@ export declare type _Image = { /** * ResultImage */ -export declare type Image = { +export type Image = { name: string; type: ImageType; url: string; thumbnail: string; - metadata: ImageMetadata; + metadata: ImageResponseMetadata; }; // GalleryImages is an array of Image. -export declare type GalleryImages = { +export type GalleryImages = { images: Array<_Image>; }; @@ -152,7 +151,7 @@ export declare type GalleryImages = { */ // This represents the processing status of the backend. -export declare type SystemStatus = { +export type SystemStatus = { isProcessing: boolean; currentStep: number; totalSteps: number; @@ -163,7 +162,7 @@ export declare type SystemStatus = { hasError: boolean; }; -export declare type SystemGenerationMetadata = { +export type SystemGenerationMetadata = { model: string; model_weights?: string; model_id?: string; @@ -172,14 +171,14 @@ export declare type SystemGenerationMetadata = { app_version: string; }; -export declare type SystemConfig = SystemGenerationMetadata & { +export type SystemConfig = SystemGenerationMetadata & { model_list: ModelList; infill_methods: string[]; }; -export declare type ModelStatus = 'active' | 'cached' | 'not loaded'; +export type ModelStatus = 'active' | 'cached' | 'not loaded'; -export declare type Model = { +export type Model = { status: ModelStatus; description: string; weights: string; @@ -191,7 +190,7 @@ export declare type Model = { format?: string; }; -export declare type DiffusersModel = { +export type DiffusersModel = { status: ModelStatus; description: string; repo_id?: string; @@ -204,14 +203,14 @@ export declare type DiffusersModel = { default?: boolean; }; -export declare type ModelList = Record; +export type ModelList = Record; -export declare type FoundModel = { +export type FoundModel = { name: string; location: string; }; -export declare type InvokeModelConfigProps = { +export type InvokeModelConfigProps = { name: string | undefined; description: string | undefined; config: string | undefined; @@ -223,7 +222,7 @@ export declare type InvokeModelConfigProps = { format: string | undefined; }; -export declare type InvokeDiffusersModelConfigProps = { +export type InvokeDiffusersModelConfigProps = { name: string | undefined; description: string | undefined; repo_id: string | undefined; @@ -236,13 +235,13 @@ export declare type InvokeDiffusersModelConfigProps = { }; }; -export declare type InvokeModelConversionProps = { +export type InvokeModelConversionProps = { model_name: string; save_location: string; custom_location: string | null; }; -export declare type InvokeModelMergingProps = { +export type InvokeModelMergingProps = { models_to_merge: string[]; alpha: number; interp: 'weighted_sum' | 'sigmoid' | 'inv_sigmoid' | 'add_difference'; @@ -255,48 +254,48 @@ export declare type InvokeModelMergingProps = { * These types type data received from the server via socketio. */ -export declare type ModelChangeResponse = { +export type ModelChangeResponse = { model_name: string; model_list: ModelList; }; -export declare type ModelConvertedResponse = { +export type ModelConvertedResponse = { converted_model_name: string; model_list: ModelList; }; -export declare type ModelsMergedResponse = { +export type ModelsMergedResponse = { merged_models: string[]; merged_model_name: string; model_list: ModelList; }; -export declare type ModelAddedResponse = { +export type ModelAddedResponse = { new_model_name: string; model_list: ModelList; update: boolean; }; -export declare type ModelDeletedResponse = { +export type ModelDeletedResponse = { deleted_model_name: string; model_list: ModelList; }; -export declare type FoundModelResponse = { +export type FoundModelResponse = { search_folder: string; found_models: FoundModel[]; }; -export declare type SystemStatusResponse = SystemStatus; +export type SystemStatusResponse = SystemStatus; -export declare type SystemConfigResponse = SystemConfig; +export type SystemConfigResponse = SystemConfig; -export declare type ImageResultResponse = Omit<_Image, 'uuid'> & { +export type ImageResultResponse = Omit<_Image, 'uuid'> & { boundingBox?: IRect; generationMode: InvokeTabName; }; -export declare type ImageUploadResponse = { +export type ImageUploadResponse = { // image: Omit; url: string; mtime: number; @@ -306,33 +305,33 @@ export declare type ImageUploadResponse = { // bbox: [number, number, number, number]; }; -export declare type ErrorResponse = { +export type ErrorResponse = { message: string; additionalData?: string; }; -export declare type GalleryImagesResponse = { +export type GalleryImagesResponse = { images: Array>; areMoreImagesAvailable: boolean; category: GalleryCategory; }; -export declare type ImageDeletedResponse = { +export type ImageDeletedResponse = { uuid: string; url: string; category: GalleryCategory; }; -export declare type ImageUrlResponse = { +export type ImageUrlResponse = { url: string; }; -export declare type UploadImagePayload = { - file: File; - destination?: ImageUploadDestination; -}; +// export type UploadImagePayload = { +// file: File; +// destination?: ImageUploadDestination; +// }; -export declare type UploadOutpaintingMergeImagePayload = { +export type UploadOutpaintingMergeImagePayload = { dataURL: string; name: string; }; @@ -340,7 +339,7 @@ export declare type UploadOutpaintingMergeImagePayload = { /** * A disable-able application feature */ -export declare type AppFeature = +export type AppFeature = | 'faceRestore' | 'upscaling' | 'lightbox' @@ -353,7 +352,7 @@ export declare type AppFeature = /** * A disable-able Stable Diffusion feature */ -export declare type StableDiffusionFeature = +export type StableDiffusionFeature = | 'noiseConfig' | 'variations' | 'symmetry' @@ -364,7 +363,7 @@ export declare type StableDiffusionFeature = * Configuration options for the InvokeAI UI. * Distinct from system settings which may be changed inside the app. */ -export declare type AppConfig = { +export type AppConfig = { /** * Whether or not URLs should be transformed to use a different host */ @@ -428,4 +427,4 @@ export declare type AppConfig = { }; }; -export declare type PartialAppConfig = O.Partial; +export type PartialAppConfig = O.Partial; diff --git a/invokeai/frontend/web/src/exports.tsx b/invokeai/frontend/web/src/exports.tsx deleted file mode 100644 index 617a1fd271..0000000000 --- a/invokeai/frontend/web/src/exports.tsx +++ /dev/null @@ -1,22 +0,0 @@ -// import App from './app/components/App'; - -// import InvokeAiLogoComponent from './features/system/components/InvokeAILogoComponent'; -// import ThemeChanger from './features/system/components/ThemeChanger'; -// import IAIPopover from './common/components/IAIPopover'; -// import IAIIconButton from './common/components/IAIIconButton'; -// import SettingsModal from './features/system/components/SettingsModal/SettingsModal'; -// import StatusIndicator from './features/system/components/StatusIndicator'; -// import ModelSelect from 'features/system/components/ModelSelect'; - -// export default App; -// export { -// InvokeAiLogoComponent, -// ThemeChanger, -// IAIPopover, -// IAIIconButton, -// SettingsModal, -// StatusIndicator, -// ModelSelect, -// }; - -export default {}; diff --git a/invokeai/frontend/web/src/index.ts b/invokeai/frontend/web/src/index.ts new file mode 100644 index 0000000000..274f9d5a0b --- /dev/null +++ b/invokeai/frontend/web/src/index.ts @@ -0,0 +1,9 @@ +export { default as InvokeAiLogoComponent } from './features/system/components/InvokeAILogoComponent'; +export { default as ThemeChanger } from './features/system/components/ThemeChanger'; +export { default as IAIPopover } from './common/components/IAIPopover'; +export { default as IAIIconButton } from './common/components/IAIIconButton'; +export { default as SettingsModal } from './features/system/components/SettingsModal/SettingsModal'; +export { default as StatusIndicator } from './features/system/components/StatusIndicator'; +export { default as ModelSelect } from './features/system/components/ModelSelect'; +export { default as InvokeAIUI } from './app/components/InvokeAIUI'; +export type { PartialAppConfig } from './app/types/invokeai'; diff --git a/invokeai/frontend/web/tsconfig.node.json b/invokeai/frontend/web/tsconfig.node.json index a375708f74..aed3c05590 100644 --- a/invokeai/frontend/web/tsconfig.node.json +++ b/invokeai/frontend/web/tsconfig.node.json @@ -6,5 +6,10 @@ "allowSyntheticDefaultImports": true, "baseUrl": "src" }, - "include": ["vite.config.ts"] + "include": [ + "vite.config.ts", + "./config/vite.app.config.ts", + "./config/vite.package.config.ts", + "./config/vite.common.config.ts" + ] } diff --git a/invokeai/frontend/web/vite.config.ts b/invokeai/frontend/web/vite.config.ts index 2128593f10..a8fc0c39af 100644 --- a/invokeai/frontend/web/vite.config.ts +++ b/invokeai/frontend/web/vite.config.ts @@ -1,82 +1,13 @@ -import react from '@vitejs/plugin-react-swc'; -import { visualizer } from 'rollup-plugin-visualizer'; -import { defineConfig, PluginOption } from 'vite'; -import eslint from 'vite-plugin-eslint'; -import tsconfigPaths from 'vite-tsconfig-paths'; +import { defineConfig } from 'vite'; +import { commonConfig } from './config/vite.common.config'; +import { appConfig } from './config/vite.app.config'; +import { packageConfig } from './config/vite.package.config'; +import { defaultsDeep } from 'lodash'; -// https://vitejs.dev/config/ export default defineConfig(({ mode }) => { - const common = { - base: '', - plugins: [ - react(), - eslint(), - tsconfigPaths(), - visualizer() as unknown as PluginOption, - ], - server: { - // Proxy HTTP requests to the flask server - proxy: { - '/outputs': { - target: 'http://127.0.0.1:9090/outputs', - changeOrigin: true, - rewrite: (path) => path.replace(/^\/outputs/, ''), - }, - '/upload': { - target: 'http://127.0.0.1:9090/upload', - changeOrigin: true, - rewrite: (path) => path.replace(/^\/upload/, ''), - }, - '/flaskwebgui-keep-server-alive': { - target: 'http://127.0.0.1:9090/flaskwebgui-keep-server-alive', - changeOrigin: true, - rewrite: (path) => - path.replace(/^\/flaskwebgui-keep-server-alive/, ''), - }, - // Proxy socket.io to the flask-socketio server - '/socket.io': { - target: 'ws://127.0.0.1:9090', - ws: true, - }, - // Proxy socket.io to the nodes socketio server - '/ws/socket.io': { - target: 'ws://127.0.0.1:9090', - ws: true, - }, - // Proxy openapi schema definiton - '/openapi.json': { - target: 'http://127.0.0.1:9090/openapi.json', - rewrite: (path) => path.replace(/^\/openapi.json/, ''), - changeOrigin: true, - }, - // proxy nodes api - '/api/v1': { - target: 'http://127.0.0.1:9090/api/v1', - rewrite: (path) => path.replace(/^\/api\/v1/, ''), - changeOrigin: true, - }, - }, - }, - build: { - /** - * We need to polyfill for Array.prototype.findLast(); the polyfill plugin above - * overrides any target specified here. - */ - // target: 'esnext', - chunkSizeWarningLimit: 1500, // we don't really care about chunk size, - }, - }; - if (mode == 'development') { - return { - ...common, - build: { - ...common.build, - // sourcemap: true, // this can be enabled if needed, it adds ovwer 15MB to the commit - }, - }; - } else { - return { - ...common, - }; + if (mode === 'package') { + return defaultsDeep(packageConfig, commonConfig); } + + return defaultsDeep(appConfig, commonConfig); }); diff --git a/invokeai/frontend/web/yarn.lock b/invokeai/frontend/web/yarn.lock index 1e9bff0197..1a003eecc2 100644 --- a/invokeai/frontend/web/yarn.lock +++ b/invokeai/frontend/web/yarn.lock @@ -1252,7 +1252,7 @@ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== -"@jridgewell/sourcemap-codec@^1.4.10": +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.13": version "1.4.15" resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== @@ -1278,6 +1278,48 @@ resolved "https://registry.yarnpkg.com/@jsdevtools/ono/-/ono-7.1.3.tgz#9df03bbd7c696a5c58885c34aa06da41c8543796" integrity sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg== +"@microsoft/api-extractor-model@7.26.5": + version "7.26.5" + resolved "https://registry.yarnpkg.com/@microsoft/api-extractor-model/-/api-extractor-model-7.26.5.tgz#b3d0939b4dab6897ce27c966bd394a582f1871e7" + integrity sha512-sv1dF9B3AeMURTW0xubvmrX/tLFe2bpmHJBXKiqfOl2YOoLNjreIqmPHPe1vDSq9MDxAJLqvyurjOf87abVJBQ== + dependencies: + "@microsoft/tsdoc" "0.14.2" + "@microsoft/tsdoc-config" "~0.16.1" + "@rushstack/node-core-library" "3.56.0" + +"@microsoft/api-extractor@^7.34.4": + version "7.34.5" + resolved "https://registry.yarnpkg.com/@microsoft/api-extractor/-/api-extractor-7.34.5.tgz#06ee82834a7ccdc104b096cc44ef74d877b68d07" + integrity sha512-0CUMSHvJ3Tq7ZJg09vn3kwvZN41k6dbe4zcPrDpZwQKh/dXIL5oQ7hbrbrASBDlE5DSPHs+7iGYa9FGGdgyrCA== + dependencies: + "@microsoft/api-extractor-model" "7.26.5" + "@microsoft/tsdoc" "0.14.2" + "@microsoft/tsdoc-config" "~0.16.1" + "@rushstack/node-core-library" "3.56.0" + "@rushstack/rig-package" "0.3.18" + "@rushstack/ts-command-line" "4.13.2" + colors "~1.2.1" + lodash "~4.17.15" + resolve "~1.22.1" + semver "~7.3.0" + source-map "~0.6.1" + typescript "~4.8.4" + +"@microsoft/tsdoc-config@~0.16.1": + version "0.16.2" + resolved "https://registry.yarnpkg.com/@microsoft/tsdoc-config/-/tsdoc-config-0.16.2.tgz#b786bb4ead00d54f53839a458ce626c8548d3adf" + integrity sha512-OGiIzzoBLgWWR0UdRJX98oYO+XKGf7tiK4Zk6tQ/E4IJqGCe7dvkTvgDZV5cFJUzLGDOjeAXrnZoA6QkVySuxw== + dependencies: + "@microsoft/tsdoc" "0.14.2" + ajv "~6.12.6" + jju "~1.4.0" + resolve "~1.19.0" + +"@microsoft/tsdoc@0.14.2": + version "0.14.2" + resolved "https://registry.yarnpkg.com/@microsoft/tsdoc/-/tsdoc-0.14.2.tgz#c3ec604a0b54b9a9b87e9735dfc59e1a5da6a5fb" + integrity sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug== + "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" @@ -1387,6 +1429,46 @@ estree-walker "^2.0.1" picomatch "^2.2.2" +"@rollup/pluginutils@^5.0.2": + version "5.0.2" + resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-5.0.2.tgz#012b8f53c71e4f6f9cb317e311df1404f56e7a33" + integrity sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA== + dependencies: + "@types/estree" "^1.0.0" + estree-walker "^2.0.2" + picomatch "^2.3.1" + +"@rushstack/node-core-library@3.56.0", "@rushstack/node-core-library@^3.55.2": + version "3.56.0" + resolved "https://registry.yarnpkg.com/@rushstack/node-core-library/-/node-core-library-3.56.0.tgz#61136eaeac442194822fc075c63fee426019896d" + integrity sha512-HyaRfgL77I8y6HCFYkLnAUWjsniDrIHlomic570TJ/ehd+pOdrRr95APAYGFw+nVwXE4qyEUTyYMWxsOnV14VA== + dependencies: + colors "~1.2.1" + fs-extra "~7.0.1" + import-lazy "~4.0.0" + jju "~1.4.0" + resolve "~1.22.1" + semver "~7.3.0" + z-schema "~5.0.2" + +"@rushstack/rig-package@0.3.18": + version "0.3.18" + resolved "https://registry.yarnpkg.com/@rushstack/rig-package/-/rig-package-0.3.18.tgz#2b59eb8ed482e8cd6ad8d396414bf3200efdd682" + integrity sha512-SGEwNTwNq9bI3pkdd01yCaH+gAsHqs0uxfGvtw9b0LJXH52qooWXnrFTRRLG1aL9pf+M2CARdrA9HLHJys3jiQ== + dependencies: + resolve "~1.22.1" + strip-json-comments "~3.1.1" + +"@rushstack/ts-command-line@4.13.2": + version "4.13.2" + resolved "https://registry.yarnpkg.com/@rushstack/ts-command-line/-/ts-command-line-4.13.2.tgz#2dfdcf418d58256671433b1da4a3b67e1814cc7a" + integrity sha512-bCU8qoL9HyWiciltfzg7GqdfODUeda/JpI0602kbN5YH22rzTxyqYvv7aRLENCM7XCQ1VRs7nMkEqgJUOU8Sag== + dependencies: + "@types/argparse" "1.0.38" + argparse "~1.0.9" + colors "~1.2.1" + string-argv "~0.3.1" + "@sindresorhus/is@^0.14.0": version "0.14.0" resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" @@ -1470,6 +1552,16 @@ dependencies: defer-to-connect "^1.0.1" +"@ts-morph/common@~0.19.0": + version "0.19.0" + resolved "https://registry.yarnpkg.com/@ts-morph/common/-/common-0.19.0.tgz#927fcd81d1bbc09c89c4a310a84577fb55f3694e" + integrity sha512-Unz/WHmd4pGax91rdIKWi51wnVUW11QttMEPpBiBgIewnc9UQIX7UDLxr5vRlqeByXCwhkF6VabSsI0raWcyAQ== + dependencies: + fast-glob "^3.2.12" + minimatch "^7.4.3" + mkdirp "^2.1.6" + path-browserify "^1.0.1" + "@tsconfig/node10@^1.0.7": version "1.0.9" resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2" @@ -1490,6 +1582,11 @@ resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.3.tgz#472eaab5f15c1ffdd7f8628bd4c4f753995ec79e" integrity sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ== +"@types/argparse@1.0.38": + version "1.0.38" + resolved "https://registry.yarnpkg.com/@types/argparse/-/argparse-1.0.38.tgz#a81fd8606d481f873a3800c6ebae4f1d768a56a9" + integrity sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA== + "@types/d3-array@*": version "3.0.4" resolved "https://registry.yarnpkg.com/@types/d3-array/-/d3-array-3.0.4.tgz#44eebe40be57476cad6a0cd6a85b0f57d54185a2" @@ -1713,7 +1810,7 @@ "@types/estree" "*" "@types/json-schema" "*" -"@types/estree@*": +"@types/estree@*", "@types/estree@^1.0.0": version "1.0.1" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.1.tgz#aa22750962f3bf0e79d753d3cc067f010c95f194" integrity sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA== @@ -1753,6 +1850,11 @@ resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.194.tgz#b71eb6f7a0ff11bff59fc987134a093029258a76" integrity sha512-r22s9tAS7imvBt2lyHC9B8AGwWnXaYb1tY09oyLkXDs4vArpYJzw09nj8MLx5VfciBPGIb+ZwG0ssYnEPJxn/g== +"@types/node@^18.16.2": + version "18.16.2" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.16.2.tgz#2f610ea71034b3971c312192377f8a7178eb57f1" + integrity sha512-GQW/JL/5Fz/0I8RpeBG9lKp0+aNcXEaVL71c0D2Q0QHDTFvlYKT7an0onCUXj85anv7b4/WesqdfchLc0jtsCg== + "@types/parse-json@^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" @@ -1968,7 +2070,7 @@ aggregate-error@^3.0.0: clean-stack "^2.0.0" indent-string "^4.0.0" -ajv@^6.10.0, ajv@^6.12.4: +ajv@^6.10.0, ajv@^6.12.4, ajv@~6.12.6: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -2049,6 +2151,13 @@ argparse@^2.0.1: resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== +argparse@~1.0.9: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + aria-hidden@^1.2.2: version "1.2.3" resolved "https://registry.yarnpkg.com/aria-hidden/-/aria-hidden-1.2.3.tgz#14aeb7fb692bbb72d69bebfa47279c1fd725e954" @@ -2213,6 +2322,13 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" +brace-expansion@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" + integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + dependencies: + balanced-match "^1.0.0" + braces@^3.0.2, braces@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" @@ -2430,6 +2546,11 @@ clone@^1.0.2: resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg== +code-block-writer@^12.0.0: + version "12.0.0" + resolved "https://registry.yarnpkg.com/code-block-writer/-/code-block-writer-12.0.0.tgz#4dd58946eb4234105aff7f0035977b2afdc2a770" + integrity sha512-q4dMFMlXtKR3XNBHyMHt/3pwYNA69EDk00lloMOaaUMKPUXBw6lpXtbu3MMVG6/uOihGnRDOlkyqsONEUj60+w== + color-convert@^1.9.0: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" @@ -2464,6 +2585,11 @@ colorette@^2.0.19: resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== +colors@~1.2.1: + version "1.2.5" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.2.5.tgz#89c7ad9a374bc030df8013241f68136ed8835afc" + integrity sha512-erNRLao/Y3Fv54qUa0LBB+//Uf3YwMUmdJinN20yMXm9zdKKqH9wt7R9IIVZ+K7ShzfpLV/Zg8+VyrBJYB4lpg== + combined-stream@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" @@ -3258,7 +3384,7 @@ estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0: resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== -estree-walker@^2.0.1: +estree-walker@^2.0.1, estree-walker@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== @@ -3293,7 +3419,7 @@ fast-diff@^1.1.2: resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== -fast-glob@^3.2.9: +fast-glob@^3.2.12, fast-glob@^3.2.9: version "3.2.12" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w== @@ -3456,6 +3582,15 @@ framesync@6.1.2: dependencies: tslib "2.4.0" +fs-extra@^10.1.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" + integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + fs-extra@^11.1.1: version "11.1.1" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.1.1.tgz#da69f7c39f3b002378b0954bb6ae7efdc0876e2d" @@ -3475,6 +3610,15 @@ fs-extra@^9.0.0: jsonfile "^6.0.1" universalify "^2.0.0" +fs-extra@~7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" + integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== + dependencies: + graceful-fs "^4.1.2" + jsonfile "^4.0.0" + universalify "^0.1.0" + fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -3823,6 +3967,11 @@ import-lazy@^2.1.0: resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" integrity sha512-m7ZEHgtw69qOGw+jwxXkHlrlIPdTGkyh66zXZ1ajZbxkDBNjSY/LGbmjc7h0s2ELsUDTAhFr55TrPSSqJGPG0A== +import-lazy@~4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-4.0.0.tgz#e8eb627483a0a43da3c03f3e35548be5cb0cc153" + integrity sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw== + imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" @@ -3925,7 +4074,7 @@ is-ci@^2.0.0: dependencies: ci-info "^2.0.0" -is-core-module@^2.11.0, is-core-module@^2.9.0: +is-core-module@^2.1.0, is-core-module@^2.11.0, is-core-module@^2.9.0: version "2.12.0" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.12.0.tgz#36ad62f6f73c8253fd6472517a12483cf03e7ec4" integrity sha512-RECHCBCd/viahWmwj6enj19sKbHfJrddi/6cBDsNTKbNq0f7VeaUkBo60BqzvPqo/W54ChS62Z5qyun7cfOMqQ== @@ -4148,6 +4297,11 @@ its-fine@^1.0.6: dependencies: "@types/react-reconciler" "^0.28.0" +jju@~1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/jju/-/jju-1.4.0.tgz#a3abe2718af241a2b2904f84a625970f389ae32a" + integrity sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA== + js-sdsl@^4.1.4: version "4.4.0" resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.4.0.tgz#8b437dbe642daa95760400b602378ed8ffea8430" @@ -4204,6 +4358,13 @@ json5@^2.2.2: resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== +jsonfile@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" + integrity sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg== + optionalDependencies: + graceful-fs "^4.1.6" + jsonfile@^6.0.1: version "6.1.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" @@ -4235,6 +4396,11 @@ klaw-sync@^6.0.0: dependencies: graceful-fs "^4.1.11" +kolorist@^1.7.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/kolorist/-/kolorist-1.8.0.tgz#edddbbbc7894bc13302cdf740af6374d4a04743c" + integrity sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ== + konva@^9.0.1: version "9.0.1" resolved "https://registry.yarnpkg.com/konva/-/konva-9.0.1.tgz#92b4171beaa94273b108bd87b08c4d3e51a0da22" @@ -4318,6 +4484,16 @@ lodash-es@^4.17.21: resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee" integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw== +lodash.get@^4.4.2: + version "4.4.2" + resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" + integrity sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ== + +lodash.isequal@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" + integrity sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ== + lodash.merge@^4.6.2: version "4.6.2" resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" @@ -4333,7 +4509,7 @@ lodash.throttle@^4.1.1: resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4" integrity sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ== -lodash@^4.17.21: +lodash@^4.17.21, lodash@~4.17.15: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -4416,6 +4592,13 @@ madge@^6.0.0: typescript "^3.9.5" walkdir "^0.4.1" +magic-string@^0.29.0: + version "0.29.0" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.29.0.tgz#f034f79f8c43dba4ae1730ffb5e8c4e084b16cf3" + integrity sha512-WcfidHrDjMY+eLjlU+8OvwREqHwpgCeKVBUpQ3OhYYuvfaYCUgcbuBzappNzZvg/v8onU3oQj+BYpkOJe9Iw4Q== + dependencies: + "@jridgewell/sourcemap-codec" "^1.4.13" + make-dir@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" @@ -4480,11 +4663,23 @@ minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: dependencies: brace-expansion "^1.1.7" +minimatch@^7.4.3: + version "7.4.6" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-7.4.6.tgz#845d6f254d8f4a5e4fd6baf44d5f10c8448365fb" + integrity sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw== + dependencies: + brace-expansion "^2.0.1" + minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6: version "1.2.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== +mkdirp@^2.1.6: + version "2.1.6" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-2.1.6.tgz#964fbcb12b2d8c5d6fbc62a963ac95a273e2cc19" + integrity sha512-+hEnITedc8LAtIP9u3HJDFIdcLV2vXP33sqLLIzkv1Db1zO/1OxbvYf0Y1OC/S/Qo5dxHXepofhmxL02PsKe+A== + module-definition@^3.3.1: version "3.4.0" resolved "https://registry.yarnpkg.com/module-definition/-/module-definition-3.4.0.tgz#953a3861f65df5e43e80487df98bb35b70614c2b" @@ -4811,6 +5006,11 @@ patch-package@^7.0.0: tmp "^0.0.33" yaml "^2.2.2" +path-browserify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd" + integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g== + path-exists@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" @@ -4831,7 +5031,7 @@ path-key@^4.0.0: resolved "https://registry.yarnpkg.com/path-key/-/path-key-4.0.0.tgz#295588dc3aee64154f877adb9d780b81c554bf18" integrity sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ== -path-parse@^1.0.7: +path-parse@^1.0.6, path-parse@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== @@ -5306,7 +5506,7 @@ resolve-from@^4.0.0: resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== -resolve@^1.19.0, resolve@^1.21.0: +resolve@^1.19.0, resolve@^1.21.0, resolve@~1.22.1: version "1.22.2" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.2.tgz#0ed0943d4e301867955766c9f3e1ae6d01c6845f" integrity sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g== @@ -5324,6 +5524,14 @@ resolve@^2.0.0-next.4: path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" +resolve@~1.19.0: + version "1.19.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.19.0.tgz#1af5bf630409734a067cae29318aac7fa29a267c" + integrity sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg== + dependencies: + is-core-module "^2.1.0" + path-parse "^1.0.6" + responselike@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" @@ -5453,6 +5661,13 @@ semver@^7.3.4, semver@^7.3.5, semver@^7.3.7: dependencies: lru-cache "^6.0.0" +semver@~7.3.0: + version "7.3.8" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798" + integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A== + dependencies: + lru-cache "^6.0.0" + shebang-command@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" @@ -5571,6 +5786,11 @@ spawn-command@0.0.2-1: resolved "https://registry.yarnpkg.com/spawn-command/-/spawn-command-0.0.2-1.tgz#62f5e9466981c1b796dc5929937e11c9c6921bd0" integrity sha512-n98l9E2RMSJ9ON1AKisHzz7V42VDiBQGY6PB1BwRglz99wpVsSuGzQ+jOi6lFXBGVTCrRpltvjm+/XA+tpeJrg== +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== + stream-to-array@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/stream-to-array/-/stream-to-array-2.3.0.tgz#bbf6b39f5f43ec30bc71babcb37557acecf34353" @@ -5578,7 +5798,7 @@ stream-to-array@^2.3.0: dependencies: any-promise "^1.1.0" -string-argv@^0.3.1: +string-argv@^0.3.1, string-argv@~0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.1.tgz#95e2fbec0427ae19184935f816d74aaa4c5c19da" integrity sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg== @@ -5682,7 +5902,7 @@ strip-final-newline@^3.0.0: resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-3.0.0.tgz#52894c313fbff318835280aed60ff71ebf12b8fd" integrity sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw== -strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: +strip-json-comments@^3.1.0, strip-json-comments@^3.1.1, strip-json-comments@~3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== @@ -5810,6 +6030,14 @@ ts-graphviz@^1.5.0: resolved "https://registry.yarnpkg.com/ts-graphviz/-/ts-graphviz-1.6.1.tgz#f44525c048cb8c8c188b7324d2a91015fd31ceaf" integrity sha512-9aZKR7hoQAHXlgb7HvUND3y5VhEI5PMNVv/BfelPXebcsxdwZhBYbM8XpnV4NfiHV9O0/sAI9sQVuce0gogzlA== +ts-morph@18.0.0: + version "18.0.0" + resolved "https://registry.yarnpkg.com/ts-morph/-/ts-morph-18.0.0.tgz#b9e7a898ea115064585a8a775d86da6edc9c5b4e" + integrity sha512-Kg5u0mk19PIIe4islUI/HWRvm9bC1lHejK4S0oh1zaZ77TMZAEmQC0sHQYiu2RgCQFZKXz1fMVi/7nOOeirznA== + dependencies: + "@ts-morph/common" "~0.19.0" + code-block-writer "^12.0.0" + ts-node@^10.7.0: version "10.9.1" resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.1.tgz#e73de9102958af9e1f0b168a6ff320e25adcff4b" @@ -5930,6 +6158,11 @@ typescript@^4.0.0, typescript@^4.9.5: resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== +typescript@~4.8.4: + version "4.8.4" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.8.4.tgz#c464abca159669597be5f96b8943500b238e60e6" + integrity sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ== + uglify-js@^3.1.4: version "3.17.4" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.17.4.tgz#61678cf5fa3f5b7eb789bb345df29afb8257c22c" @@ -5957,6 +6190,11 @@ unique-string@^2.0.0: dependencies: crypto-random-string "^2.0.0" +universalify@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" + integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== + universalify@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" @@ -6036,6 +6274,27 @@ v8-compile-cache-lib@^3.0.1: resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== +validator@^13.7.0: + version "13.9.0" + resolved "https://registry.yarnpkg.com/validator/-/validator-13.9.0.tgz#33e7b85b604f3bbce9bb1a05d5c3e22e1c2ff855" + integrity sha512-B+dGG8U3fdtM0/aNK4/X8CXq/EcxU2WPrPEkJGslb47qyHsxmbggTWK0yEA4qnYVNF+nxNlN88o14hIcPmSIEA== + +vite-plugin-dts@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/vite-plugin-dts/-/vite-plugin-dts-2.3.0.tgz#6ab2edf56f48261bfede03958704bfaee2fca3e4" + integrity sha512-WbJgGtsStgQhdm3EosYmIdTGbag5YQpZ3HXWUAPCDyoXI5qN6EY0V7NXq0lAmnv9hVQsvh0htbYcg0Or5Db9JQ== + dependencies: + "@babel/parser" "^7.21.4" + "@microsoft/api-extractor" "^7.34.4" + "@rollup/pluginutils" "^5.0.2" + "@rushstack/node-core-library" "^3.55.2" + debug "^4.3.4" + fast-glob "^3.2.12" + fs-extra "^10.1.0" + kolorist "^1.7.0" + magic-string "^0.29.0" + ts-morph "18.0.0" + vite-plugin-eslint@^1.8.1: version "1.8.1" resolved "https://registry.yarnpkg.com/vite-plugin-eslint/-/vite-plugin-eslint-1.8.1.tgz#0381b8272e7f0fd8b663311b64f7608d55d8b04c" @@ -6243,6 +6502,17 @@ yocto-queue@^0.1.0: resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== +z-schema@~5.0.2: + version "5.0.6" + resolved "https://registry.yarnpkg.com/z-schema/-/z-schema-5.0.6.tgz#46d6a687b15e4a4369e18d6cb1c7b8618fc256c5" + integrity sha512-+XR1GhnWklYdfr8YaZv/iu+vY+ux7V5DS5zH1DQf6bO5ufrt/5cgNhVO5qyhsjFXvsqQb/f08DWE9b6uPscyAg== + dependencies: + lodash.get "^4.4.2" + lodash.isequal "^4.5.0" + validator "^13.7.0" + optionalDependencies: + commander "^10.0.0" + zustand@^4.3.1: version "4.3.7" resolved "https://registry.yarnpkg.com/zustand/-/zustand-4.3.7.tgz#501b1f0393a7f1d103332e45ab574be5747fedce" From ee881e4c7897cb8fc31ee3df0bf0f8cde58afab8 Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Fri, 28 Apr 2023 21:24:35 +1000 Subject: [PATCH 20/68] build(ui): add react/react-dom peer deps --- invokeai/frontend/web/package.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/invokeai/frontend/web/package.json b/invokeai/frontend/web/package.json index 9932fb3ad3..4be29d1c25 100644 --- a/invokeai/frontend/web/package.json +++ b/invokeai/frontend/web/package.json @@ -95,6 +95,10 @@ "use-image": "^1.1.0", "uuid": "^9.0.0" }, + "peerDependencies": { + "react": "^18.2.0", + "react-dom": "^18.2.0" + }, "devDependencies": { "@types/dateformat": "^5.0.0", "@types/lodash": "^4.14.194", From a591184d2ade467f6d05a9e1e54c278104d4c203 Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Fri, 28 Apr 2023 21:25:05 +1000 Subject: [PATCH 21/68] build(ui): remove unneeded types file --- invokeai/frontend/web/index.d.ts | 96 -------------------------------- 1 file changed, 96 deletions(-) delete mode 100644 invokeai/frontend/web/index.d.ts diff --git a/invokeai/frontend/web/index.d.ts b/invokeai/frontend/web/index.d.ts deleted file mode 100644 index 72b3e139de..0000000000 --- a/invokeai/frontend/web/index.d.ts +++ /dev/null @@ -1,96 +0,0 @@ -import React, { PropsWithChildren } from 'react'; -import { IAIPopoverProps } from '../web/src/common/components/IAIPopover'; -import { IAIIconButtonProps } from '../web/src/common/components/IAIIconButton'; -import { InvokeTabName } from 'features/ui/store/tabMap'; -import { PartialAppConfig } from 'app/types/invokeai'; - -export {}; - -declare module 'redux-socket.io-middleware'; - -declare global { - /* eslint-disable @typescript-eslint/no-explicit-any */ - interface Array { - /** - * Returns the value of the last element in the array where predicate is true, and undefined - * otherwise. - * @param predicate findLast calls predicate once for each element of the array, in descending - * order, until it finds one where predicate returns true. If such an element is found, findLast - * immediately returns that element value. Otherwise, findLast returns undefined. - * @param thisArg If provided, it will be used as the this value for each invocation of - * predicate. If it is not provided, undefined is used instead. - */ - findLast( - predicate: (value: T, index: number, array: T[]) => value is S, - thisArg?: any - ): S | undefined; - findLast( - predicate: (value: T, index: number, array: T[]) => unknown, - thisArg?: any - ): T | undefined; - - /** - * Returns the index of the last element in the array where predicate is true, and -1 - * otherwise. - * @param predicate findLastIndex calls predicate once for each element of the array, in descending - * order, until it finds one where predicate returns true. If such an element is found, - * findLastIndex immediately returns that element index. Otherwise, findLastIndex returns -1. - * @param thisArg If provided, it will be used as the this value for each invocation of - * predicate. If it is not provided, undefined is used instead. - */ - findLastIndex( - predicate: (value: T, index: number, array: T[]) => unknown, - thisArg?: any - ): number; - } - /* eslint-enable @typescript-eslint/no-explicit-any */ -} - -declare module '@invoke-ai/invoke-ai-ui' { - declare class ThemeChanger extends React.Component { - public constructor(props: ThemeChangerProps); - } - - declare class InvokeAiLogoComponent extends React.Component { - public constructor(props: InvokeAILogoComponentProps); - } - - declare class IAIPopover extends React.Component { - public constructor(props: IAIPopoverProps); - } - - declare class IAIIconButton extends React.Component { - public constructor(props: IAIIconButtonProps); - } - - declare class SettingsModal extends React.Component { - public constructor(props: SettingsModalProps); - } - - declare class StatusIndicator extends React.Component { - public constructor(props: StatusIndicatorProps); - } - - declare class ModelSelect extends React.Component { - public constructor(props: ModelSelectProps); - } -} - -interface InvokeProps extends PropsWithChildren { - apiUrl?: string; - token?: string; - config?: PartialAppConfig; -} - -declare function Invoke(props: InvokeProps): JSX.Element; - -export { - ThemeChanger, - InvokeAiLogoComponent, - IAIPopover, - IAIIconButton, - SettingsModal, - StatusIndicator, - ModelSelect, -}; -export = Invoke; From d92d5b525875d4b403e143d689ee7e687b832f2b Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Fri, 28 Apr 2023 21:25:25 +1000 Subject: [PATCH 22/68] build(ui): fix types exports --- invokeai/frontend/web/config/vite.app.config.ts | 3 --- invokeai/frontend/web/config/vite.common.config.ts | 6 +----- .../frontend/web/config/vite.package.config.ts | 14 ++++++++++++-- invokeai/frontend/web/tsconfig.json | 11 +++++++---- invokeai/frontend/web/tsconfig.node.json | 3 +-- 5 files changed, 21 insertions(+), 16 deletions(-) diff --git a/invokeai/frontend/web/config/vite.app.config.ts b/invokeai/frontend/web/config/vite.app.config.ts index e6725e98c8..9897b28118 100644 --- a/invokeai/frontend/web/config/vite.app.config.ts +++ b/invokeai/frontend/web/config/vite.app.config.ts @@ -11,7 +11,4 @@ export const appConfig: UserConfig = { tsconfigPaths(), visualizer() as unknown as PluginOption, ], - build: { - chunkSizeWarningLimit: 1500, - }, }; diff --git a/invokeai/frontend/web/config/vite.common.config.ts b/invokeai/frontend/web/config/vite.common.config.ts index dbd8ae4b8d..8955a5a3d0 100644 --- a/invokeai/frontend/web/config/vite.common.config.ts +++ b/invokeai/frontend/web/config/vite.common.config.ts @@ -1,8 +1,4 @@ -import react from '@vitejs/plugin-react-swc'; -import { visualizer } from 'rollup-plugin-visualizer'; -import { PluginOption, UserConfig } from 'vite'; -import eslint from 'vite-plugin-eslint'; -import tsconfigPaths from 'vite-tsconfig-paths'; +import { UserConfig } from 'vite'; export const commonConfig: UserConfig = { base: './', diff --git a/invokeai/frontend/web/config/vite.package.config.ts b/invokeai/frontend/web/config/vite.package.config.ts index 906af84887..d4b902d54b 100644 --- a/invokeai/frontend/web/config/vite.package.config.ts +++ b/invokeai/frontend/web/config/vite.package.config.ts @@ -17,19 +17,29 @@ export const packageConfig: UserConfig = { }), ], build: { - chunkSizeWarningLimit: 1500, lib: { entry: path.resolve(__dirname, '../src/index.ts'), name: 'InvokeAIUI', fileName: (format) => `invoke-ai-ui.${format}.js`, }, rollupOptions: { - external: ['react', 'react-dom'], + external: ['react', 'react-dom', '@emotion/react'], output: { globals: { react: 'React', + 'react-dom': 'ReactDOM', }, }, }, }, + resolve: { + alias: { + app: path.resolve(__dirname, '../src/app'), + assets: path.resolve(__dirname, '../src/assets'), + common: path.resolve(__dirname, '../src/common'), + features: path.resolve(__dirname, '../src/features'), + services: path.resolve(__dirname, '../src/services'), + theme: path.resolve(__dirname, '../src/theme'), + }, + }, }; diff --git a/invokeai/frontend/web/tsconfig.json b/invokeai/frontend/web/tsconfig.json index 9731a64d3d..8276f461eb 100644 --- a/invokeai/frontend/web/tsconfig.json +++ b/invokeai/frontend/web/tsconfig.json @@ -14,10 +14,13 @@ "resolveJsonModule": true, "isolatedModules": true, "noEmit": true, - "baseUrl": "src", - "jsx": "react-jsx" + "jsx": "react-jsx", + "baseUrl": "./", + "paths": { + "*": ["./src/*"] + } }, - "include": ["src", "index.d.ts"], - "exclude": ["src/services/fixtures/*"], + "include": ["src/**/*.ts", "src/**/*.tsx", "*.d.ts"], + "exclude": ["src/services/fixtures/*", "node_modules", "dist"], "references": [{ "path": "./tsconfig.node.json" }] } diff --git a/invokeai/frontend/web/tsconfig.node.json b/invokeai/frontend/web/tsconfig.node.json index aed3c05590..4b04192240 100644 --- a/invokeai/frontend/web/tsconfig.node.json +++ b/invokeai/frontend/web/tsconfig.node.json @@ -3,8 +3,7 @@ "composite": true, "module": "ESNext", "moduleResolution": "Node", - "allowSyntheticDefaultImports": true, - "baseUrl": "src" + "allowSyntheticDefaultImports": true }, "include": [ "vite.config.ts", From 2b5ccdc55f80e6ae8d531952f0b37c4b1fdc6829 Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Fri, 28 Apr 2023 21:46:58 +1000 Subject: [PATCH 23/68] build(ui): treeshake lodash via lodash-es --- .../frontend/web/config/vite.app.config.ts | 26 ++ .../frontend/web/config/vite.common.config.ts | 50 ---- .../web/config/vite.package.config.ts | 4 +- invokeai/frontend/web/package.json | 4 +- .../src/app/selectors/readinessSelector.ts | 2 +- .../src/common/components/IAINumberInput.tsx | 2 +- .../web/src/common/components/IAISlider.tsx | 2 +- .../web/src/common/hooks/useGlobalHotkeys.ts | 2 +- .../web/src/common/util/parseMetadata.ts | 2 +- .../features/canvas/components/IAICanvas.tsx | 2 +- .../IAICanvasBoundingBoxOverlay.tsx | 2 +- .../canvas/components/IAICanvasGrid.tsx | 2 +- .../components/IAICanvasIntermediateImage.tsx | 2 +- .../components/IAICanvasMaskCompositer.tsx | 2 +- .../canvas/components/IAICanvasMaskLines.tsx | 2 +- .../components/IAICanvasObjectRenderer.tsx | 2 +- .../components/IAICanvasStagingArea.tsx | 2 +- .../IAICanvasStagingAreaToolbar.tsx | 2 +- .../canvas/components/IAICanvasStatusText.tsx | 2 +- .../IAICanvasStatusTextCursorPos.tsx | 2 +- .../components/IAICanvasToolPreview.tsx | 2 +- .../IAICanvasToolbar/IAICanvasBoundingBox.tsx | 2 +- .../IAICanvasToolbar/IAICanvasMaskOptions.tsx | 2 +- .../IAICanvasToolbar/IAICanvasRedoButton.tsx | 2 +- .../IAICanvasSettingsButtonPopover.tsx | 2 +- .../IAICanvasToolChooserOptions.tsx | 2 +- .../IAICanvasToolbar/IAICanvasToolbar.tsx | 2 +- .../IAICanvasToolbar/IAICanvasUndoButton.tsx | 2 +- .../canvas/hooks/useCanvasDragMove.ts | 2 +- .../features/canvas/hooks/useCanvasHotkeys.ts | 2 +- .../canvas/hooks/useCanvasMouseDown.ts | 2 +- .../canvas/hooks/useCanvasMouseMove.ts | 2 +- .../features/canvas/hooks/useCanvasMouseUp.ts | 2 +- .../features/canvas/hooks/useCanvasZoom.ts | 2 +- .../src/features/canvas/store/canvasSlice.ts | 2 +- .../canvas/store/thunks/requestCanvasScale.ts | 2 +- .../components/CurrentImageButtons.tsx | 2 +- .../components/CurrentImageDisplay.tsx | 2 +- .../components/CurrentImagePreview.tsx | 2 +- .../gallery/components/DeleteImageModal.tsx | 2 +- .../gallery/components/HoverableImage.tsx | 77 +++--- .../gallery/components/ImageGallery.tsx | 2 +- .../gallery/components/ImageGalleryPanel.tsx | 2 +- .../components/NextPrevImageButtons.tsx | 2 +- .../gallery/store/gallerySelectors.ts | 2 +- .../features/gallery/store/gallerySlice.ts | 2 +- .../features/lightbox/components/Lightbox.tsx | 2 +- .../lightbox/store/lightboxSelectors.ts | 2 +- .../features/nodes/components/AddNodeMenu.tsx | 2 +- .../nodes/components/FieldTypeLegend.tsx | 2 +- .../components/IAINode/IAINodeInputs.tsx | 2 +- .../components/IAINode/IAINodeOutputs.tsx | 2 +- .../fields/ModelInputFieldComponent.tsx | 2 +- .../nodes/components/search/NodeSearch.tsx | 2 +- .../nodes/hooks/useBuildInvocation.ts | 2 +- .../nodes/hooks/useIsValidConnection.ts | 118 ++++----- .../nodes/util/fieldTemplateBuilders.ts | 2 +- .../util/nodesGraphBuilder/buildNodesGraph.ts | 2 +- .../src/features/nodes/util/parseSchema.ts | 2 +- .../BoundingBox/BoundingBoxSettings.tsx | 2 +- .../Canvas/InfillAndScalingSettings.tsx | 2 +- .../ImageToImage/ImageToImageSettings.tsx | 2 +- .../ImageToImage/InitialImagePreview.tsx | 2 +- .../Output/HiresSettings.tsx | 2 +- .../components/ParametersAccordion.tsx | 2 +- .../ProcessButtons/CancelButton.tsx | 4 +- .../ProcessButtons/ProcessButtons.tsx | 2 +- .../components/PromptInput/PromptInput.tsx | 2 +- .../parameters/store/generationSelectors.ts | 2 +- .../parameters/store/generationSlice.ts | 238 +++++++++--------- .../features/system/components/Console.tsx | 2 +- .../ModelManager/CheckpointModelEdit.tsx | 2 +- .../ModelManager/DiffusersModelEdit.tsx | 2 +- .../components/ModelManager/ModelList.tsx | 2 +- .../components/ModelManager/SearchModels.tsx | 2 +- .../system/components/ModelSelect.tsx | 2 +- .../system/components/ProgressBar.tsx | 2 +- .../SettingsModal/SettingsModal.tsx | 2 +- .../system/components/StatusIndicator.tsx | 2 +- .../src/features/system/store/configSlice.ts | 2 +- .../features/system/store/modelSelectors.ts | 2 +- .../src/features/system/store/modelSlice.ts | 2 +- .../features/system/store/systemSelectors.ts | 2 +- .../ui/components/FloatingGalleryButton.tsx | 2 +- .../FloatingParametersPanelButtons.tsx | 2 +- .../features/ui/components/InvokeWorkarea.tsx | 2 +- .../ui/components/ParametersPanel.tsx | 2 +- .../ui/components/common/ParametersSlide.tsx | 2 +- .../ui/components/common/Scrollable.tsx | 2 +- .../tabs/Generate/GenerateParameters.tsx | 2 +- .../UnifiedCanvasContentBeta.tsx | 2 +- .../UnifiedCanvasColorPicker.tsx | 2 +- .../UnifiedCanvasSettings.tsx | 2 +- .../UnifiedCanvasToolSettingsBeta.tsx | 2 +- .../UnifiedCanvasLayerSelect.tsx | 2 +- .../UnifiedCanvasToolSelect.tsx | 2 +- .../UnifiedCanvas/UnifiedCanvasContent.tsx | 2 +- .../web/src/features/ui/store/uiSelectors.ts | 2 +- .../frontend/web/src/services/thunks/image.ts | 2 +- .../frontend/web/src/services/thunks/model.ts | 2 +- invokeai/frontend/web/vite.config.ts | 6 +- invokeai/frontend/web/yarn.lock | 55 ++-- 102 files changed, 370 insertions(+), 396 deletions(-) delete mode 100644 invokeai/frontend/web/config/vite.common.config.ts diff --git a/invokeai/frontend/web/config/vite.app.config.ts b/invokeai/frontend/web/config/vite.app.config.ts index 9897b28118..e6c4df79fd 100644 --- a/invokeai/frontend/web/config/vite.app.config.ts +++ b/invokeai/frontend/web/config/vite.app.config.ts @@ -5,10 +5,36 @@ import eslint from 'vite-plugin-eslint'; import tsconfigPaths from 'vite-tsconfig-paths'; export const appConfig: UserConfig = { + base: './', plugins: [ react(), eslint(), tsconfigPaths(), visualizer() as unknown as PluginOption, ], + build: { + chunkSizeWarningLimit: 1500, + }, + server: { + // Proxy HTTP requests to the flask server + proxy: { + // Proxy socket.io to the nodes socketio server + '/ws/socket.io': { + target: 'ws://127.0.0.1:9090', + ws: true, + }, + // Proxy openapi schema definiton + '/openapi.json': { + target: 'http://127.0.0.1:9090/openapi.json', + rewrite: (path) => path.replace(/^\/openapi.json/, ''), + changeOrigin: true, + }, + // proxy nodes api + '/api/v1': { + target: 'http://127.0.0.1:9090/api/v1', + rewrite: (path) => path.replace(/^\/api\/v1/, ''), + changeOrigin: true, + }, + }, + }, }; diff --git a/invokeai/frontend/web/config/vite.common.config.ts b/invokeai/frontend/web/config/vite.common.config.ts deleted file mode 100644 index 8955a5a3d0..0000000000 --- a/invokeai/frontend/web/config/vite.common.config.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { UserConfig } from 'vite'; - -export const commonConfig: UserConfig = { - base: './', - server: { - // Proxy HTTP requests to the flask server - proxy: { - '/outputs': { - target: 'http://127.0.0.1:9090/outputs', - changeOrigin: true, - rewrite: (path) => path.replace(/^\/outputs/, ''), - }, - '/upload': { - target: 'http://127.0.0.1:9090/upload', - changeOrigin: true, - rewrite: (path) => path.replace(/^\/upload/, ''), - }, - '/flaskwebgui-keep-server-alive': { - target: 'http://127.0.0.1:9090/flaskwebgui-keep-server-alive', - changeOrigin: true, - rewrite: (path) => path.replace(/^\/flaskwebgui-keep-server-alive/, ''), - }, - // Proxy socket.io to the flask-socketio server - '/socket.io': { - target: 'ws://127.0.0.1:9090', - ws: true, - }, - // Proxy socket.io to the nodes socketio server - '/ws/socket.io': { - target: 'ws://127.0.0.1:9090', - ws: true, - }, - // Proxy openapi schema definiton - '/openapi.json': { - target: 'http://127.0.0.1:9090/openapi.json', - rewrite: (path) => path.replace(/^\/openapi.json/, ''), - changeOrigin: true, - }, - // proxy nodes api - '/api/v1': { - target: 'http://127.0.0.1:9090/api/v1', - rewrite: (path) => path.replace(/^\/api\/v1/, ''), - changeOrigin: true, - }, - }, - }, - build: { - chunkSizeWarningLimit: 1500, - }, -}; diff --git a/invokeai/frontend/web/config/vite.package.config.ts b/invokeai/frontend/web/config/vite.package.config.ts index d4b902d54b..5865461b06 100644 --- a/invokeai/frontend/web/config/vite.package.config.ts +++ b/invokeai/frontend/web/config/vite.package.config.ts @@ -2,11 +2,12 @@ import react from '@vitejs/plugin-react-swc'; import path from 'path'; import { visualizer } from 'rollup-plugin-visualizer'; import { PluginOption, UserConfig } from 'vite'; +import dts from 'vite-plugin-dts'; import eslint from 'vite-plugin-eslint'; import tsconfigPaths from 'vite-tsconfig-paths'; -import dts from 'vite-plugin-dts'; export const packageConfig: UserConfig = { + base: './', plugins: [ react(), eslint(), @@ -17,6 +18,7 @@ export const packageConfig: UserConfig = { }), ], build: { + chunkSizeWarningLimit: 1500, lib: { entry: path.resolve(__dirname, '../src/index.ts'), name: 'InvokeAIUI', diff --git a/invokeai/frontend/web/package.json b/invokeai/frontend/web/package.json index 4be29d1c25..3b16766bb1 100644 --- a/invokeai/frontend/web/package.json +++ b/invokeai/frontend/web/package.json @@ -72,7 +72,7 @@ "i18next-browser-languagedetector": "^7.0.1", "i18next-http-backend": "^2.2.0", "konva": "^9.0.1", - "lodash": "^4.17.21", + "lodash-es": "^4.17.21", "patch-package": "^7.0.0", "re-resizable": "^6.9.9", "react": "^18.2.0", @@ -101,7 +101,7 @@ }, "devDependencies": { "@types/dateformat": "^5.0.0", - "@types/lodash": "^4.14.194", + "@types/lodash-es": "^4.14.194", "@types/node": "^18.16.2", "@types/react": "^18.2.0", "@types/react-dom": "^18.2.1", diff --git a/invokeai/frontend/web/src/app/selectors/readinessSelector.ts b/invokeai/frontend/web/src/app/selectors/readinessSelector.ts index 82672756c8..d70043e545 100644 --- a/invokeai/frontend/web/src/app/selectors/readinessSelector.ts +++ b/invokeai/frontend/web/src/app/selectors/readinessSelector.ts @@ -4,7 +4,7 @@ import { initialCanvasImageSelector } from 'features/canvas/store/canvasSelector import { generationSelector } from 'features/parameters/store/generationSelectors'; import { systemSelector } from 'features/system/store/systemSelectors'; import { activeTabNameSelector } from 'features/ui/store/uiSelectors'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; export const readinessSelector = createSelector( [ diff --git a/invokeai/frontend/web/src/common/components/IAINumberInput.tsx b/invokeai/frontend/web/src/common/components/IAINumberInput.tsx index 4f468eb354..762182eb47 100644 --- a/invokeai/frontend/web/src/common/components/IAINumberInput.tsx +++ b/invokeai/frontend/web/src/common/components/IAINumberInput.tsx @@ -14,7 +14,7 @@ import { Tooltip, TooltipProps, } from '@chakra-ui/react'; -import { clamp } from 'lodash'; +import { clamp } from 'lodash-es'; import { FocusEvent, memo, useEffect, useState } from 'react'; diff --git a/invokeai/frontend/web/src/common/components/IAISlider.tsx b/invokeai/frontend/web/src/common/components/IAISlider.tsx index 643c5616c2..44f039c433 100644 --- a/invokeai/frontend/web/src/common/components/IAISlider.tsx +++ b/invokeai/frontend/web/src/common/components/IAISlider.tsx @@ -23,7 +23,7 @@ import { Tooltip, TooltipProps, } from '@chakra-ui/react'; -import { clamp } from 'lodash'; +import { clamp } from 'lodash-es'; import { useTranslation } from 'react-i18next'; import { diff --git a/invokeai/frontend/web/src/common/hooks/useGlobalHotkeys.ts b/invokeai/frontend/web/src/common/hooks/useGlobalHotkeys.ts index 46dff1f933..5078c8d358 100644 --- a/invokeai/frontend/web/src/common/hooks/useGlobalHotkeys.ts +++ b/invokeai/frontend/web/src/common/hooks/useGlobalHotkeys.ts @@ -2,7 +2,7 @@ import { createSelector } from '@reduxjs/toolkit'; import { RootState } from 'app/store/store'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { shiftKeyPressed } from 'features/ui/store/hotkeysSlice'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; import { isHotkeyPressed, useHotkeys } from 'react-hotkeys-hook'; const globalHotkeysSelector = createSelector( diff --git a/invokeai/frontend/web/src/common/util/parseMetadata.ts b/invokeai/frontend/web/src/common/util/parseMetadata.ts index 433aa9b2a1..210c1f85ab 100644 --- a/invokeai/frontend/web/src/common/util/parseMetadata.ts +++ b/invokeai/frontend/web/src/common/util/parseMetadata.ts @@ -1,4 +1,4 @@ -import { forEach, size } from 'lodash'; +import { forEach, size } from 'lodash-es'; import { ImageField, LatentsField } from 'services/api'; const OBJECT_TYPESTRING = '[object Object]'; diff --git a/invokeai/frontend/web/src/features/canvas/components/IAICanvas.tsx b/invokeai/frontend/web/src/features/canvas/components/IAICanvas.tsx index 634a72f81c..1850b4bfe4 100644 --- a/invokeai/frontend/web/src/features/canvas/components/IAICanvas.tsx +++ b/invokeai/frontend/web/src/features/canvas/components/IAICanvas.tsx @@ -8,7 +8,7 @@ import { import Konva from 'konva'; import { KonvaEventObject } from 'konva/lib/Node'; import { Vector2d } from 'konva/lib/types'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; import { useCallback, useRef } from 'react'; import { Layer, Stage } from 'react-konva'; diff --git a/invokeai/frontend/web/src/features/canvas/components/IAICanvasBoundingBoxOverlay.tsx b/invokeai/frontend/web/src/features/canvas/components/IAICanvasBoundingBoxOverlay.tsx index b6406a1945..e90d2c4d25 100644 --- a/invokeai/frontend/web/src/features/canvas/components/IAICanvasBoundingBoxOverlay.tsx +++ b/invokeai/frontend/web/src/features/canvas/components/IAICanvasBoundingBoxOverlay.tsx @@ -1,6 +1,6 @@ import { createSelector } from '@reduxjs/toolkit'; import { useAppSelector } from 'app/store/storeHooks'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; import { Group, Rect } from 'react-konva'; import { canvasSelector } from '../store/canvasSelectors'; diff --git a/invokeai/frontend/web/src/features/canvas/components/IAICanvasGrid.tsx b/invokeai/frontend/web/src/features/canvas/components/IAICanvasGrid.tsx index 6bd926f852..ad47b77041 100644 --- a/invokeai/frontend/web/src/features/canvas/components/IAICanvasGrid.tsx +++ b/invokeai/frontend/web/src/features/canvas/components/IAICanvasGrid.tsx @@ -5,7 +5,7 @@ import { createSelector } from '@reduxjs/toolkit'; import { RootState } from 'app/store/store'; import { useAppSelector } from 'app/store/storeHooks'; import { canvasSelector } from 'features/canvas/store/canvasSelectors'; -import { isEqual, range } from 'lodash'; +import { isEqual, range } from 'lodash-es'; import { ReactNode, useCallback, useLayoutEffect, useState } from 'react'; import { Group, Line as KonvaLine } from 'react-konva'; diff --git a/invokeai/frontend/web/src/features/canvas/components/IAICanvasIntermediateImage.tsx b/invokeai/frontend/web/src/features/canvas/components/IAICanvasIntermediateImage.tsx index 071d303939..745825a975 100644 --- a/invokeai/frontend/web/src/features/canvas/components/IAICanvasIntermediateImage.tsx +++ b/invokeai/frontend/web/src/features/canvas/components/IAICanvasIntermediateImage.tsx @@ -4,7 +4,7 @@ import { useAppSelector } from 'app/store/storeHooks'; import { useGetUrl } from 'common/util/getUrl'; import { GalleryState } from 'features/gallery/store/gallerySlice'; import { ImageConfig } from 'konva/lib/shapes/Image'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; import { useEffect, useState } from 'react'; import { Image as KonvaImage } from 'react-konva'; diff --git a/invokeai/frontend/web/src/features/canvas/components/IAICanvasMaskCompositer.tsx b/invokeai/frontend/web/src/features/canvas/components/IAICanvasMaskCompositer.tsx index 1c2a15c600..e374d2aa7b 100644 --- a/invokeai/frontend/web/src/features/canvas/components/IAICanvasMaskCompositer.tsx +++ b/invokeai/frontend/web/src/features/canvas/components/IAICanvasMaskCompositer.tsx @@ -6,7 +6,7 @@ import { Rect } from 'react-konva'; import { rgbaColorToString } from 'features/canvas/util/colorToString'; import Konva from 'konva'; -import { isNumber } from 'lodash'; +import { isNumber } from 'lodash-es'; import { useCallback, useEffect, useRef, useState } from 'react'; export const canvasMaskCompositerSelector = createSelector( diff --git a/invokeai/frontend/web/src/features/canvas/components/IAICanvasMaskLines.tsx b/invokeai/frontend/web/src/features/canvas/components/IAICanvasMaskLines.tsx index e1bf26f4ba..a553653901 100644 --- a/invokeai/frontend/web/src/features/canvas/components/IAICanvasMaskLines.tsx +++ b/invokeai/frontend/web/src/features/canvas/components/IAICanvasMaskLines.tsx @@ -2,7 +2,7 @@ import { createSelector } from '@reduxjs/toolkit'; import { useAppSelector } from 'app/store/storeHooks'; import { canvasSelector } from 'features/canvas/store/canvasSelectors'; import { GroupConfig } from 'konva/lib/Group'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; import { Group, Line } from 'react-konva'; import { isCanvasMaskLine } from '../store/canvasTypes'; diff --git a/invokeai/frontend/web/src/features/canvas/components/IAICanvasObjectRenderer.tsx b/invokeai/frontend/web/src/features/canvas/components/IAICanvasObjectRenderer.tsx index 6d1598a21b..32d2b36324 100644 --- a/invokeai/frontend/web/src/features/canvas/components/IAICanvasObjectRenderer.tsx +++ b/invokeai/frontend/web/src/features/canvas/components/IAICanvasObjectRenderer.tsx @@ -3,7 +3,7 @@ import { useAppSelector } from 'app/store/storeHooks'; import { useGetUrl } from 'common/util/getUrl'; import { canvasSelector } from 'features/canvas/store/canvasSelectors'; import { rgbaColorToString } from 'features/canvas/util/colorToString'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; import { Group, Line, Rect } from 'react-konva'; import { diff --git a/invokeai/frontend/web/src/features/canvas/components/IAICanvasStagingArea.tsx b/invokeai/frontend/web/src/features/canvas/components/IAICanvasStagingArea.tsx index c373141f6f..7bd4782840 100644 --- a/invokeai/frontend/web/src/features/canvas/components/IAICanvasStagingArea.tsx +++ b/invokeai/frontend/web/src/features/canvas/components/IAICanvasStagingArea.tsx @@ -3,7 +3,7 @@ import { useAppSelector } from 'app/store/storeHooks'; import { useGetUrl } from 'common/util/getUrl'; import { canvasSelector } from 'features/canvas/store/canvasSelectors'; import { GroupConfig } from 'konva/lib/Group'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; import { Group, Rect } from 'react-konva'; import IAICanvasImage from './IAICanvasImage'; diff --git a/invokeai/frontend/web/src/features/canvas/components/IAICanvasStagingAreaToolbar.tsx b/invokeai/frontend/web/src/features/canvas/components/IAICanvasStagingAreaToolbar.tsx index e74081b2f4..cbcd86d8d6 100644 --- a/invokeai/frontend/web/src/features/canvas/components/IAICanvasStagingAreaToolbar.tsx +++ b/invokeai/frontend/web/src/features/canvas/components/IAICanvasStagingAreaToolbar.tsx @@ -12,7 +12,7 @@ import { setShouldShowStagingImage, setShouldShowStagingOutline, } from 'features/canvas/store/canvasSlice'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; import { useCallback } from 'react'; import { useHotkeys } from 'react-hotkeys-hook'; diff --git a/invokeai/frontend/web/src/features/canvas/components/IAICanvasStatusText.tsx b/invokeai/frontend/web/src/features/canvas/components/IAICanvasStatusText.tsx index a6d32081c4..8e3edadd01 100644 --- a/invokeai/frontend/web/src/features/canvas/components/IAICanvasStatusText.tsx +++ b/invokeai/frontend/web/src/features/canvas/components/IAICanvasStatusText.tsx @@ -2,7 +2,7 @@ import { Box, Flex } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; import { useAppSelector } from 'app/store/storeHooks'; import { canvasSelector } from 'features/canvas/store/canvasSelectors'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; import { useTranslation } from 'react-i18next'; import roundToHundreth from '../util/roundToHundreth'; diff --git a/invokeai/frontend/web/src/features/canvas/components/IAICanvasStatusText/IAICanvasStatusTextCursorPos.tsx b/invokeai/frontend/web/src/features/canvas/components/IAICanvasStatusText/IAICanvasStatusTextCursorPos.tsx index b5d6e068e2..8c37be85bd 100644 --- a/invokeai/frontend/web/src/features/canvas/components/IAICanvasStatusText/IAICanvasStatusTextCursorPos.tsx +++ b/invokeai/frontend/web/src/features/canvas/components/IAICanvasStatusText/IAICanvasStatusTextCursorPos.tsx @@ -3,7 +3,7 @@ import { createSelector } from '@reduxjs/toolkit'; import { useAppSelector } from 'app/store/storeHooks'; import { canvasSelector } from 'features/canvas/store/canvasSelectors'; import roundToHundreth from 'features/canvas/util/roundToHundreth'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; import { useTranslation } from 'react-i18next'; diff --git a/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolPreview.tsx b/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolPreview.tsx index 9aeab9b211..8ad58e020c 100644 --- a/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolPreview.tsx +++ b/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolPreview.tsx @@ -3,7 +3,7 @@ import { useAppSelector } from 'app/store/storeHooks'; import { canvasSelector } from 'features/canvas/store/canvasSelectors'; import { rgbaColorToString } from 'features/canvas/util/colorToString'; import { GroupConfig } from 'konva/lib/Group'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; import { Circle, Group } from 'react-konva'; import { diff --git a/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasBoundingBox.tsx b/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasBoundingBox.tsx index 7e648ae6f3..0241f3eb55 100644 --- a/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasBoundingBox.tsx +++ b/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasBoundingBox.tsx @@ -16,7 +16,7 @@ import Konva from 'konva'; import { GroupConfig } from 'konva/lib/Group'; import { KonvaEventObject } from 'konva/lib/Node'; import { Vector2d } from 'konva/lib/types'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; import { useCallback, useEffect, useRef, useState } from 'react'; import { Group, Rect, Transformer } from 'react-konva'; diff --git a/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasMaskOptions.tsx b/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasMaskOptions.tsx index 639733722d..b345f2cda0 100644 --- a/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasMaskOptions.tsx +++ b/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasMaskOptions.tsx @@ -18,7 +18,7 @@ import { setShouldPreserveMaskedArea, } from 'features/canvas/store/canvasSlice'; import { rgbaColorToString } from 'features/canvas/util/colorToString'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; import { useHotkeys } from 'react-hotkeys-hook'; import { useTranslation } from 'react-i18next'; diff --git a/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasRedoButton.tsx b/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasRedoButton.tsx index 31d60bf455..72f4a19479 100644 --- a/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasRedoButton.tsx +++ b/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasRedoButton.tsx @@ -9,7 +9,7 @@ import { FaRedo } from 'react-icons/fa'; import { redo } from 'features/canvas/store/canvasSlice'; import { systemSelector } from 'features/system/store/systemSelectors'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; import { useTranslation } from 'react-i18next'; const canvasRedoSelector = createSelector( diff --git a/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasSettingsButtonPopover.tsx b/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasSettingsButtonPopover.tsx index 6d2bd64afc..87e3435127 100644 --- a/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasSettingsButtonPopover.tsx +++ b/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasSettingsButtonPopover.tsx @@ -16,7 +16,7 @@ import { setShouldSnapToGrid, } from 'features/canvas/store/canvasSlice'; import EmptyTempFolderButtonModal from 'features/system/components/ClearTempFolderButtonModal'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; import { ChangeEvent } from 'react'; import { useHotkeys } from 'react-hotkeys-hook'; diff --git a/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasToolChooserOptions.tsx b/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasToolChooserOptions.tsx index a6c059b28d..eee462dd2d 100644 --- a/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasToolChooserOptions.tsx +++ b/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasToolChooserOptions.tsx @@ -17,7 +17,7 @@ import { setTool, } from 'features/canvas/store/canvasSlice'; import { systemSelector } from 'features/system/store/systemSelectors'; -import { clamp, isEqual } from 'lodash'; +import { clamp, isEqual } from 'lodash-es'; import { useHotkeys } from 'react-hotkeys-hook'; import { useTranslation } from 'react-i18next'; diff --git a/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasToolbar.tsx b/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasToolbar.tsx index 1fc9a699d5..dd8963de7b 100644 --- a/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasToolbar.tsx +++ b/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasToolbar.tsx @@ -24,7 +24,7 @@ import { import { mergeAndUploadCanvas } from 'features/canvas/store/thunks/mergeAndUploadCanvas'; import { getCanvasBaseLayer } from 'features/canvas/util/konvaInstanceProvider'; import { systemSelector } from 'features/system/store/systemSelectors'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; import { ChangeEvent } from 'react'; import { useHotkeys } from 'react-hotkeys-hook'; diff --git a/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasUndoButton.tsx b/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasUndoButton.tsx index 9642e5fb86..9feb2dfcb5 100644 --- a/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasUndoButton.tsx +++ b/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasUndoButton.tsx @@ -9,7 +9,7 @@ import { undo } from 'features/canvas/store/canvasSlice'; import { systemSelector } from 'features/system/store/systemSelectors'; import { activeTabNameSelector } from 'features/ui/store/uiSelectors'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; import { useTranslation } from 'react-i18next'; const canvasUndoSelector = createSelector( diff --git a/invokeai/frontend/web/src/features/canvas/hooks/useCanvasDragMove.ts b/invokeai/frontend/web/src/features/canvas/hooks/useCanvasDragMove.ts index 35342d5279..6861c25842 100644 --- a/invokeai/frontend/web/src/features/canvas/hooks/useCanvasDragMove.ts +++ b/invokeai/frontend/web/src/features/canvas/hooks/useCanvasDragMove.ts @@ -9,7 +9,7 @@ import { setStageCoordinates, } from 'features/canvas/store/canvasSlice'; import { KonvaEventObject } from 'konva/lib/Node'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; import { useCallback } from 'react'; diff --git a/invokeai/frontend/web/src/features/canvas/hooks/useCanvasHotkeys.ts b/invokeai/frontend/web/src/features/canvas/hooks/useCanvasHotkeys.ts index 9816be91cb..6f4669a42a 100644 --- a/invokeai/frontend/web/src/features/canvas/hooks/useCanvasHotkeys.ts +++ b/invokeai/frontend/web/src/features/canvas/hooks/useCanvasHotkeys.ts @@ -13,7 +13,7 @@ import { setTool, } from 'features/canvas/store/canvasSlice'; import { activeTabNameSelector } from 'features/ui/store/uiSelectors'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; import { useRef } from 'react'; import { useHotkeys } from 'react-hotkeys-hook'; diff --git a/invokeai/frontend/web/src/features/canvas/hooks/useCanvasMouseDown.ts b/invokeai/frontend/web/src/features/canvas/hooks/useCanvasMouseDown.ts index 0c0e95a569..67bf7a8539 100644 --- a/invokeai/frontend/web/src/features/canvas/hooks/useCanvasMouseDown.ts +++ b/invokeai/frontend/web/src/features/canvas/hooks/useCanvasMouseDown.ts @@ -12,7 +12,7 @@ import { import { activeTabNameSelector } from 'features/ui/store/uiSelectors'; import Konva from 'konva'; import { KonvaEventObject } from 'konva/lib/Node'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; import { MutableRefObject, useCallback } from 'react'; import getScaledCursorPosition from '../util/getScaledCursorPosition'; diff --git a/invokeai/frontend/web/src/features/canvas/hooks/useCanvasMouseMove.ts b/invokeai/frontend/web/src/features/canvas/hooks/useCanvasMouseMove.ts index cd083020ad..abeab825e4 100644 --- a/invokeai/frontend/web/src/features/canvas/hooks/useCanvasMouseMove.ts +++ b/invokeai/frontend/web/src/features/canvas/hooks/useCanvasMouseMove.ts @@ -11,7 +11,7 @@ import { import { activeTabNameSelector } from 'features/ui/store/uiSelectors'; import Konva from 'konva'; import { Vector2d } from 'konva/lib/types'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; import { MutableRefObject, useCallback } from 'react'; import getScaledCursorPosition from '../util/getScaledCursorPosition'; diff --git a/invokeai/frontend/web/src/features/canvas/hooks/useCanvasMouseUp.ts b/invokeai/frontend/web/src/features/canvas/hooks/useCanvasMouseUp.ts index 6ca47ac126..8e70543c6f 100644 --- a/invokeai/frontend/web/src/features/canvas/hooks/useCanvasMouseUp.ts +++ b/invokeai/frontend/web/src/features/canvas/hooks/useCanvasMouseUp.ts @@ -12,7 +12,7 @@ import { } from 'features/canvas/store/canvasSlice'; import { activeTabNameSelector } from 'features/ui/store/uiSelectors'; import Konva from 'konva'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; import { MutableRefObject, useCallback } from 'react'; import getScaledCursorPosition from '../util/getScaledCursorPosition'; diff --git a/invokeai/frontend/web/src/features/canvas/hooks/useCanvasZoom.ts b/invokeai/frontend/web/src/features/canvas/hooks/useCanvasZoom.ts index 3861b2151b..3d6a1d7804 100644 --- a/invokeai/frontend/web/src/features/canvas/hooks/useCanvasZoom.ts +++ b/invokeai/frontend/web/src/features/canvas/hooks/useCanvasZoom.ts @@ -7,7 +7,7 @@ import { } from 'features/canvas/store/canvasSlice'; import Konva from 'konva'; import { KonvaEventObject } from 'konva/lib/Node'; -import { clamp, isEqual } from 'lodash'; +import { clamp, isEqual } from 'lodash-es'; import { MutableRefObject, useCallback } from 'react'; import { diff --git a/invokeai/frontend/web/src/features/canvas/store/canvasSlice.ts b/invokeai/frontend/web/src/features/canvas/store/canvasSlice.ts index e277ccdef2..ab3ab0c4e9 100644 --- a/invokeai/frontend/web/src/features/canvas/store/canvasSlice.ts +++ b/invokeai/frontend/web/src/features/canvas/store/canvasSlice.ts @@ -6,7 +6,7 @@ import { roundToMultiple, } from 'common/util/roundDownToMultiple'; import { IRect, Vector2d } from 'konva/lib/types'; -import { clamp, cloneDeep } from 'lodash'; +import { clamp, cloneDeep } from 'lodash-es'; // import { RgbaColor } from 'react-colorful'; import calculateCoordinates from '../util/calculateCoordinates'; diff --git a/invokeai/frontend/web/src/features/canvas/store/thunks/requestCanvasScale.ts b/invokeai/frontend/web/src/features/canvas/store/thunks/requestCanvasScale.ts index e6efbb979b..f16c92651a 100644 --- a/invokeai/frontend/web/src/features/canvas/store/thunks/requestCanvasScale.ts +++ b/invokeai/frontend/web/src/features/canvas/store/thunks/requestCanvasScale.ts @@ -1,6 +1,6 @@ import { AppDispatch, AppGetState } from 'app/store/store'; import { activeTabNameSelector } from 'features/ui/store/uiSelectors'; -import { debounce } from 'lodash'; +import { debounce } from 'lodash-es'; import { setDoesCanvasNeedScaling } from '../canvasSlice'; const debouncedCanvasScale = debounce((dispatch: AppDispatch) => { diff --git a/invokeai/frontend/web/src/features/gallery/components/CurrentImageButtons.tsx b/invokeai/frontend/web/src/features/gallery/components/CurrentImageButtons.tsx index 10b6d55ec7..6d247c7ed4 100644 --- a/invokeai/frontend/web/src/features/gallery/components/CurrentImageButtons.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/CurrentImageButtons.tsx @@ -1,5 +1,5 @@ import { createSelector } from '@reduxjs/toolkit'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; import { ButtonGroup, diff --git a/invokeai/frontend/web/src/features/gallery/components/CurrentImageDisplay.tsx b/invokeai/frontend/web/src/features/gallery/components/CurrentImageDisplay.tsx index ee849a95d2..36451cfb2c 100644 --- a/invokeai/frontend/web/src/features/gallery/components/CurrentImageDisplay.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/CurrentImageDisplay.tsx @@ -2,7 +2,7 @@ import { Flex, Icon } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; import { useAppSelector } from 'app/store/storeHooks'; import { systemSelector } from 'features/system/store/systemSelectors'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; import { MdPhoto } from 'react-icons/md'; import { selectedImageSelector } from '../store/gallerySelectors'; diff --git a/invokeai/frontend/web/src/features/gallery/components/CurrentImagePreview.tsx b/invokeai/frontend/web/src/features/gallery/components/CurrentImagePreview.tsx index 8ee0829190..54d69b9e5b 100644 --- a/invokeai/frontend/web/src/features/gallery/components/CurrentImagePreview.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/CurrentImagePreview.tsx @@ -4,7 +4,7 @@ import { useAppSelector } from 'app/store/storeHooks'; import { useGetUrl } from 'common/util/getUrl'; import { systemSelector } from 'features/system/store/systemSelectors'; import { uiSelector } from 'features/ui/store/uiSelectors'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; import { selectedImageSelector } from '../store/gallerySelectors'; import CurrentImageFallback from './CurrentImageFallback'; diff --git a/invokeai/frontend/web/src/features/gallery/components/DeleteImageModal.tsx b/invokeai/frontend/web/src/features/gallery/components/DeleteImageModal.tsx index 1f74706ede..12038f4179 100644 --- a/invokeai/frontend/web/src/features/gallery/components/DeleteImageModal.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/DeleteImageModal.tsx @@ -15,7 +15,7 @@ import IAISwitch from 'common/components/IAISwitch'; import { configSelector } from 'features/system/store/configSelectors'; import { systemSelector } from 'features/system/store/systemSelectors'; import { setShouldConfirmOnDelete } from 'features/system/store/systemSlice'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; import { ChangeEvent, memo, useCallback, useRef } from 'react'; import { useTranslation } from 'react-i18next'; diff --git a/invokeai/frontend/web/src/features/gallery/components/HoverableImage.tsx b/invokeai/frontend/web/src/features/gallery/components/HoverableImage.tsx index 491ca371d3..6ad8e87642 100644 --- a/invokeai/frontend/web/src/features/gallery/components/HoverableImage.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/HoverableImage.tsx @@ -53,7 +53,7 @@ import { systemSelector } from 'features/system/store/systemSelectors'; import { configSelector } from 'features/system/store/configSelectors'; import { lightboxSelector } from 'features/lightbox/store/lightboxSelectors'; import { activeTabNameSelector } from 'features/ui/store/uiSelectors'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; export const selector = createSelector( [ @@ -151,8 +151,8 @@ const HoverableImage = memo((props: HoverableImageProps) => { }; const handleUsePrompt = () => { - if (image.metadata?.sd_metadata?.prompt) { - setBothPrompts(image.metadata?.sd_metadata?.prompt); + if (typeof image.metadata?.invokeai?.node?.prompt === 'string') { + setBothPrompts(image.metadata?.invokeai?.node?.prompt); } toast({ title: t('toast.promptSet'), @@ -163,8 +163,8 @@ const HoverableImage = memo((props: HoverableImageProps) => { }; const handleUseSeed = () => { - image.metadata.sd_metadata && - dispatch(setSeed(image.metadata.sd_metadata.image.seed)); + typeof image.metadata.invokeai?.node?.seed === 'number' && + dispatch(setSeed(image.metadata.invokeai?.node?.seed)); toast({ title: t('toast.seedSet'), status: 'success', @@ -195,38 +195,39 @@ const HoverableImage = memo((props: HoverableImageProps) => { }; const handleUseAllParameters = () => { - metadata.sd_metadata && dispatch(setAllParameters(metadata.sd_metadata)); - toast({ - title: t('toast.parametersSet'), - status: 'success', - duration: 2500, - isClosable: true, - }); + // metadata.invokeai?.node && + // dispatch(setAllParameters(metadata.invokeai?.node)); + // toast({ + // title: t('toast.parametersSet'), + // status: 'success', + // duration: 2500, + // isClosable: true, + // }); }; const handleUseInitialImage = async () => { - if (metadata.sd_metadata?.image?.init_image_path) { - const response = await fetch( - metadata.sd_metadata?.image?.init_image_path - ); - if (response.ok) { - dispatch(setAllImageToImageParameters(metadata?.sd_metadata)); - toast({ - title: t('toast.initialImageSet'), - status: 'success', - duration: 2500, - isClosable: true, - }); - return; - } - } - toast({ - title: t('toast.initialImageNotSet'), - description: t('toast.initialImageNotSetDesc'), - status: 'error', - duration: 2500, - isClosable: true, - }); + // if (metadata.invokeai?.node?.image?.init_image_path) { + // const response = await fetch( + // metadata.invokeai?.node?.image?.init_image_path + // ); + // if (response.ok) { + // dispatch(setAllImageToImageParameters(metadata?.invokeai?.node)); + // toast({ + // title: t('toast.initialImageSet'), + // status: 'success', + // duration: 2500, + // isClosable: true, + // }); + // return; + // } + // } + // toast({ + // title: t('toast.initialImageNotSet'), + // description: t('toast.initialImageNotSetDesc'), + // status: 'error', + // duration: 2500, + // isClosable: true, + // }); }; const handleSelectImage = () => { @@ -268,7 +269,7 @@ const HoverableImage = memo((props: HoverableImageProps) => { } onClickCapture={handleUsePrompt} - isDisabled={image?.metadata?.sd_metadata?.prompt === undefined} + isDisabled={image?.metadata?.invokeai?.node?.prompt === undefined} > {t('parameters.usePrompt')} @@ -276,14 +277,14 @@ const HoverableImage = memo((props: HoverableImageProps) => { } onClickCapture={handleUseSeed} - isDisabled={image?.metadata?.sd_metadata?.seed === undefined} + isDisabled={image?.metadata?.invokeai?.node?.seed === undefined} > {t('parameters.useSeed')} } onClickCapture={handleUseInitialImage} - isDisabled={image?.metadata?.sd_metadata?.type !== 'img2img'} + isDisabled={image?.metadata?.invokeai?.node?.type !== 'img2img'} > {t('parameters.useInitImg')} @@ -292,7 +293,7 @@ const HoverableImage = memo((props: HoverableImageProps) => { onClickCapture={handleUseAllParameters} isDisabled={ !['txt2img', 'img2img'].includes( - image?.metadata?.sd_metadata?.type + String(image?.metadata?.invokeai?.node?.type) ) } > diff --git a/invokeai/frontend/web/src/features/gallery/components/ImageGallery.tsx b/invokeai/frontend/web/src/features/gallery/components/ImageGallery.tsx index b3998649a5..706ff215dc 100644 --- a/invokeai/frontend/web/src/features/gallery/components/ImageGallery.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/ImageGallery.tsx @@ -35,7 +35,7 @@ // } from 'features/ui/store/uiSlice'; // import { InvokeTabName } from 'features/ui/store/tabMap'; -// import { clamp } from 'lodash'; +// import { clamp } from 'lodash-es'; // import { Direction } from 're-resizable/lib/resizer'; // import React, { // ChangeEvent, diff --git a/invokeai/frontend/web/src/features/gallery/components/ImageGalleryPanel.tsx b/invokeai/frontend/web/src/features/gallery/components/ImageGalleryPanel.tsx index 2a48a7a5dc..37ed69d4da 100644 --- a/invokeai/frontend/web/src/features/gallery/components/ImageGalleryPanel.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/ImageGalleryPanel.tsx @@ -7,7 +7,7 @@ import { } from 'features/gallery/store/gallerySlice'; import { InvokeTabName } from 'features/ui/store/tabMap'; -import { clamp, isEqual } from 'lodash'; +import { clamp, isEqual } from 'lodash-es'; import { useHotkeys } from 'react-hotkeys-hook'; import './ImageGallery.css'; diff --git a/invokeai/frontend/web/src/features/gallery/components/NextPrevImageButtons.tsx b/invokeai/frontend/web/src/features/gallery/components/NextPrevImageButtons.tsx index eb94a5b25e..7c878a9485 100644 --- a/invokeai/frontend/web/src/features/gallery/components/NextPrevImageButtons.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/NextPrevImageButtons.tsx @@ -1,7 +1,7 @@ import { ChakraProps, Flex, Grid, IconButton } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; import { useState } from 'react'; import { useTranslation } from 'react-i18next'; import { FaAngleLeft, FaAngleRight } from 'react-icons/fa'; diff --git a/invokeai/frontend/web/src/features/gallery/store/gallerySelectors.ts b/invokeai/frontend/web/src/features/gallery/store/gallerySelectors.ts index 73b0a2ef0b..ebb27e12d9 100644 --- a/invokeai/frontend/web/src/features/gallery/store/gallerySelectors.ts +++ b/invokeai/frontend/web/src/features/gallery/store/gallerySelectors.ts @@ -7,7 +7,7 @@ import { activeTabNameSelector, uiSelector, } from 'features/ui/store/uiSelectors'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; import { selectResultsAll, selectResultsById, diff --git a/invokeai/frontend/web/src/features/gallery/store/gallerySlice.ts b/invokeai/frontend/web/src/features/gallery/store/gallerySlice.ts index 5cecf778b6..4d752a151b 100644 --- a/invokeai/frontend/web/src/features/gallery/store/gallerySlice.ts +++ b/invokeai/frontend/web/src/features/gallery/store/gallerySlice.ts @@ -4,7 +4,7 @@ import * as InvokeAI from 'app/types/invokeai'; import { invocationComplete } from 'services/events/actions'; import { InvokeTabName } from 'features/ui/store/tabMap'; import { IRect } from 'konva/lib/types'; -import { clamp } from 'lodash'; +import { clamp } from 'lodash-es'; import { isImageOutput } from 'services/types/guards'; import { deserializeImageResponse } from 'services/util/deserializeImageResponse'; import { imageUploaded } from 'services/thunks/image'; diff --git a/invokeai/frontend/web/src/features/lightbox/components/Lightbox.tsx b/invokeai/frontend/web/src/features/lightbox/components/Lightbox.tsx index 4fa70e4a53..cd0ce55b1e 100644 --- a/invokeai/frontend/web/src/features/lightbox/components/Lightbox.tsx +++ b/invokeai/frontend/web/src/features/lightbox/components/Lightbox.tsx @@ -10,7 +10,7 @@ import { gallerySelector } from 'features/gallery/store/gallerySelectors'; import { setIsLightboxOpen } from 'features/lightbox/store/lightboxSlice'; import { uiSelector } from 'features/ui/store/uiSelectors'; import { AnimatePresence, motion } from 'framer-motion'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; import { useHotkeys } from 'react-hotkeys-hook'; import { BiExit } from 'react-icons/bi'; import { TransformWrapper } from 'react-zoom-pan-pinch'; diff --git a/invokeai/frontend/web/src/features/lightbox/store/lightboxSelectors.ts b/invokeai/frontend/web/src/features/lightbox/store/lightboxSelectors.ts index afaf1ae398..f7d7e0129a 100644 --- a/invokeai/frontend/web/src/features/lightbox/store/lightboxSelectors.ts +++ b/invokeai/frontend/web/src/features/lightbox/store/lightboxSelectors.ts @@ -1,6 +1,6 @@ import { createSelector } from '@reduxjs/toolkit'; import { RootState } from 'app/store/store'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; export const lightboxSelector = createSelector( (state: RootState) => state.lightbox, diff --git a/invokeai/frontend/web/src/features/nodes/components/AddNodeMenu.tsx b/invokeai/frontend/web/src/features/nodes/components/AddNodeMenu.tsx index 8fb14c7a23..3265a2620f 100644 --- a/invokeai/frontend/web/src/features/nodes/components/AddNodeMenu.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/AddNodeMenu.tsx @@ -13,7 +13,7 @@ import { import { FaEllipsisV, FaPlus } from 'react-icons/fa'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { nodeAdded } from '../store/nodesSlice'; -import { cloneDeep, map } from 'lodash'; +import { cloneDeep, map } from 'lodash-es'; import { RootState } from 'app/store/store'; import { useBuildInvocation } from '../hooks/useBuildInvocation'; import { addToast } from 'features/system/store/systemSlice'; diff --git a/invokeai/frontend/web/src/features/nodes/components/FieldTypeLegend.tsx b/invokeai/frontend/web/src/features/nodes/components/FieldTypeLegend.tsx index 1e86ebfd97..c14c7ebccf 100644 --- a/invokeai/frontend/web/src/features/nodes/components/FieldTypeLegend.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/FieldTypeLegend.tsx @@ -1,6 +1,6 @@ import 'reactflow/dist/style.css'; import { Tooltip, Badge, Flex } from '@chakra-ui/react'; -import { map } from 'lodash'; +import { map } from 'lodash-es'; import { FIELDS } from '../types/constants'; import { memo } from 'react'; diff --git a/invokeai/frontend/web/src/features/nodes/components/IAINode/IAINodeInputs.tsx b/invokeai/frontend/web/src/features/nodes/components/IAINode/IAINodeInputs.tsx index ee8a21ec86..9ea383c09d 100644 --- a/invokeai/frontend/web/src/features/nodes/components/IAINode/IAINodeInputs.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/IAINode/IAINodeInputs.tsx @@ -4,7 +4,7 @@ import { InvocationTemplate, } from 'features/nodes/types/types'; import { memo, ReactNode, useCallback } from 'react'; -import { map } from 'lodash'; +import { map } from 'lodash-es'; import { useAppSelector } from 'app/store/storeHooks'; import { RootState } from 'app/store/store'; import { diff --git a/invokeai/frontend/web/src/features/nodes/components/IAINode/IAINodeOutputs.tsx b/invokeai/frontend/web/src/features/nodes/components/IAINode/IAINodeOutputs.tsx index e4eaa27bc9..2cb0bcde8d 100644 --- a/invokeai/frontend/web/src/features/nodes/components/IAINode/IAINodeOutputs.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/IAINode/IAINodeOutputs.tsx @@ -4,7 +4,7 @@ import { OutputFieldValue, } from 'features/nodes/types/types'; import { memo, ReactNode, useCallback } from 'react'; -import { map } from 'lodash'; +import { map } from 'lodash-es'; import { useAppSelector } from 'app/store/storeHooks'; import { RootState } from 'app/store/store'; import { Box, Flex, FormControl, FormLabel, HStack } from '@chakra-ui/react'; diff --git a/invokeai/frontend/web/src/features/nodes/components/fields/ModelInputFieldComponent.tsx b/invokeai/frontend/web/src/features/nodes/components/fields/ModelInputFieldComponent.tsx index 6861520eb5..3ce790171a 100644 --- a/invokeai/frontend/web/src/features/nodes/components/fields/ModelInputFieldComponent.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/fields/ModelInputFieldComponent.tsx @@ -11,7 +11,7 @@ import { selectModelsById, selectModelsIds, } from 'features/system/store/modelSlice'; -import { isEqual, map } from 'lodash'; +import { isEqual, map } from 'lodash-es'; import { ChangeEvent, memo } from 'react'; import { FieldComponentProps } from './types'; diff --git a/invokeai/frontend/web/src/features/nodes/components/search/NodeSearch.tsx b/invokeai/frontend/web/src/features/nodes/components/search/NodeSearch.tsx index eaf665f0ec..66b1d72014 100644 --- a/invokeai/frontend/web/src/features/nodes/components/search/NodeSearch.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/search/NodeSearch.tsx @@ -3,7 +3,7 @@ import { RootState } from 'app/store/store'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIInput from 'common/components/IAIInput'; import { Panel } from 'reactflow'; -import { map } from 'lodash'; +import { map } from 'lodash-es'; import { ChangeEvent, FocusEvent, diff --git a/invokeai/frontend/web/src/features/nodes/hooks/useBuildInvocation.ts b/invokeai/frontend/web/src/features/nodes/hooks/useBuildInvocation.ts index 7620113829..0526eee969 100644 --- a/invokeai/frontend/web/src/features/nodes/hooks/useBuildInvocation.ts +++ b/invokeai/frontend/web/src/features/nodes/hooks/useBuildInvocation.ts @@ -1,7 +1,7 @@ import { createSelector } from '@reduxjs/toolkit'; import { RootState } from 'app/store/store'; import { useAppSelector } from 'app/store/storeHooks'; -import { reduce } from 'lodash'; +import { reduce } from 'lodash-es'; import { useCallback } from 'react'; import { Node, useReactFlow } from 'reactflow'; import { AnyInvocationType } from 'services/events/types'; diff --git a/invokeai/frontend/web/src/features/nodes/hooks/useIsValidConnection.ts b/invokeai/frontend/web/src/features/nodes/hooks/useIsValidConnection.ts index dec9120d08..a24267d9d9 100644 --- a/invokeai/frontend/web/src/features/nodes/hooks/useIsValidConnection.ts +++ b/invokeai/frontend/web/src/features/nodes/hooks/useIsValidConnection.ts @@ -14,77 +14,77 @@ export const useIsValidConnection = () => { return true; - // Connection must have valid targets - if (!(source && sourceHandle && target && targetHandle)) { - return false; - } + // // Connection must have valid targets + // if (!(source && sourceHandle && target && targetHandle)) { + // return false; + // } - // Connection is invalid if target already has a connection - if ( - edges.find((edge) => { - return edge.target === target && edge.targetHandle === targetHandle; - }) - ) { - return false; - } + // // Connection is invalid if target already has a connection + // if ( + // edges.find((edge) => { + // return edge.target === target && edge.targetHandle === targetHandle; + // }) + // ) { + // return false; + // } - // Find the source and target nodes - const sourceNode = flow.getNode(source) as Node; + // // Find the source and target nodes + // const sourceNode = flow.getNode(source) as Node; - const targetNode = flow.getNode(target) as Node; + // const targetNode = flow.getNode(target) as Node; - // Conditional guards against undefined nodes/handles - if (!(sourceNode && targetNode && sourceNode.data && targetNode.data)) { - return false; - } + // // Conditional guards against undefined nodes/handles + // if (!(sourceNode && targetNode && sourceNode.data && targetNode.data)) { + // return false; + // } - // Connection types must be the same for a connection - if ( - sourceNode.data.outputs[sourceHandle].type !== - targetNode.data.inputs[targetHandle].type - ) { - return false; - } + // // Connection types must be the same for a connection + // if ( + // sourceNode.data.outputs[sourceHandle].type !== + // targetNode.data.inputs[targetHandle].type + // ) { + // return false; + // } - // Graphs much be acyclic (no loops!) + // // Graphs much be acyclic (no loops!) - /** - * TODO: use `graphlib.alg.findCycles()` to identify strong connections - * - * this validation func only runs when the cursor hits the second handle of the connection, - * and only on that second handle - so it cannot tell us exhaustively which connections - * are valid. - * - * ideally, we check when the connection starts to calculate all invalid handles at once. - * - * requires making a new graphlib graph - and calling `findCycles()` - for each potential - * handle. instead of using the `isValidConnection` prop, it would use the `onConnectStart` - * prop. - * - * the strong connections should be stored in global state. - * - * then, `isValidConnection` would simple loop through the strong connections and if the - * source and target are in a single strong connection, return false. - * - * and also, we can use this knowledge to style every handle when a connection starts, - * which is otherwise not possible. - */ + // /** + // * TODO: use `graphlib.alg.findCycles()` to identify strong connections + // * + // * this validation func only runs when the cursor hits the second handle of the connection, + // * and only on that second handle - so it cannot tell us exhaustively which connections + // * are valid. + // * + // * ideally, we check when the connection starts to calculate all invalid handles at once. + // * + // * requires making a new graphlib graph - and calling `findCycles()` - for each potential + // * handle. instead of using the `isValidConnection` prop, it would use the `onConnectStart` + // * prop. + // * + // * the strong connections should be stored in global state. + // * + // * then, `isValidConnection` would simple loop through the strong connections and if the + // * source and target are in a single strong connection, return false. + // * + // * and also, we can use this knowledge to style every handle when a connection starts, + // * which is otherwise not possible. + // */ - // build a graphlib graph - const g = new graphlib.Graph(); + // // build a graphlib graph + // const g = new graphlib.Graph(); - nodes.forEach((n) => { - g.setNode(n.id); - }); + // nodes.forEach((n) => { + // g.setNode(n.id); + // }); - edges.forEach((e) => { - g.setEdge(e.source, e.target); - }); + // edges.forEach((e) => { + // g.setEdge(e.source, e.target); + // }); - // Add the candidate edge to the graph - g.setEdge(source, target); + // // Add the candidate edge to the graph + // g.setEdge(source, target); - return graphlib.alg.isAcyclic(g); + // return graphlib.alg.isAcyclic(g); }, [flow] ); diff --git a/invokeai/frontend/web/src/features/nodes/util/fieldTemplateBuilders.ts b/invokeai/frontend/web/src/features/nodes/util/fieldTemplateBuilders.ts index e37f446e00..df895ba4af 100644 --- a/invokeai/frontend/web/src/features/nodes/util/fieldTemplateBuilders.ts +++ b/invokeai/frontend/web/src/features/nodes/util/fieldTemplateBuilders.ts @@ -1,4 +1,4 @@ -import { reduce } from 'lodash'; +import { reduce } from 'lodash-es'; import { OpenAPIV3 } from 'openapi-types'; import { FIELD_TYPE_MAP } from '../types/constants'; import { isSchemaObject } from '../types/typeGuards'; diff --git a/invokeai/frontend/web/src/features/nodes/util/nodesGraphBuilder/buildNodesGraph.ts b/invokeai/frontend/web/src/features/nodes/util/nodesGraphBuilder/buildNodesGraph.ts index c473695ade..f12b141e09 100644 --- a/invokeai/frontend/web/src/features/nodes/util/nodesGraphBuilder/buildNodesGraph.ts +++ b/invokeai/frontend/web/src/features/nodes/util/nodesGraphBuilder/buildNodesGraph.ts @@ -1,6 +1,6 @@ import { Graph } from 'services/api'; import { v4 as uuidv4 } from 'uuid'; -import { reduce } from 'lodash'; +import { reduce } from 'lodash-es'; import { RootState } from 'app/store/store'; import { AnyInvocation } from 'services/events/types'; diff --git a/invokeai/frontend/web/src/features/nodes/util/parseSchema.ts b/invokeai/frontend/web/src/features/nodes/util/parseSchema.ts index ffdf4710b5..7cb8132b65 100644 --- a/invokeai/frontend/web/src/features/nodes/util/parseSchema.ts +++ b/invokeai/frontend/web/src/features/nodes/util/parseSchema.ts @@ -1,4 +1,4 @@ -import { filter, reduce } from 'lodash'; +import { filter, reduce } from 'lodash-es'; import { OpenAPIV3 } from 'openapi-types'; import { isSchemaObject } from '../types/typeGuards'; import { diff --git a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Canvas/BoundingBox/BoundingBoxSettings.tsx b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Canvas/BoundingBox/BoundingBoxSettings.tsx index 6e753b002a..35a325e74e 100644 --- a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Canvas/BoundingBox/BoundingBoxSettings.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Canvas/BoundingBox/BoundingBoxSettings.tsx @@ -4,7 +4,7 @@ import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAISlider from 'common/components/IAISlider'; import { canvasSelector } from 'features/canvas/store/canvasSelectors'; import { setBoundingBoxDimensions } from 'features/canvas/store/canvasSlice'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; import { useTranslation } from 'react-i18next'; diff --git a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Canvas/InfillAndScalingSettings.tsx b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Canvas/InfillAndScalingSettings.tsx index d58ff4746b..c18934e22b 100644 --- a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Canvas/InfillAndScalingSettings.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Canvas/InfillAndScalingSettings.tsx @@ -18,7 +18,7 @@ import { setTileSize, } from 'features/parameters/store/generationSlice'; import { systemSelector } from 'features/system/store/systemSelectors'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; import { ChangeEvent } from 'react'; import { useTranslation } from 'react-i18next'; diff --git a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/ImageToImage/ImageToImageSettings.tsx b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/ImageToImage/ImageToImageSettings.tsx index 95d6272408..71b853f162 100644 --- a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/ImageToImage/ImageToImageSettings.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/ImageToImage/ImageToImageSettings.tsx @@ -29,7 +29,7 @@ export default function ImageToImageSettings() { - + ); diff --git a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/ImageToImage/InitialImagePreview.tsx b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/ImageToImage/InitialImagePreview.tsx index d8d79edc7f..2082c2a015 100644 --- a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/ImageToImage/InitialImagePreview.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/ImageToImage/InitialImagePreview.tsx @@ -11,7 +11,7 @@ import { initialImageSelected, } from 'features/parameters/store/generationSlice'; import { addToast } from 'features/system/store/systemSlice'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; import { DragEvent, useCallback, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { ImageType } from 'services/api'; diff --git a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Output/HiresSettings.tsx b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Output/HiresSettings.tsx index 35b1e9d044..7f20a1d6c3 100644 --- a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Output/HiresSettings.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/Output/HiresSettings.tsx @@ -8,7 +8,7 @@ import { setHiresFix, setHiresStrength, } from 'features/parameters/store/postprocessingSlice'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; import { ChangeEvent } from 'react'; import { useTranslation } from 'react-i18next'; diff --git a/invokeai/frontend/web/src/features/parameters/components/ParametersAccordion.tsx b/invokeai/frontend/web/src/features/parameters/components/ParametersAccordion.tsx index 50c5bb62e9..22d7a6228e 100644 --- a/invokeai/frontend/web/src/features/parameters/components/ParametersAccordion.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/ParametersAccordion.tsx @@ -5,7 +5,7 @@ import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { tabMap } from 'features/ui/store/tabMap'; import { uiSelector } from 'features/ui/store/uiSelectors'; import { openAccordionItemsChanged } from 'features/ui/store/uiSlice'; -import { map } from 'lodash'; +import { map } from 'lodash-es'; import { ReactNode, useCallback } from 'react'; import InvokeAccordionItem from './AccordionItems/InvokeAccordionItem'; diff --git a/invokeai/frontend/web/src/features/parameters/components/ProcessButtons/CancelButton.tsx b/invokeai/frontend/web/src/features/parameters/components/ProcessButtons/CancelButton.tsx index 69567e5e1e..2500081925 100644 --- a/invokeai/frontend/web/src/features/parameters/components/ProcessButtons/CancelButton.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/ProcessButtons/CancelButton.tsx @@ -12,7 +12,7 @@ import { cancelTypeChanged, CancelType, } from 'features/system/store/systemSlice'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; import { useEffect, useCallback, memo } from 'react'; import { ButtonSpinner, @@ -170,7 +170,7 @@ const CancelButton = ( } diff --git a/invokeai/frontend/web/src/features/parameters/components/ProcessButtons/ProcessButtons.tsx b/invokeai/frontend/web/src/features/parameters/components/ProcessButtons/ProcessButtons.tsx index e0ebba9f0d..ba8522f0bf 100644 --- a/invokeai/frontend/web/src/features/parameters/components/ProcessButtons/ProcessButtons.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/ProcessButtons/ProcessButtons.tsx @@ -14,7 +14,7 @@ const ProcessButtons = () => { return ( - {activeTabName === 'img2img' && } + {/* {activeTabName === 'img2img' && } */} ); diff --git a/invokeai/frontend/web/src/features/parameters/components/PromptInput/PromptInput.tsx b/invokeai/frontend/web/src/features/parameters/components/PromptInput/PromptInput.tsx index a04a073986..13095ffefa 100644 --- a/invokeai/frontend/web/src/features/parameters/components/PromptInput/PromptInput.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/PromptInput/PromptInput.tsx @@ -12,7 +12,7 @@ import { } from 'features/parameters/store/generationSlice'; import { activeTabNameSelector } from 'features/ui/store/uiSelectors'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; import { useHotkeys } from 'react-hotkeys-hook'; import { useTranslation } from 'react-i18next'; diff --git a/invokeai/frontend/web/src/features/parameters/store/generationSelectors.ts b/invokeai/frontend/web/src/features/parameters/store/generationSelectors.ts index eb3cb7a7d8..ce3c9c4e1e 100644 --- a/invokeai/frontend/web/src/features/parameters/store/generationSelectors.ts +++ b/invokeai/frontend/web/src/features/parameters/store/generationSelectors.ts @@ -6,7 +6,7 @@ import { selectResultsEntities, } from 'features/gallery/store/resultsSlice'; import { selectUploadsById } from 'features/gallery/store/uploadsSlice'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; export const generationSelector = (state: RootState) => state.generation; diff --git a/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts b/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts index 7dabfae07f..f303491b2b 100644 --- a/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts +++ b/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts @@ -4,7 +4,7 @@ import * as InvokeAI from 'app/types/invokeai'; import { getPromptAndNegative } from 'common/util/getPromptAndNegative'; import promptToString from 'common/util/promptToString'; import { seedWeightsToString } from 'common/util/seedWeightPairs'; -import { clamp } from 'lodash'; +import { clamp } from 'lodash-es'; export interface GenerationState { cfgScale: number; @@ -179,136 +179,126 @@ export const generationSlice = createSlice({ state, action: PayloadAction ) => { - const { - sampler, - prompt, - seed, - variations, - steps, - cfg_scale, - threshold, - perlin, - seamless, - _hires_fix, - width, - height, - } = action.payload.image; - - if (variations && variations.length > 0) { - state.seedWeights = seedWeightsToString(variations); - state.shouldGenerateVariations = true; - state.variationAmount = 0; - } else { - state.shouldGenerateVariations = false; - } - - if (seed) { - state.seed = seed; - state.shouldRandomizeSeed = false; - } - - if (prompt) state.prompt = promptToString(prompt); - if (sampler) state.sampler = sampler; - if (steps) state.steps = steps; - if (cfg_scale) state.cfgScale = cfg_scale; - if (typeof threshold === 'undefined') { - state.threshold = 0; - } else { - state.threshold = threshold; - } - if (typeof perlin === 'undefined') { - state.perlin = 0; - } else { - state.perlin = perlin; - } - if (typeof seamless === 'boolean') state.seamless = seamless; - // if (typeof hires_fix === 'boolean') state.hiresFix = hires_fix; // TODO: Needs to be fixed after reorg - if (width) state.width = width; - if (height) state.height = height; + // const { + // sampler, + // prompt, + // seed, + // variations, + // steps, + // cfg_scale, + // threshold, + // perlin, + // seamless, + // _hires_fix, + // width, + // height, + // } = action.payload.image; + // if (variations && variations.length > 0) { + // state.seedWeights = seedWeightsToString(variations); + // state.shouldGenerateVariations = true; + // state.variationAmount = 0; + // } else { + // state.shouldGenerateVariations = false; + // } + // if (seed) { + // state.seed = seed; + // state.shouldRandomizeSeed = false; + // } + // if (prompt) state.prompt = promptToString(prompt); + // if (sampler) state.sampler = sampler; + // if (steps) state.steps = steps; + // if (cfg_scale) state.cfgScale = cfg_scale; + // if (typeof threshold === 'undefined') { + // state.threshold = 0; + // } else { + // state.threshold = threshold; + // } + // if (typeof perlin === 'undefined') { + // state.perlin = 0; + // } else { + // state.perlin = perlin; + // } + // if (typeof seamless === 'boolean') state.seamless = seamless; + // // if (typeof hires_fix === 'boolean') state.hiresFix = hires_fix; // TODO: Needs to be fixed after reorg + // if (width) state.width = width; + // if (height) state.height = height; }, setAllImageToImageParameters: ( state, action: PayloadAction ) => { - const { type, strength, fit, init_image_path, mask_image_path } = - action.payload.image; - - if (type === 'img2img') { - if (init_image_path) state.initialImage = init_image_path; - if (mask_image_path) state.maskPath = mask_image_path; - if (strength) state.img2imgStrength = strength; - if (typeof fit === 'boolean') state.shouldFitToWidthHeight = fit; - } + // const { type, strength, fit, init_image_path, mask_image_path } = + // action.payload.image; + // if (type === 'img2img') { + // if (init_image_path) state.initialImage = init_image_path; + // if (mask_image_path) state.maskPath = mask_image_path; + // if (strength) state.img2imgStrength = strength; + // if (typeof fit === 'boolean') state.shouldFitToWidthHeight = fit; + // } }, setAllParameters: (state, action: PayloadAction) => { - const { - type, - sampler, - prompt, - seed, - variations, - steps, - cfg_scale, - threshold, - perlin, - seamless, - _hires_fix, - width, - height, - strength, - fit, - init_image_path, - mask_image_path, - } = action.payload.image; - - if (type === 'img2img') { - if (init_image_path) state.initialImage = init_image_path; - if (mask_image_path) state.maskPath = mask_image_path; - if (strength) state.img2imgStrength = strength; - if (typeof fit === 'boolean') state.shouldFitToWidthHeight = fit; - } - - if (variations && variations.length > 0) { - state.seedWeights = seedWeightsToString(variations); - state.shouldGenerateVariations = true; - state.variationAmount = 0; - } else { - state.shouldGenerateVariations = false; - } - - if (seed) { - state.seed = seed; - state.shouldRandomizeSeed = false; - } - - if (prompt) { - const [promptOnly, negativePrompt] = getPromptAndNegative(prompt); - if (promptOnly) state.prompt = promptOnly; - negativePrompt - ? (state.negativePrompt = negativePrompt) - : (state.negativePrompt = ''); - } - - if (sampler) state.sampler = sampler; - if (steps) state.steps = steps; - if (cfg_scale) state.cfgScale = cfg_scale; - if (typeof threshold === 'undefined') { - state.threshold = 0; - } else { - state.threshold = threshold; - } - if (typeof perlin === 'undefined') { - state.perlin = 0; - } else { - state.perlin = perlin; - } - if (typeof seamless === 'boolean') state.seamless = seamless; - // if (typeof hires_fix === 'boolean') state.hiresFix = hires_fix; // TODO: Needs to be fixed after reorg - if (width) state.width = width; - if (height) state.height = height; - - // state.shouldRunESRGAN = false; // TODO: Needs to be fixed after reorg - // state.shouldRunFacetool = false; // TODO: Needs to be fixed after reorg + // const { + // type, + // sampler, + // prompt, + // seed, + // variations, + // steps, + // cfg_scale, + // threshold, + // perlin, + // seamless, + // _hires_fix, + // width, + // height, + // strength, + // fit, + // init_image_path, + // mask_image_path, + // } = action.payload.image; + // if (type === 'img2img') { + // if (init_image_path) state.initialImage = init_image_path; + // if (mask_image_path) state.maskPath = mask_image_path; + // if (strength) state.img2imgStrength = strength; + // if (typeof fit === 'boolean') state.shouldFitToWidthHeight = fit; + // } + // if (variations && variations.length > 0) { + // state.seedWeights = seedWeightsToString(variations); + // state.shouldGenerateVariations = true; + // state.variationAmount = 0; + // } else { + // state.shouldGenerateVariations = false; + // } + // if (seed) { + // state.seed = seed; + // state.shouldRandomizeSeed = false; + // } + // if (prompt) { + // const [promptOnly, negativePrompt] = getPromptAndNegative(prompt); + // if (promptOnly) state.prompt = promptOnly; + // negativePrompt + // ? (state.negativePrompt = negativePrompt) + // : (state.negativePrompt = ''); + // } + // if (sampler) state.sampler = sampler; + // if (steps) state.steps = steps; + // if (cfg_scale) state.cfgScale = cfg_scale; + // if (typeof threshold === 'undefined') { + // state.threshold = 0; + // } else { + // state.threshold = threshold; + // } + // if (typeof perlin === 'undefined') { + // state.perlin = 0; + // } else { + // state.perlin = perlin; + // } + // if (typeof seamless === 'boolean') state.seamless = seamless; + // // if (typeof hires_fix === 'boolean') state.hiresFix = hires_fix; // TODO: Needs to be fixed after reorg + // if (width) state.width = width; + // if (height) state.height = height; + // // state.shouldRunESRGAN = false; // TODO: Needs to be fixed after reorg + // // state.shouldRunFacetool = false; // TODO: Needs to be fixed after reorg }, resetParametersState: (state) => { return { diff --git a/invokeai/frontend/web/src/features/system/components/Console.tsx b/invokeai/frontend/web/src/features/system/components/Console.tsx index 6df54be3a5..338e5b1382 100644 --- a/invokeai/frontend/web/src/features/system/components/Console.tsx +++ b/invokeai/frontend/web/src/features/system/components/Console.tsx @@ -7,7 +7,7 @@ import { setShouldShowLogViewer, SystemState, } from 'features/system/store/systemSlice'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; import { Resizable } from 're-resizable'; import { useLayoutEffect, useRef, useState } from 'react'; import { useHotkeys } from 'react-hotkeys-hook'; diff --git a/invokeai/frontend/web/src/features/system/components/ModelManager/CheckpointModelEdit.tsx b/invokeai/frontend/web/src/features/system/components/ModelManager/CheckpointModelEdit.tsx index 00f7a8cee8..3523e6fab7 100644 --- a/invokeai/frontend/web/src/features/system/components/ModelManager/CheckpointModelEdit.tsx +++ b/invokeai/frontend/web/src/features/system/components/ModelManager/CheckpointModelEdit.tsx @@ -24,7 +24,7 @@ import { useTranslation } from 'react-i18next'; import type { InvokeModelConfigProps } from 'app/types/invokeai'; import type { RootState } from 'app/store/store'; import type { FieldInputProps, FormikProps } from 'formik'; -import { isEqual, pickBy } from 'lodash'; +import { isEqual, pickBy } from 'lodash-es'; import ModelConvert from './ModelConvert'; import IAIFormHelperText from 'common/components/IAIForms/IAIFormHelperText'; import IAIFormErrorMessage from 'common/components/IAIForms/IAIFormErrorMessage'; diff --git a/invokeai/frontend/web/src/features/system/components/ModelManager/DiffusersModelEdit.tsx b/invokeai/frontend/web/src/features/system/components/ModelManager/DiffusersModelEdit.tsx index 39765a1dd5..f996d5a5d6 100644 --- a/invokeai/frontend/web/src/features/system/components/ModelManager/DiffusersModelEdit.tsx +++ b/invokeai/frontend/web/src/features/system/components/ModelManager/DiffusersModelEdit.tsx @@ -15,7 +15,7 @@ import { useTranslation } from 'react-i18next'; import type { InvokeDiffusersModelConfigProps } from 'app/types/invokeai'; import type { RootState } from 'app/store/store'; -import { isEqual, pickBy } from 'lodash'; +import { isEqual, pickBy } from 'lodash-es'; import IAIFormHelperText from 'common/components/IAIForms/IAIFormHelperText'; import IAIFormErrorMessage from 'common/components/IAIForms/IAIFormErrorMessage'; import IAIForm from 'common/components/IAIForm'; diff --git a/invokeai/frontend/web/src/features/system/components/ModelManager/ModelList.tsx b/invokeai/frontend/web/src/features/system/components/ModelManager/ModelList.tsx index b22cbc7548..4ef311e1d4 100644 --- a/invokeai/frontend/web/src/features/system/components/ModelManager/ModelList.tsx +++ b/invokeai/frontend/web/src/features/system/components/ModelManager/ModelList.tsx @@ -12,7 +12,7 @@ import { useTranslation } from 'react-i18next'; import { createSelector } from '@reduxjs/toolkit'; import { systemSelector } from 'features/system/store/systemSelectors'; import type { SystemState } from 'features/system/store/systemSlice'; -import { isEqual, map } from 'lodash'; +import { isEqual, map } from 'lodash-es'; import React, { useMemo, useState, useTransition } from 'react'; import type { ChangeEvent, ReactNode } from 'react'; diff --git a/invokeai/frontend/web/src/features/system/components/ModelManager/SearchModels.tsx b/invokeai/frontend/web/src/features/system/components/ModelManager/SearchModels.tsx index b791aae339..a7867efd5b 100644 --- a/invokeai/frontend/web/src/features/system/components/ModelManager/SearchModels.tsx +++ b/invokeai/frontend/web/src/features/system/components/ModelManager/SearchModels.tsx @@ -31,7 +31,7 @@ import type { FoundModel } from 'app/types/invokeai'; import type { RootState } from 'app/store/store'; import IAIInput from 'common/components/IAIInput'; import { Field, Formik } from 'formik'; -import { forEach, remove } from 'lodash'; +import { forEach, remove } from 'lodash-es'; import type { ChangeEvent, ReactNode } from 'react'; import IAIForm from 'common/components/IAIForm'; diff --git a/invokeai/frontend/web/src/features/system/components/ModelSelect.tsx b/invokeai/frontend/web/src/features/system/components/ModelSelect.tsx index 704a075474..d0ad89ba36 100644 --- a/invokeai/frontend/web/src/features/system/components/ModelSelect.tsx +++ b/invokeai/frontend/web/src/features/system/components/ModelSelect.tsx @@ -1,6 +1,6 @@ import { createSelector } from '@reduxjs/toolkit'; import { ChangeEvent, memo } from 'react'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; import { useTranslation } from 'react-i18next'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; diff --git a/invokeai/frontend/web/src/features/system/components/ProgressBar.tsx b/invokeai/frontend/web/src/features/system/components/ProgressBar.tsx index 0687b3f39f..35699c632c 100644 --- a/invokeai/frontend/web/src/features/system/components/ProgressBar.tsx +++ b/invokeai/frontend/web/src/features/system/components/ProgressBar.tsx @@ -2,7 +2,7 @@ import { Progress } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; import { useAppSelector } from 'app/store/storeHooks'; import { SystemState } from 'features/system/store/systemSlice'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; import { useTranslation } from 'react-i18next'; import { PROGRESS_BAR_THICKNESS } from 'theme/util/constants'; import { systemSelector } from '../store/systemSelectors'; diff --git a/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsModal.tsx b/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsModal.tsx index 53b0463208..3edd6229a4 100644 --- a/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsModal.tsx +++ b/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsModal.tsx @@ -37,7 +37,7 @@ import { setShouldUseSliders, } from 'features/ui/store/uiSlice'; import { UIState } from 'features/ui/store/uiTypes'; -import { isEqual, map } from 'lodash'; +import { isEqual, map } from 'lodash-es'; import { persistor } from 'app/store/persistor'; import { ChangeEvent, cloneElement, ReactElement } from 'react'; import { useTranslation } from 'react-i18next'; diff --git a/invokeai/frontend/web/src/features/system/components/StatusIndicator.tsx b/invokeai/frontend/web/src/features/system/components/StatusIndicator.tsx index 9820eb7345..03d8934f45 100644 --- a/invokeai/frontend/web/src/features/system/components/StatusIndicator.tsx +++ b/invokeai/frontend/web/src/features/system/components/StatusIndicator.tsx @@ -2,7 +2,7 @@ import { Text, Tooltip } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { errorSeen, SystemState } from 'features/system/store/systemSlice'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; import { useTranslation } from 'react-i18next'; import { systemSelector } from '../store/systemSelectors'; diff --git a/invokeai/frontend/web/src/features/system/store/configSlice.ts b/invokeai/frontend/web/src/features/system/store/configSlice.ts index e38d554603..d668a59574 100644 --- a/invokeai/frontend/web/src/features/system/store/configSlice.ts +++ b/invokeai/frontend/web/src/features/system/store/configSlice.ts @@ -1,7 +1,7 @@ import type { PayloadAction } from '@reduxjs/toolkit'; import { createSlice } from '@reduxjs/toolkit'; import { AppConfig, PartialAppConfig } from 'app/types/invokeai'; -import { merge } from 'lodash'; +import { merge } from 'lodash-es'; const initialConfigState: AppConfig = { shouldTransformUrls: false, diff --git a/invokeai/frontend/web/src/features/system/store/modelSelectors.ts b/invokeai/frontend/web/src/features/system/store/modelSelectors.ts index 5695ae8556..8b502fb3b6 100644 --- a/invokeai/frontend/web/src/features/system/store/modelSelectors.ts +++ b/invokeai/frontend/web/src/features/system/store/modelSelectors.ts @@ -1,5 +1,5 @@ import { createSelector } from '@reduxjs/toolkit'; import { RootState } from 'app/store/store'; -import { reduce } from 'lodash'; +import { reduce } from 'lodash-es'; export const modelSelector = (state: RootState) => state.models; diff --git a/invokeai/frontend/web/src/features/system/store/modelSlice.ts b/invokeai/frontend/web/src/features/system/store/modelSlice.ts index f858fafd8b..cb1cf05328 100644 --- a/invokeai/frontend/web/src/features/system/store/modelSlice.ts +++ b/invokeai/frontend/web/src/features/system/store/modelSlice.ts @@ -1,7 +1,7 @@ import { createEntityAdapter, PayloadAction } from '@reduxjs/toolkit'; import { createSlice } from '@reduxjs/toolkit'; import { RootState } from 'app/store/store'; -import { keys, sample } from 'lodash'; +import { keys, sample } from 'lodash-es'; import { CkptModelInfo, DiffusersModelInfo } from 'services/api'; import { receivedModels } from 'services/thunks/model'; diff --git a/invokeai/frontend/web/src/features/system/store/systemSelectors.ts b/invokeai/frontend/web/src/features/system/store/systemSelectors.ts index 876d40e862..68265aa2dc 100644 --- a/invokeai/frontend/web/src/features/system/store/systemSelectors.ts +++ b/invokeai/frontend/web/src/features/system/store/systemSelectors.ts @@ -1,6 +1,6 @@ import { createSelector } from '@reduxjs/toolkit'; import { RootState } from 'app/store/store'; -import { isEqual, reduce, pickBy } from 'lodash'; +import { isEqual, reduce, pickBy } from 'lodash-es'; export const systemSelector = (state: RootState) => state.system; diff --git a/invokeai/frontend/web/src/features/ui/components/FloatingGalleryButton.tsx b/invokeai/frontend/web/src/features/ui/components/FloatingGalleryButton.tsx index ea13842f23..38cada229f 100644 --- a/invokeai/frontend/web/src/features/ui/components/FloatingGalleryButton.tsx +++ b/invokeai/frontend/web/src/features/ui/components/FloatingGalleryButton.tsx @@ -4,7 +4,7 @@ import IAIIconButton from 'common/components/IAIIconButton'; import { useTranslation } from 'react-i18next'; import { requestCanvasRescale } from 'features/canvas/store/thunks/requestCanvasScale'; import { setShouldShowGallery } from 'features/ui/store/uiSlice'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; import { MdPhotoLibrary } from 'react-icons/md'; import { activeTabNameSelector, uiSelector } from '../store/uiSelectors'; diff --git a/invokeai/frontend/web/src/features/ui/components/FloatingParametersPanelButtons.tsx b/invokeai/frontend/web/src/features/ui/components/FloatingParametersPanelButtons.tsx index 6b47ee1c97..c671c0dd02 100644 --- a/invokeai/frontend/web/src/features/ui/components/FloatingParametersPanelButtons.tsx +++ b/invokeai/frontend/web/src/features/ui/components/FloatingParametersPanelButtons.tsx @@ -10,7 +10,7 @@ import { uiSelector, } from 'features/ui/store/uiSelectors'; import { setShouldShowParametersPanel } from 'features/ui/store/uiSlice'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; import { useTranslation } from 'react-i18next'; import { FaSlidersH } from 'react-icons/fa'; diff --git a/invokeai/frontend/web/src/features/ui/components/InvokeWorkarea.tsx b/invokeai/frontend/web/src/features/ui/components/InvokeWorkarea.tsx index 691ce5f703..f59028c8ca 100644 --- a/invokeai/frontend/web/src/features/ui/components/InvokeWorkarea.tsx +++ b/invokeai/frontend/web/src/features/ui/components/InvokeWorkarea.tsx @@ -10,7 +10,7 @@ import { DragEvent, ReactNode } from 'react'; import { setInitialCanvasImage } from 'features/canvas/store/canvasSlice'; import useGetImageByUuid from 'features/gallery/hooks/useGetImageByUuid'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; import { APP_CONTENT_HEIGHT } from 'theme/util/constants'; import ParametersPanel from './ParametersPanel'; diff --git a/invokeai/frontend/web/src/features/ui/components/ParametersPanel.tsx b/invokeai/frontend/web/src/features/ui/components/ParametersPanel.tsx index 116aa7bcc4..b36199e263 100644 --- a/invokeai/frontend/web/src/features/ui/components/ParametersPanel.tsx +++ b/invokeai/frontend/web/src/features/ui/components/ParametersPanel.tsx @@ -17,7 +17,7 @@ import PinParametersPanelButton from './PinParametersPanelButton'; import { requestCanvasRescale } from 'features/canvas/store/thunks/requestCanvasScale'; import { createSelector } from '@reduxjs/toolkit'; import { activeTabNameSelector, uiSelector } from '../store/uiSelectors'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; import { lightboxSelector } from 'features/lightbox/store/lightboxSelectors'; import useResolution from 'common/hooks/useResolution'; diff --git a/invokeai/frontend/web/src/features/ui/components/common/ParametersSlide.tsx b/invokeai/frontend/web/src/features/ui/components/common/ParametersSlide.tsx index 4dcc8dc06e..3342a9338b 100644 --- a/invokeai/frontend/web/src/features/ui/components/common/ParametersSlide.tsx +++ b/invokeai/frontend/web/src/features/ui/components/common/ParametersSlide.tsx @@ -3,7 +3,7 @@ import { Slide } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { uiSelector } from 'features/ui/store/uiSelectors'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; import { memo, PropsWithChildren, useRef } from 'react'; import PinParametersPanelButton from 'features/ui/components/PinParametersPanelButton'; import { diff --git a/invokeai/frontend/web/src/features/ui/components/common/Scrollable.tsx b/invokeai/frontend/web/src/features/ui/components/common/Scrollable.tsx index 0fdcff742f..91a9b14e31 100644 --- a/invokeai/frontend/web/src/features/ui/components/common/Scrollable.tsx +++ b/invokeai/frontend/web/src/features/ui/components/common/Scrollable.tsx @@ -1,5 +1,5 @@ import { Box, ChakraProps } from '@chakra-ui/react'; -import { throttle } from 'lodash'; +import { throttle } from 'lodash-es'; import { ReactNode, useEffect, useRef } from 'react'; const scrollShadowBaseStyles: ChakraProps['sx'] = { diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/Generate/GenerateParameters.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/Generate/GenerateParameters.tsx index 46cf07d088..5b56fa5b0c 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/Generate/GenerateParameters.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/Generate/GenerateParameters.tsx @@ -29,7 +29,7 @@ import ParametersAccordion, { import ProcessButtons from 'features/parameters/components/ProcessButtons/ProcessButtons'; import NegativePromptInput from 'features/parameters/components/PromptInput/NegativePromptInput'; import PromptInput from 'features/parameters/components/PromptInput/PromptInput'; -import { findIndex } from 'lodash'; +import { findIndex } from 'lodash-es'; import { memo, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { PARAMETERS_PANEL_WIDTH } from 'theme/util/constants'; diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasContentBeta.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasContentBeta.tsx index ff3736d3b6..601c36b9e2 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasContentBeta.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasContentBeta.tsx @@ -6,7 +6,7 @@ import IAICanvas from 'features/canvas/components/IAICanvas'; import IAICanvasResizer from 'features/canvas/components/IAICanvasResizer'; import { canvasSelector } from 'features/canvas/store/canvasSelectors'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; import { useLayoutEffect } from 'react'; import UnifiedCanvasToolbarBeta from './UnifiedCanvasToolbarBeta'; import UnifiedCanvasToolSettingsBeta from './UnifiedCanvasToolSettingsBeta'; diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolSettings/UnifiedCanvasColorPicker.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolSettings/UnifiedCanvasColorPicker.tsx index 32f82d48f4..c83bb6934e 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolSettings/UnifiedCanvasColorPicker.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolSettings/UnifiedCanvasColorPicker.tsx @@ -8,7 +8,7 @@ import { isStagingSelector, } from 'features/canvas/store/canvasSelectors'; import { setBrushColor, setMaskColor } from 'features/canvas/store/canvasSlice'; -import { clamp, isEqual } from 'lodash'; +import { clamp, isEqual } from 'lodash-es'; import { useHotkeys } from 'react-hotkeys-hook'; diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolSettings/UnifiedCanvasSettings.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolSettings/UnifiedCanvasSettings.tsx index eed8f73433..a2b21368d4 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolSettings/UnifiedCanvasSettings.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolSettings/UnifiedCanvasSettings.tsx @@ -16,7 +16,7 @@ import EmptyTempFolderButtonModal from 'features/system/components/ClearTempFold import { FaWrench } from 'react-icons/fa'; import ClearCanvasHistoryButtonModal from 'features/canvas/components/ClearCanvasHistoryButtonModal'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; import { useTranslation } from 'react-i18next'; export const canvasControlsSelector = createSelector( diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolSettingsBeta.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolSettingsBeta.tsx index e3382c39a7..e5503ac203 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolSettingsBeta.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolSettingsBeta.tsx @@ -3,7 +3,7 @@ import { useAppSelector } from 'app/store/storeHooks'; import { canvasSelector } from 'features/canvas/store/canvasSelectors'; import { Flex } from '@chakra-ui/react'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; import UnifiedCanvasBaseBrushSettings from './UnifiedCanvasToolSettings/UnifiedCanvasBaseBrushSettings'; import UnifiedCanvasMaskBrushSettings from './UnifiedCanvasToolSettings/UnifiedCanvasMaskBrushSettings'; import UnifiedCanvasMoveSettings from './UnifiedCanvasToolSettings/UnifiedCanvasMoveSettings'; diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolbar/UnifiedCanvasLayerSelect.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolbar/UnifiedCanvasLayerSelect.tsx index 8655a344b4..780744b045 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolbar/UnifiedCanvasLayerSelect.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolbar/UnifiedCanvasLayerSelect.tsx @@ -10,7 +10,7 @@ import { CanvasLayer, LAYER_NAMES_DICT, } from 'features/canvas/store/canvasTypes'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; import { ChangeEvent } from 'react'; import { useHotkeys } from 'react-hotkeys-hook'; diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolbar/UnifiedCanvasToolSelect.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolbar/UnifiedCanvasToolSelect.tsx index deb9bfd144..a6c4ec7c40 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolbar/UnifiedCanvasToolSelect.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolbar/UnifiedCanvasToolSelect.tsx @@ -12,7 +12,7 @@ import { setTool, } from 'features/canvas/store/canvasSlice'; import { systemSelector } from 'features/system/store/systemSelectors'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; import { useHotkeys } from 'react-hotkeys-hook'; import { useTranslation } from 'react-i18next'; diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasContent.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasContent.tsx index 00c0245af5..6cc63a8446 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasContent.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasContent.tsx @@ -7,7 +7,7 @@ import IAICanvasResizer from 'features/canvas/components/IAICanvasResizer'; import IAICanvasToolbar from 'features/canvas/components/IAICanvasToolbar/IAICanvasToolbar'; import { canvasSelector } from 'features/canvas/store/canvasSelectors'; import { requestCanvasRescale } from 'features/canvas/store/thunks/requestCanvasScale'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; import { useLayoutEffect } from 'react'; diff --git a/invokeai/frontend/web/src/features/ui/store/uiSelectors.ts b/invokeai/frontend/web/src/features/ui/store/uiSelectors.ts index 88edd76786..fa152e9ce5 100644 --- a/invokeai/frontend/web/src/features/ui/store/uiSelectors.ts +++ b/invokeai/frontend/web/src/features/ui/store/uiSelectors.ts @@ -1,6 +1,6 @@ import { createSelector } from '@reduxjs/toolkit'; import { RootState } from 'app/store/store'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; import { tabMap } from './tabMap'; import { UIState } from './uiTypes'; diff --git a/invokeai/frontend/web/src/services/thunks/image.ts b/invokeai/frontend/web/src/services/thunks/image.ts index 6b902f6e26..d9fdd1c589 100644 --- a/invokeai/frontend/web/src/services/thunks/image.ts +++ b/invokeai/frontend/web/src/services/thunks/image.ts @@ -1,7 +1,7 @@ import { isFulfilled, isRejected } from '@reduxjs/toolkit'; import { createAppAsyncThunk } from 'app/store/storeUtils'; import { imageSelected } from 'features/gallery/store/gallerySlice'; -import { clamp } from 'lodash'; +import { clamp } from 'lodash-es'; import { ImagesService } from 'services/api'; import { getHeaders } from 'services/util/getHeaders'; diff --git a/invokeai/frontend/web/src/services/thunks/model.ts b/invokeai/frontend/web/src/services/thunks/model.ts index b8017b562d..a4aac7563d 100644 --- a/invokeai/frontend/web/src/services/thunks/model.ts +++ b/invokeai/frontend/web/src/services/thunks/model.ts @@ -1,6 +1,6 @@ import { createAppAsyncThunk } from 'app/store/storeUtils'; import { Model } from 'features/system/store/modelSlice'; -import { reduce } from 'lodash'; +import { reduce } from 'lodash-es'; import { ModelsService } from 'services/api'; export const IMAGES_PER_PAGE = 20; diff --git a/invokeai/frontend/web/vite.config.ts b/invokeai/frontend/web/vite.config.ts index a8fc0c39af..6491eb72e7 100644 --- a/invokeai/frontend/web/vite.config.ts +++ b/invokeai/frontend/web/vite.config.ts @@ -1,13 +1,11 @@ import { defineConfig } from 'vite'; -import { commonConfig } from './config/vite.common.config'; import { appConfig } from './config/vite.app.config'; import { packageConfig } from './config/vite.package.config'; -import { defaultsDeep } from 'lodash'; export default defineConfig(({ mode }) => { if (mode === 'package') { - return defaultsDeep(packageConfig, commonConfig); + return packageConfig; } - return defaultsDeep(appConfig, commonConfig); + return appConfig; }); diff --git a/invokeai/frontend/web/yarn.lock b/invokeai/frontend/web/yarn.lock index 1a003eecc2..b0811ad877 100644 --- a/invokeai/frontend/web/yarn.lock +++ b/invokeai/frontend/web/yarn.lock @@ -930,10 +930,10 @@ gonzales-pe "^4.3.0" node-source-walk "^5.0.1" -"@emotion/babel-plugin@^11.10.6": - version "11.10.6" - resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.10.6.tgz#a68ee4b019d661d6f37dec4b8903255766925ead" - integrity sha512-p2dAqtVrkhSa7xz1u/m9eHYdLi+en8NowrmXeF/dKtJpU8lCWli8RUAati7NcSl0afsBott48pdnANuD0wh9QQ== +"@emotion/babel-plugin@^11.10.8": + version "11.10.8" + resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.10.8.tgz#bae325c902937665d00684038fd5294223ef9e1d" + integrity sha512-gxNky50AJL3AlkbjvTARiwAqei6/tNUxDZPSKd+3jqWVM3AmdVTTdpjHorR/an/M0VJqdsuq5oGcFH+rjtyujQ== dependencies: "@babel/helper-module-imports" "^7.16.7" "@babel/runtime" "^7.18.3" @@ -945,18 +945,18 @@ escape-string-regexp "^4.0.0" find-root "^1.1.0" source-map "^0.5.7" - stylis "4.1.3" + stylis "4.1.4" -"@emotion/cache@^11.10.5": - version "11.10.7" - resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.10.7.tgz#2e3b12d3c7c74db0a020ae79eefc52a1b03a6908" - integrity sha512-VLl1/2D6LOjH57Y8Vem1RoZ9haWF4jesHDGiHtKozDQuBIkJm2gimVo0I02sWCuzZtVACeixTVB4jeE8qvCBoQ== +"@emotion/cache@^11.10.8": + version "11.10.8" + resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.10.8.tgz#3b39b4761bea0ae2f4f07f0a425eec8b6977c03e" + integrity sha512-5fyqGHi51LU95o7qQ/vD1jyvC4uCY5GcBT+UgP4LHdpO9jPDlXqhrRr9/wCKmfoAvh5G/F7aOh4MwQa+8uEqhA== dependencies: "@emotion/memoize" "^0.8.0" "@emotion/sheet" "^1.2.1" "@emotion/utils" "^1.2.0" "@emotion/weak-memoize" "^0.3.0" - stylis "4.1.3" + stylis "4.1.4" "@emotion/hash@^0.9.0": version "0.9.0" @@ -988,13 +988,13 @@ integrity sha512-G/YwXTkv7Den9mXDO7AhLWkE3q+I92B+VqAE+dYG4NGPaHZGvt3G8Q0p9vmE+sq7rTGphUbAvmQ9YpbfMQGGlA== "@emotion/react@^11.10.6": - version "11.10.6" - resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.10.6.tgz#dbe5e650ab0f3b1d2e592e6ab1e006e75fd9ac11" - integrity sha512-6HT8jBmcSkfzO7mc+N1L9uwvOnlcGoix8Zn7srt+9ga0MjREo6lRpuVX0kzo6Jp6oTqDhREOFsygN6Ew4fEQbw== + version "11.10.8" + resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.10.8.tgz#02e274ecb45e03ab9d7a8eb9f0f0c064613eaf7b" + integrity sha512-ZfGfiABtJ1P1OXqOBsW08EgCDp5fK6C5I8hUJauc/VcJBGSzqAirMnFslhFWnZJ/w5HxPI36XbvMV0l4KZHl+w== dependencies: "@babel/runtime" "^7.18.3" - "@emotion/babel-plugin" "^11.10.6" - "@emotion/cache" "^11.10.5" + "@emotion/babel-plugin" "^11.10.8" + "@emotion/cache" "^11.10.8" "@emotion/serialize" "^1.1.1" "@emotion/use-insertion-effect-with-fallbacks" "^1.0.0" "@emotion/utils" "^1.2.0" @@ -1018,12 +1018,12 @@ integrity sha512-zxRBwl93sHMsOj4zs+OslQKg/uhF38MB+OMKoCrVuS0nyTkqnau+BM3WGEoOptg9Oz45T/aIGs1qbVAsEFo3nA== "@emotion/styled@^11.10.6": - version "11.10.6" - resolved "https://registry.yarnpkg.com/@emotion/styled/-/styled-11.10.6.tgz#d886afdc51ef4d66c787ebde848f3cc8b117ebba" - integrity sha512-OXtBzOmDSJo5Q0AFemHCfl+bUueT8BIcPSxu0EGTpGk6DmI5dnhSzQANm1e1ze0YZL7TDyAyy6s/b/zmGOS3Og== + version "11.10.8" + resolved "https://registry.yarnpkg.com/@emotion/styled/-/styled-11.10.8.tgz#a3fd68efd90bd7e8a06b82b95adec643d386fa69" + integrity sha512-gow0lF4Uw/QEdX2REMhI8v6wLOabPKJ+4HKNF0xdJ2DJdznN6fxaXpQOx6sNkyBhSUL558Rmcu1Lq/MYlVo4vw== dependencies: "@babel/runtime" "^7.18.3" - "@emotion/babel-plugin" "^11.10.6" + "@emotion/babel-plugin" "^11.10.8" "@emotion/is-prop-valid" "^1.2.0" "@emotion/serialize" "^1.1.1" "@emotion/use-insertion-effect-with-fallbacks" "^1.0.0" @@ -1838,6 +1838,13 @@ resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== +"@types/lodash-es@^4.14.194": + version "4.17.7" + resolved "https://registry.yarnpkg.com/@types/lodash-es/-/lodash-es-4.17.7.tgz#22edcae9f44aff08546e71db8925f05b33c7cc40" + integrity sha512-z0ptr6UI10VlU6l5MYhGwS4mC8DZyYer2mCoyysZtSF7p26zOX8UpbrV0YpNYLGS8K4PUFIyEr62IMFFjveSiQ== + dependencies: + "@types/lodash" "*" + "@types/lodash.mergewith@4.6.7": version "4.6.7" resolved "https://registry.yarnpkg.com/@types/lodash.mergewith/-/lodash.mergewith-4.6.7.tgz#eaa65aa5872abdd282f271eae447b115b2757212" @@ -1845,7 +1852,7 @@ dependencies: "@types/lodash" "*" -"@types/lodash@*", "@types/lodash@^4.14.194": +"@types/lodash@*": version "4.14.194" resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.194.tgz#b71eb6f7a0ff11bff59fc987134a093029258a76" integrity sha512-r22s9tAS7imvBt2lyHC9B8AGwWnXaYb1tY09oyLkXDs4vArpYJzw09nj8MLx5VfciBPGIb+ZwG0ssYnEPJxn/g== @@ -5912,10 +5919,10 @@ strip-json-comments@~2.0.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== -stylis@4.1.3: - version "4.1.3" - resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.1.3.tgz#fd2fbe79f5fed17c55269e16ed8da14c84d069f7" - integrity sha512-GP6WDNWf+o403jrEp9c5jibKavrtLW+/qYGhFxFrG8maXhwTBI7gLLhiBb0o7uFccWN+EOS9aMO6cGHWAO07OA== +stylis@4.1.4: + version "4.1.4" + resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.1.4.tgz#9cb60e7153d8ac6d02d773552bf51c7a0344535b" + integrity sha512-USf5pszRYwuE6hg9by0OkKChkQYEXfkeTtm0xKw+jqQhwyjCVLdYyMBK7R+n7dhzsblAWJnGxju4vxq5eH20GQ== stylus-lookup@^3.0.1: version "3.0.2" From a8cec4c7e6829670e80889c68b99647961388df1 Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Thu, 27 Apr 2023 14:54:54 +1000 Subject: [PATCH 24/68] fix(ui): improve schema parsing error handling --- .../web/src/features/nodes/store/nodesSlice.ts | 12 +++++++++++- .../web/src/features/system/store/systemSlice.ts | 9 ++++----- .../frontend/web/src/services/thunks/schema.ts | 14 ++++++-------- 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/invokeai/frontend/web/src/features/nodes/store/nodesSlice.ts b/invokeai/frontend/web/src/features/nodes/store/nodesSlice.ts index a886274489..960625135a 100644 --- a/invokeai/frontend/web/src/features/nodes/store/nodesSlice.ts +++ b/invokeai/frontend/web/src/features/nodes/store/nodesSlice.ts @@ -82,10 +82,19 @@ const nodesSlice = createSlice({ shouldShowGraphOverlayChanged: (state, action: PayloadAction) => { state.shouldShowGraphOverlay = action.payload; }, + parsedOpenAPISchema: (state, action: PayloadAction) => { + try { + const parsedSchema = parseSchema(action.payload); + console.debug('Parsed schema: ', parsedSchema); + state.invocationTemplates = parsedSchema; + } catch (err) { + console.error(err); + } + }, }, extraReducers(builder) { builder.addCase(receivedOpenAPISchema.fulfilled, (state, action) => { - state.invocationTemplates = action.payload; + state.schema = action.payload; }); builder.addMatcher(isFulfilledAnyGraphBuilt, (state, action) => { @@ -103,6 +112,7 @@ export const { connectionStarted, connectionEnded, shouldShowGraphOverlayChanged, + parsedOpenAPISchema, } = nodesSlice.actions; export default nodesSlice.reducer; diff --git a/invokeai/frontend/web/src/features/system/store/systemSlice.ts b/invokeai/frontend/web/src/features/system/store/systemSlice.ts index 01d19973f9..8f1410490c 100644 --- a/invokeai/frontend/web/src/features/system/store/systemSlice.ts +++ b/invokeai/frontend/web/src/features/system/store/systemSlice.ts @@ -19,9 +19,8 @@ import { ProgressImage } from 'services/events/types'; import { initialImageSelected } from 'features/parameters/store/generationSlice'; import { makeToast } from '../hooks/useToastWatcher'; import { sessionCanceled, sessionInvoked } from 'services/thunks/session'; -import { InvokeTabName } from 'features/ui/store/tabMap'; import { receivedModels } from 'services/thunks/model'; -import { receivedOpenAPISchema } from 'services/thunks/schema'; +import { parsedOpenAPISchema } from 'features/nodes/store/nodesSlice'; export type LogLevel = 'info' | 'warning' | 'error'; @@ -546,14 +545,14 @@ export const systemSlice = createSlice({ /** * Received available models from the backend */ - builder.addCase(receivedModels.fulfilled, (state, action) => { + builder.addCase(receivedModels.fulfilled, (state) => { state.wereModelsReceived = true; }); /** - * OpenAPI schema was received and parsed + * OpenAPI schema was parsed */ - builder.addCase(receivedOpenAPISchema.fulfilled, (state, action) => { + builder.addCase(parsedOpenAPISchema, (state) => { state.wasSchemaParsed = true; }); }, diff --git a/invokeai/frontend/web/src/services/thunks/schema.ts b/invokeai/frontend/web/src/services/thunks/schema.ts index bd5135cdf9..7da8514427 100644 --- a/invokeai/frontend/web/src/services/thunks/schema.ts +++ b/invokeai/frontend/web/src/services/thunks/schema.ts @@ -1,19 +1,17 @@ import { createAsyncThunk } from '@reduxjs/toolkit'; -import { parseSchema } from 'features/nodes/util/parseSchema'; +import { parsedOpenAPISchema } from 'features/nodes/store/nodesSlice'; import { OpenAPIV3 } from 'openapi-types'; export const receivedOpenAPISchema = createAsyncThunk( 'nodes/receivedOpenAPISchema', - async () => { + async (_, { dispatch }): Promise => { const response = await fetch(`openapi.json`); - const jsonData = (await response.json()) as OpenAPIV3.Document; + const openAPISchema = (await response.json()) as OpenAPIV3.Document; - console.debug('OpenAPI schema: ', jsonData); + console.debug('OpenAPI schema: ', openAPISchema); - const parsedSchema = parseSchema(jsonData); + dispatch(parsedOpenAPISchema(openAPISchema)); - console.debug('Parsed schema: ', parsedSchema); - - return parsedSchema; + return openAPISchema; } ); From 5d8728c7ef4e3dea7d560289170636fb97dca59b Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Thu, 27 Apr 2023 17:29:59 +1000 Subject: [PATCH 25/68] feat(ui): persist socket session ids and re-sub on connect --- invokeai/frontend/web/src/app/store/store.ts | 1 + .../web/src/services/events/middleware.ts | 99 +++++++------------ .../frontend/web/src/services/events/types.ts | 6 -- .../services/events/util/setEventListeners.ts | 54 ++++++++++ 4 files changed, 88 insertions(+), 72 deletions(-) create mode 100644 invokeai/frontend/web/src/services/events/util/setEventListeners.ts diff --git a/invokeai/frontend/web/src/app/store/store.ts b/invokeai/frontend/web/src/app/store/store.ts index 1c1d16de50..8a805d6f16 100644 --- a/invokeai/frontend/web/src/app/store/store.ts +++ b/invokeai/frontend/web/src/app/store/store.ts @@ -114,6 +114,7 @@ export const store = configureStore({ 'canvas/setBoundingBoxDimensions', 'canvas/setIsDrawing', 'canvas/addPointToCurrentLine', + 'socket/generatorProgress', ], }, }); diff --git a/invokeai/frontend/web/src/services/events/middleware.ts b/invokeai/frontend/web/src/services/events/middleware.ts index 4c457f3d24..1449242afe 100644 --- a/invokeai/frontend/web/src/services/events/middleware.ts +++ b/invokeai/frontend/web/src/services/events/middleware.ts @@ -32,6 +32,7 @@ import { receivedModels } from 'services/thunks/model'; import { receivedOpenAPISchema } from 'services/thunks/schema'; import { isImageOutput } from 'services/types/guards'; import { imageReceived, thumbnailReceived } from 'services/thunks/image'; +import { setEventListeners } from './util/setEventListeners'; export const socketMiddleware = () => { let areListenersSet = false; @@ -66,25 +67,25 @@ export const socketMiddleware = () => { (store: MiddlewareAPI) => (next) => (action) => { const { dispatch, getState } = store; - // Nothing dispatches `socketReset` actions yet, so this is a noop, but including anyways - if (socketReset.match(action)) { - const { sessionId } = getState().system; + // Nothing dispatches `socketReset` actions yet + // if (socketReset.match(action)) { + // const { sessionId } = getState().system; - if (sessionId) { - socket.emit('unsubscribe', { session: sessionId }); - dispatch( - socketUnsubscribed({ sessionId, timestamp: getTimestamp() }) - ); - } + // if (sessionId) { + // socket.emit('unsubscribe', { session: sessionId }); + // dispatch( + // socketUnsubscribed({ sessionId, timestamp: getTimestamp() }) + // ); + // } - if (socket.connected) { - socket.disconnect(); - dispatch(socketDisconnected({ timestamp: getTimestamp() })); - } + // if (socket.connected) { + // socket.disconnect(); + // dispatch(socketDisconnected({ timestamp: getTimestamp() })); + // } - socket.removeAllListeners(); - areListenersSet = false; - } + // socket.removeAllListeners(); + // areListenersSet = false; + // } // Set listeners for `connect` and `disconnect` events once // Must happen in middleware to get access to `dispatch` @@ -92,7 +93,8 @@ export const socketMiddleware = () => { socket.on('connect', () => { dispatch(socketConnected({ timestamp: getTimestamp() })); - const { results, uploads, models, nodes, config } = getState(); + const { results, uploads, models, nodes, config, system } = + getState(); const { disabledTabs } = config; @@ -112,6 +114,18 @@ export const socketMiddleware = () => { if (!nodes.schema && !disabledTabs.includes('nodes')) { dispatch(receivedOpenAPISchema()); } + + if (system.sessionId) { + console.log(`Re-subscribing to session ${system.sessionId}`); + socket.emit('subscribe', { session: system.sessionId }); + dispatch( + socketSubscribed({ + sessionId: system.sessionId, + timestamp: getTimestamp(), + }) + ); + setEventListeners({ socket, store }); + } }); socket.on('disconnect', () => { @@ -128,9 +142,6 @@ export const socketMiddleware = () => { if (isFulfilledSessionCreatedAction(action)) { const oldSessionId = getState().system.sessionId; - // temp disable event subscription - const shouldHandleEvent = (id: string): boolean => true; - // const subscribedNodeIds = getState().system.subscribedNodeIds; // const shouldHandleEvent = (id: string): boolean => { // if (subscribedNodeIds.length === 1 && subscribedNodeIds[0] === '*') { @@ -152,7 +163,6 @@ export const socketMiddleware = () => { timestamp: getTimestamp(), }) ); - const listenersToRemove: (keyof ServerToClientEvents)[] = [ 'invocation_started', 'generator_progress', @@ -168,57 +178,14 @@ export const socketMiddleware = () => { const sessionId = action.payload.id; - // After a session is created, we immediately subscribe to events and then invoke the session socket.emit('subscribe', { session: sessionId }); - - // Always dispatch the event actions for other consumers who want to know when we subscribed dispatch( socketSubscribed({ - sessionId, + sessionId: sessionId, timestamp: getTimestamp(), }) ); - - // Set up listeners for the present subscription - socket.on('invocation_started', (data) => { - if (shouldHandleEvent(data.node.id)) { - dispatch(invocationStarted({ data, timestamp: getTimestamp() })); - } - }); - - socket.on('generator_progress', (data) => { - if (shouldHandleEvent(data.node.id)) { - dispatch(generatorProgress({ data, timestamp: getTimestamp() })); - } - }); - - socket.on('invocation_error', (data) => { - if (shouldHandleEvent(data.node.id)) { - dispatch(invocationError({ data, timestamp: getTimestamp() })); - } - }); - - socket.on('invocation_complete', (data) => { - if (shouldHandleEvent(data.node.id)) { - const sessionId = data.graph_execution_state_id; - - const { cancelType, isCancelScheduled } = getState().system; - const { shouldFetchImages } = getState().config; - - // Handle scheduled cancelation - if (cancelType === 'scheduled' && isCancelScheduled) { - dispatch(sessionCanceled({ sessionId })); - } - - dispatch( - invocationComplete({ - data, - timestamp: getTimestamp(), - shouldFetchImages, - }) - ); - } - }); + setEventListeners({ socket, store }); // Finally we actually invoke the session, starting processing dispatch(sessionInvoked({ sessionId })); diff --git a/invokeai/frontend/web/src/services/events/types.ts b/invokeai/frontend/web/src/services/events/types.ts index 8452c46340..573dc0ac3a 100644 --- a/invokeai/frontend/web/src/services/events/types.ts +++ b/invokeai/frontend/web/src/services/events/types.ts @@ -15,12 +15,6 @@ export type AnyInvocationType = NonNullable< export type AnyInvocation = NonNullable[string]; -// export type AnyInvocation = { -// id: string; -// type: AnyInvocationType | string; -// [key: string]: any; -// }; - export type AnyResult = GraphExecutionState['results'][string]; /** diff --git a/invokeai/frontend/web/src/services/events/util/setEventListeners.ts b/invokeai/frontend/web/src/services/events/util/setEventListeners.ts new file mode 100644 index 0000000000..a136c19f39 --- /dev/null +++ b/invokeai/frontend/web/src/services/events/util/setEventListeners.ts @@ -0,0 +1,54 @@ +import { MiddlewareAPI } from '@reduxjs/toolkit'; +import { AppDispatch, RootState } from 'app/store'; +import { getTimestamp } from 'common/util/getTimestamp'; +import { sessionCanceled } from 'services/thunks/session'; +import { Socket } from 'socket.io-client'; +import { + generatorProgress, + invocationComplete, + invocationError, + invocationStarted, +} from '../actions'; +import { ClientToServerEvents, ServerToClientEvents } from '../types'; + +type SetEventListenersArg = { + socket: Socket; + store: MiddlewareAPI; +}; + +export const setEventListeners = (arg: SetEventListenersArg) => { + const { socket, store } = arg; + const { dispatch, getState } = store; + // Set up listeners for the present subscription + socket.on('invocation_started', (data) => { + dispatch(invocationStarted({ data, timestamp: getTimestamp() })); + }); + + socket.on('generator_progress', (data) => { + dispatch(generatorProgress({ data, timestamp: getTimestamp() })); + }); + + socket.on('invocation_error', (data) => { + dispatch(invocationError({ data, timestamp: getTimestamp() })); + }); + + socket.on('invocation_complete', (data) => { + const sessionId = data.graph_execution_state_id; + + const { cancelType, isCancelScheduled } = getState().system; + const { shouldFetchImages } = getState().config; + + // Handle scheduled cancelation + if (cancelType === 'scheduled' && isCancelScheduled) { + dispatch(sessionCanceled({ sessionId })); + } + + dispatch( + invocationComplete({ + data, + timestamp: getTimestamp(), + shouldFetchImages, + }) + ); + }); +}; From ca1cc0e2c29fa253bdb7e14e2a3e5fef59870c50 Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Thu, 27 Apr 2023 17:30:21 +1000 Subject: [PATCH 26/68] feat(ui): rerender mitigation sweep --- .../frontend/web/src/app/components/App.tsx | 4 +- .../src/common/components/Loading/Loading.tsx | 3 +- .../frontend/web/src/common/util/getUrl.ts | 12 +++- .../components/CurrentImageButtons.tsx | 58 ++++++++++--------- .../components/CurrentImagePreview.tsx | 7 ++- .../gallery/components/ImageGalleryPanel.tsx | 7 ++- .../ProcessButtons/CancelButton.tsx | 36 +----------- .../features/parameters/hooks/usePrompt.ts | 22 ++++--- .../features/system/components/Console.tsx | 4 +- .../system/components/ProgressBar.tsx | 3 +- .../features/system/components/SiteHeader.tsx | 5 +- .../system/store/systemPersistsDenylist.ts | 2 +- .../src/features/system/store/systemSlice.ts | 37 +----------- .../ui/components/FloatingGalleryButton.tsx | 3 +- .../FloatingParametersPanelButtons.tsx | 3 +- .../src/features/ui/components/InvokeTabs.tsx | 30 +++++----- 16 files changed, 98 insertions(+), 138 deletions(-) diff --git a/invokeai/frontend/web/src/app/components/App.tsx b/invokeai/frontend/web/src/app/components/App.tsx index 7cdbe830bb..b33a7cac3f 100644 --- a/invokeai/frontend/web/src/app/components/App.tsx +++ b/invokeai/frontend/web/src/app/components/App.tsx @@ -28,11 +28,13 @@ import { useGlobalHotkeys } from 'common/hooks/useGlobalHotkeys'; import { configChanged } from 'features/system/store/configSlice'; import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus'; +const DEFAULT_CONFIG = {}; + interface Props extends PropsWithChildren { config?: PartialAppConfig; } -const App = ({ config = {}, children }: Props) => { +const App = ({ config = DEFAULT_CONFIG, children }: Props) => { useToastWatcher(); useGlobalHotkeys(); diff --git a/invokeai/frontend/web/src/common/components/Loading/Loading.tsx b/invokeai/frontend/web/src/common/components/Loading/Loading.tsx index 45a304747b..8625e5b49b 100644 --- a/invokeai/frontend/web/src/common/components/Loading/Loading.tsx +++ b/invokeai/frontend/web/src/common/components/Loading/Loading.tsx @@ -1,5 +1,6 @@ import { Flex, Image, Spinner } from '@chakra-ui/react'; import InvokeAILogoImage from 'assets/images/logo.png'; +import { memo } from 'react'; // This component loads before the theme so we cannot use theme tokens here @@ -29,4 +30,4 @@ const Loading = () => { ); }; -export default Loading; +export default memo(Loading); diff --git a/invokeai/frontend/web/src/common/util/getUrl.ts b/invokeai/frontend/web/src/common/util/getUrl.ts index 956e3428dc..72607057e4 100644 --- a/invokeai/frontend/web/src/common/util/getUrl.ts +++ b/invokeai/frontend/web/src/common/util/getUrl.ts @@ -1,5 +1,6 @@ import { RootState } from 'app/store/store'; import { useAppSelector } from 'app/store/storeHooks'; +import { useCallback } from 'react'; import { OpenAPI } from 'services/api'; export const getUrlAlt = (url: string, shouldTransformUrls: boolean) => { @@ -15,14 +16,19 @@ export const useGetUrl = () => { (state: RootState) => state.config.shouldTransformUrls ); - return { - shouldTransformUrls, - getUrl: (url?: string) => { + const getUrl = useCallback( + (url?: string) => { if (OpenAPI.BASE && shouldTransformUrls) { return [OpenAPI.BASE, url].join('/'); } return url; }, + [shouldTransformUrls] + ); + + return { + shouldTransformUrls, + getUrl, }; }; diff --git a/invokeai/frontend/web/src/features/gallery/components/CurrentImageButtons.tsx b/invokeai/frontend/web/src/features/gallery/components/CurrentImageButtons.tsx index 6d247c7ed4..3cfe932b75 100644 --- a/invokeai/frontend/web/src/features/gallery/components/CurrentImageButtons.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/CurrentImageButtons.tsx @@ -163,16 +163,16 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => { const { t } = useTranslation(); const setBothPrompts = useSetBothPrompts(); - const handleClickUseAsInitialImage = () => { + const handleClickUseAsInitialImage = useCallback(() => { if (!image) return; if (isLightboxOpen) dispatch(setIsLightboxOpen(false)); dispatch(initialImageSelected(image.name)); // dispatch(setInitialImage(currentImage)); // dispatch(setActiveTab('img2img')); - }; + }, [dispatch, image, isLightboxOpen]); - const handleCopyImage = async () => { + const handleCopyImage = useCallback(async () => { if (!image?.url) { return; } @@ -194,9 +194,9 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => { duration: 2500, isClosable: true, }); - }; + }, [getUrl, t, image?.url, toast]); - const handleCopyImageLink = () => { + const handleCopyImageLink = useCallback(() => { const url = image ? shouldTransformUrls ? getUrl(image.url) @@ -215,7 +215,7 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => { isClosable: true, }); }); - }; + }, [toast, shouldTransformUrls, getUrl, t, image]); useHotkeys( 'shift+i', @@ -241,11 +241,11 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => { [image] ); - const handlePreviewVisibility = () => { + const handlePreviewVisibility = useCallback(() => { dispatch(setShouldHidePreview(!shouldHidePreview)); - }; + }, [dispatch, shouldHidePreview]); - const handleClickUseAllParameters = () => { + const handleClickUseAllParameters = useCallback(() => { if (!image) return; // selectedImage.metadata && // dispatch(setAllParameters(selectedImage.metadata)); @@ -254,7 +254,7 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => { // } else if (selectedImage.metadata?.image.type === 'txt2img') { // dispatch(setActiveTab('txt2img')); // } - }; + }, [image]); useHotkeys( 'a', @@ -338,9 +338,9 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => { [image] ); - const handleClickUpscale = () => { + const handleClickUpscale = useCallback(() => { // selectedImage && dispatch(runESRGAN(selectedImage)); - }; + }, []); useHotkeys( 'Shift+U', @@ -369,9 +369,9 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => { ] ); - const handleClickFixFaces = () => { + const handleClickFixFaces = useCallback(() => { // selectedImage && dispatch(runFacetool(selectedImage)); - }; + }, []); useHotkeys( 'Shift+R', @@ -401,10 +401,12 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => { ] ); - const handleClickShowImageDetails = () => - dispatch(setShouldShowImageDetails(!shouldShowImageDetails)); + const handleClickShowImageDetails = useCallback( + () => dispatch(setShouldShowImageDetails(!shouldShowImageDetails)), + [dispatch, shouldShowImageDetails] + ); - const handleSendToCanvas = () => { + const handleSendToCanvas = useCallback(() => { if (!image) return; if (isLightboxOpen) dispatch(setIsLightboxOpen(false)); @@ -421,7 +423,7 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => { duration: 2500, isClosable: true, }); - }; + }, [image, isLightboxOpen, dispatch, activeTabName, toast, t]); useHotkeys( 'i', @@ -440,19 +442,19 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => { [image, shouldShowImageDetails] ); - const handleInitiateDelete = () => { + const handleDelete = useCallback(() => { + if (canDeleteImage && image) { + dispatch(imageDeleted({ imageType: image.type, imageName: image.name })); + } + }, [image, canDeleteImage, dispatch]); + + const handleInitiateDelete = useCallback(() => { if (shouldConfirmOnDelete) { onDeleteDialogOpen(); } else { handleDelete(); } - }; - - const handleDelete = () => { - if (canDeleteImage && image) { - dispatch(imageDeleted({ imageType: image.type, imageName: image.name })); - } - }; + }, [shouldConfirmOnDelete, onDeleteDialogOpen, handleDelete]); useHotkeys('delete', handleInitiateDelete, [ image, @@ -461,9 +463,9 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => { isProcessing, ]); - const handleLightBox = () => { + const handleLightBox = useCallback(() => { dispatch(setIsLightboxOpen(!isLightboxOpen)); - }; + }, [dispatch, isLightboxOpen]); return ( <> diff --git a/invokeai/frontend/web/src/features/gallery/components/CurrentImagePreview.tsx b/invokeai/frontend/web/src/features/gallery/components/CurrentImagePreview.tsx index 54d69b9e5b..8855bf11d3 100644 --- a/invokeai/frontend/web/src/features/gallery/components/CurrentImagePreview.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/CurrentImagePreview.tsx @@ -11,6 +11,7 @@ import CurrentImageFallback from './CurrentImageFallback'; import ImageMetadataViewer from './ImageMetaDataViewer/ImageMetadataViewer'; import NextPrevImageButtons from './NextPrevImageButtons'; import CurrentImageHidden from './CurrentImageHidden'; +import { memo } from 'react'; export const imagesSelector = createSelector( [uiSelector, selectedImageSelector, systemSelector], @@ -50,7 +51,7 @@ export const imagesSelector = createSelector( } ); -export default function CurrentImagePreview() { +const CurrentImagePreview = () => { const { shouldShowImageDetails, imageToDisplay, shouldHidePreview } = useAppSelector(imagesSelector); const { getUrl } = useGetUrl(); @@ -115,4 +116,6 @@ export default function CurrentImagePreview() { )} ); -} +}; + +export default memo(CurrentImagePreview); diff --git a/invokeai/frontend/web/src/features/gallery/components/ImageGalleryPanel.tsx b/invokeai/frontend/web/src/features/gallery/components/ImageGalleryPanel.tsx index 37ed69d4da..996603d3e6 100644 --- a/invokeai/frontend/web/src/features/gallery/components/ImageGalleryPanel.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/ImageGalleryPanel.tsx @@ -28,6 +28,7 @@ import { requestCanvasRescale } from 'features/canvas/store/thunks/requestCanvas import { lightboxSelector } from 'features/lightbox/store/lightboxSelectors'; import useResolution from 'common/hooks/useResolution'; import { Flex } from '@chakra-ui/react'; +import { memo } from 'react'; const GALLERY_TAB_WIDTHS: Record< InvokeTabName, @@ -72,7 +73,7 @@ const galleryPanelSelector = createSelector( } ); -export default function ImageGalleryPanel() { +export const ImageGalleryPanel = () => { const dispatch = useAppDispatch(); const { shouldPinGallery, @@ -232,4 +233,6 @@ export default function ImageGalleryPanel() { }; return renderImageGallery(); -} +}; + +export default memo(ImageGalleryPanel); diff --git a/invokeai/frontend/web/src/features/parameters/components/ProcessButtons/CancelButton.tsx b/invokeai/frontend/web/src/features/parameters/components/ProcessButtons/CancelButton.tsx index 2500081925..a71e8a3638 100644 --- a/invokeai/frontend/web/src/features/parameters/components/ProcessButtons/CancelButton.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/ProcessButtons/CancelButton.tsx @@ -6,14 +6,12 @@ import IAIIconButton, { import { systemSelector } from 'features/system/store/systemSelectors'; import { SystemState, - setCancelAfter, - setCancelType, cancelScheduled, cancelTypeChanged, CancelType, } from 'features/system/store/systemSlice'; import { isEqual } from 'lodash-es'; -import { useEffect, useCallback, memo } from 'react'; +import { useCallback, memo } from 'react'; import { ButtonSpinner, ButtonGroup, @@ -27,16 +25,9 @@ import { import { useHotkeys } from 'react-hotkeys-hook'; import { useTranslation } from 'react-i18next'; -import { - MdArrowDropDown, - MdArrowDropUp, - MdCancel, - MdCancelScheduleSend, -} from 'react-icons/md'; +import { MdCancel, MdCancelScheduleSend } from 'react-icons/md'; -import IAISimpleMenu from 'common/components/IAISimpleMenu'; import { sessionCanceled } from 'services/thunks/session'; -import { FaChevronDown } from 'react-icons/fa'; import { BiChevronDown } from 'react-icons/bi'; const cancelButtonSelector = createSelector( @@ -48,8 +39,6 @@ const cancelButtonSelector = createSelector( isCancelable: system.isCancelable, currentIteration: system.currentIteration, totalIterations: system.totalIterations, - // cancelType: system.cancelOptions.cancelType, - // cancelAfter: system.cancelOptions.cancelAfter, sessionId: system.sessionId, cancelType: system.cancelType, isCancelScheduled: system.isCancelScheduled, @@ -75,11 +64,8 @@ const CancelButton = ( isProcessing, isConnected, isCancelable, - currentIteration, - totalIterations, cancelType, isCancelScheduled, - // cancelAfter, sessionId, } = useAppSelector(cancelButtonSelector); @@ -105,7 +91,6 @@ const CancelButton = ( }, [dispatch] ); - // const isCancelScheduled = cancelAfter === null ? false : true; useHotkeys( 'shift+x', @@ -117,23 +102,6 @@ const CancelButton = ( [isConnected, isProcessing, isCancelable] ); - // useEffect(() => { - // if (cancelAfter !== null && cancelAfter < currentIteration) { - // handleClickCancel(); - // } - // }, [cancelAfter, currentIteration, handleClickCancel]); - - // const cancelMenuItems = [ - // { - // item: t('parameters.cancel.immediate'), - // onClick: () => dispatch(cancelTypeChanged('immediate')), - // }, - // { - // item: t('parameters.cancel.schedule'), - // onClick: () => dispatch(cancelTypeChanged('scheduled')), - // }, - // ]; - return ( {cancelType === 'immediate' ? ( diff --git a/invokeai/frontend/web/src/features/parameters/hooks/usePrompt.ts b/invokeai/frontend/web/src/features/parameters/hooks/usePrompt.ts index 02293c6ace..40080b77c7 100644 --- a/invokeai/frontend/web/src/features/parameters/hooks/usePrompt.ts +++ b/invokeai/frontend/web/src/features/parameters/hooks/usePrompt.ts @@ -4,23 +4,27 @@ import * as InvokeAI from 'app/types/invokeai'; import promptToString from 'common/util/promptToString'; import { useAppDispatch } from 'app/store/storeHooks'; import { setNegativePrompt, setPrompt } from '../store/generationSlice'; +import { useCallback } from 'react'; // TECHDEBT: We have two metadata prompt formats and need to handle recalling either of them. // This hook provides a function to do that. const useSetBothPrompts = () => { const dispatch = useAppDispatch(); - return (inputPrompt: InvokeAI.Prompt) => { - const promptString = - typeof inputPrompt === 'string' - ? inputPrompt - : promptToString(inputPrompt); + return useCallback( + (inputPrompt: InvokeAI.Prompt) => { + const promptString = + typeof inputPrompt === 'string' + ? inputPrompt + : promptToString(inputPrompt); - const [prompt, negativePrompt] = getPromptAndNegative(promptString); + const [prompt, negativePrompt] = getPromptAndNegative(promptString); - dispatch(setPrompt(prompt)); - dispatch(setNegativePrompt(negativePrompt)); - }; + dispatch(setPrompt(prompt)); + dispatch(setNegativePrompt(negativePrompt)); + }, + [dispatch] + ); }; export default useSetBothPrompts; diff --git a/invokeai/frontend/web/src/features/system/components/Console.tsx b/invokeai/frontend/web/src/features/system/components/Console.tsx index 338e5b1382..4f7946ee78 100644 --- a/invokeai/frontend/web/src/features/system/components/Console.tsx +++ b/invokeai/frontend/web/src/features/system/components/Console.tsx @@ -9,7 +9,7 @@ import { } from 'features/system/store/systemSlice'; import { isEqual } from 'lodash-es'; import { Resizable } from 're-resizable'; -import { useLayoutEffect, useRef, useState } from 'react'; +import { memo, useLayoutEffect, useRef, useState } from 'react'; import { useHotkeys } from 'react-hotkeys-hook'; import { useTranslation } from 'react-i18next'; import { FaAngleDoubleDown, FaCode, FaMinus } from 'react-icons/fa'; @@ -194,4 +194,4 @@ const Console = () => { ); }; -export default Console; +export default memo(Console); diff --git a/invokeai/frontend/web/src/features/system/components/ProgressBar.tsx b/invokeai/frontend/web/src/features/system/components/ProgressBar.tsx index 35699c632c..03e78965a3 100644 --- a/invokeai/frontend/web/src/features/system/components/ProgressBar.tsx +++ b/invokeai/frontend/web/src/features/system/components/ProgressBar.tsx @@ -3,6 +3,7 @@ import { createSelector } from '@reduxjs/toolkit'; import { useAppSelector } from 'app/store/storeHooks'; import { SystemState } from 'features/system/store/systemSlice'; import { isEqual } from 'lodash-es'; +import { memo } from 'react'; import { useTranslation } from 'react-i18next'; import { PROGRESS_BAR_THICKNESS } from 'theme/util/constants'; import { systemSelector } from '../store/systemSelectors'; @@ -40,4 +41,4 @@ const ProgressBar = () => { ); }; -export default ProgressBar; +export default memo(ProgressBar); diff --git a/invokeai/frontend/web/src/features/system/components/SiteHeader.tsx b/invokeai/frontend/web/src/features/system/components/SiteHeader.tsx index 004e3690fd..350e1291aa 100644 --- a/invokeai/frontend/web/src/features/system/components/SiteHeader.tsx +++ b/invokeai/frontend/web/src/features/system/components/SiteHeader.tsx @@ -1,5 +1,5 @@ import { Flex, Grid } from '@chakra-ui/react'; -import { useState } from 'react'; +import { memo, useState } from 'react'; import ModelSelect from './ModelSelect'; import StatusIndicator from './StatusIndicator'; @@ -65,5 +65,4 @@ const SiteHeader = () => { ); }; -SiteHeader.displayName = 'SiteHeader'; -export default SiteHeader; +export default memo(SiteHeader); diff --git a/invokeai/frontend/web/src/features/system/store/systemPersistsDenylist.ts b/invokeai/frontend/web/src/features/system/store/systemPersistsDenylist.ts index 84dbd0ecc7..bac2a652b5 100644 --- a/invokeai/frontend/web/src/features/system/store/systemPersistsDenylist.ts +++ b/invokeai/frontend/web/src/features/system/store/systemPersistsDenylist.ts @@ -17,7 +17,7 @@ const itemsToDenylist: (keyof SystemState)[] = [ 'totalSteps', 'openModel', 'isCancelScheduled', - 'sessionId', + // 'sessionId', 'progressImage', 'wereModelsReceived', 'wasSchemaParsed', diff --git a/invokeai/frontend/web/src/features/system/store/systemSlice.ts b/invokeai/frontend/web/src/features/system/store/systemSlice.ts index 8f1410490c..3f572a253d 100644 --- a/invokeai/frontend/web/src/features/system/store/systemSlice.ts +++ b/invokeai/frontend/web/src/features/system/store/systemSlice.ts @@ -89,18 +89,6 @@ export interface SystemState * Array of node IDs that we want to handle when events received */ subscribedNodeIds: string[]; - // /** - // * Whether or not URLs should be transformed to use a different host - // */ - // shouldTransformUrls: boolean; - // /** - // * Array of disabled tabs - // */ - // disabledTabs: InvokeTabName[]; - // /** - // * Array of disabled features - // */ - // disabledFeatures: InvokeAI.AppFeature[]; /** * Whether or not the available models were received */ @@ -358,27 +346,6 @@ export const systemSlice = createSlice({ subscribedNodeIdsSet: (state, action: PayloadAction) => { state.subscribedNodeIds = action.payload; }, - // /** - // * `shouldTransformUrls` was changed - // */ - // shouldTransformUrlsChanged: (state, action: PayloadAction) => { - // state.shouldTransformUrls = action.payload; - // }, - // /** - // * `disabledTabs` was changed - // */ - // disabledTabsChanged: (state, action: PayloadAction) => { - // state.disabledTabs = action.payload; - // }, - // /** - // * `disabledFeatures` was changed - // */ - // disabledFeaturesChanged: ( - // state, - // action: PayloadAction - // ) => { - // state.disabledFeatures = action.payload; - // }, }, extraReducers(builder) { /** @@ -386,6 +353,7 @@ export const systemSlice = createSlice({ */ builder.addCase(socketSubscribed, (state, action) => { state.sessionId = action.payload.sessionId; + console.log(`Subscribed to session ${action.payload.sessionId}`); }); /** @@ -594,9 +562,6 @@ export const { scheduledCancelAborted, cancelTypeChanged, subscribedNodeIdsSet, - // shouldTransformUrlsChanged, - // disabledTabsChanged, - // disabledFeaturesChanged, } = systemSlice.actions; export default systemSlice.reducer; diff --git a/invokeai/frontend/web/src/features/ui/components/FloatingGalleryButton.tsx b/invokeai/frontend/web/src/features/ui/components/FloatingGalleryButton.tsx index 38cada229f..83a699aca0 100644 --- a/invokeai/frontend/web/src/features/ui/components/FloatingGalleryButton.tsx +++ b/invokeai/frontend/web/src/features/ui/components/FloatingGalleryButton.tsx @@ -7,6 +7,7 @@ import { setShouldShowGallery } from 'features/ui/store/uiSlice'; import { isEqual } from 'lodash-es'; import { MdPhotoLibrary } from 'react-icons/md'; import { activeTabNameSelector, uiSelector } from '../store/uiSelectors'; +import { memo } from 'react'; const floatingGalleryButtonSelector = createSelector( [activeTabNameSelector, uiSelector], @@ -58,4 +59,4 @@ const FloatingGalleryButton = () => { ) : null; }; -export default FloatingGalleryButton; +export default memo(FloatingGalleryButton); diff --git a/invokeai/frontend/web/src/features/ui/components/FloatingParametersPanelButtons.tsx b/invokeai/frontend/web/src/features/ui/components/FloatingParametersPanelButtons.tsx index c671c0dd02..3055216b66 100644 --- a/invokeai/frontend/web/src/features/ui/components/FloatingParametersPanelButtons.tsx +++ b/invokeai/frontend/web/src/features/ui/components/FloatingParametersPanelButtons.tsx @@ -11,6 +11,7 @@ import { } from 'features/ui/store/uiSelectors'; import { setShouldShowParametersPanel } from 'features/ui/store/uiSlice'; import { isEqual } from 'lodash-es'; +import { memo } from 'react'; import { useTranslation } from 'react-i18next'; import { FaSlidersH } from 'react-icons/fa'; @@ -94,4 +95,4 @@ const FloatingParametersPanelButtons = () => { ) : null; }; -export default FloatingParametersPanelButtons; +export default memo(FloatingParametersPanelButtons); diff --git a/invokeai/frontend/web/src/features/ui/components/InvokeTabs.tsx b/invokeai/frontend/web/src/features/ui/components/InvokeTabs.tsx index e053986897..0c65a99293 100644 --- a/invokeai/frontend/web/src/features/ui/components/InvokeTabs.tsx +++ b/invokeai/frontend/web/src/features/ui/components/InvokeTabs.tsx @@ -14,7 +14,7 @@ import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { setIsLightboxOpen } from 'features/lightbox/store/lightboxSlice'; import { InvokeTabName } from 'features/ui/store/tabMap'; import { setActiveTab, togglePanels } from 'features/ui/store/uiSlice'; -import { ReactNode, useMemo } from 'react'; +import { memo, ReactNode, useMemo } from 'react'; import { useHotkeys } from 'react-hotkeys-hook'; import { MdDeviceHub, MdGridOn } from 'react-icons/md'; import { activeTabIndexSelector } from '../store/uiSelectors'; @@ -24,10 +24,10 @@ import { ResourceKey } from 'i18next'; import { requestCanvasRescale } from 'features/canvas/store/thunks/requestCanvasScale'; import NodeEditor from 'features/nodes/components/NodeEditor'; import GenerateWorkspace from './tabs/Generate/GenerateWorkspace'; -import { FaImage } from 'react-icons/fa'; import { createSelector } from '@reduxjs/toolkit'; -import { BsLightningChargeFill, BsLightningFill } from 'react-icons/bs'; +import { BsLightningChargeFill } from 'react-icons/bs'; import { configSelector } from 'features/system/store/configSelectors'; +import { isEqual } from 'lodash'; export interface InvokeTabInfo { id: InvokeTabName; @@ -35,10 +35,6 @@ export interface InvokeTabInfo { workarea: ReactNode; } -const tabIconStyles: ChakraProps['sx'] = { - boxSize: 6, -}; - const tabs: InvokeTabInfo[] = [ { id: 'generate', @@ -57,13 +53,19 @@ const tabs: InvokeTabInfo[] = [ }, ]; -const enabledTabsSelector = createSelector(configSelector, (config) => { - const { disabledTabs } = config; +const enabledTabsSelector = createSelector( + configSelector, + (config) => { + const { disabledTabs } = config; - return tabs.filter((tab) => !disabledTabs.includes(tab.id)); -}); + return tabs.filter((tab) => !disabledTabs.includes(tab.id)); + }, + { + memoizeOptions: { resultEqualityCheck: isEqual }, + } +); -export default function InvokeTabs() { +const InvokeTabs = () => { const activeTab = useAppSelector(activeTabIndexSelector); const enabledTabs = useAppSelector(enabledTabsSelector); const isLightBoxOpen = useAppSelector( @@ -160,4 +162,6 @@ export default function InvokeTabs() { {tabPanels} ); -} +}; + +export default memo(InvokeTabs); From 53c7832fd10e05ff643b286f5cc5f7ad87827f79 Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Fri, 28 Apr 2023 22:37:51 +1000 Subject: [PATCH 27/68] fix(ui): fix packaging import issue --- invokeai/frontend/web/package.json | 8 ++++++-- invokeai/frontend/web/src/services/events/middleware.ts | 2 +- .../web/src/services/events/util/setEventListeners.ts | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/invokeai/frontend/web/package.json b/invokeai/frontend/web/package.json index 3b16766bb1..05ad90e89b 100644 --- a/invokeai/frontend/web/package.json +++ b/invokeai/frontend/web/package.json @@ -15,6 +15,9 @@ } }, "types": "./dist/index.d.ts", + "files": [ + "dist" + ], "scripts": { "prepare": "cd ../../../ && husky install invokeai/frontend/web/.husky", "dev": "concurrently \"vite dev\" \"yarn run theme:watch\"", @@ -53,7 +56,6 @@ }, "dependencies": { "@chakra-ui/anatomy": "^2.1.1", - "@chakra-ui/cli": "^2.4.0", "@chakra-ui/icons": "^2.0.19", "@chakra-ui/react": "^2.6.0", "@chakra-ui/styled-system": "^2.9.0", @@ -97,7 +99,9 @@ }, "peerDependencies": { "react": "^18.2.0", - "react-dom": "^18.2.0" + "react-dom": "^18.2.0", + "ts-toolbelt": "^9.6.0", + "@chakra-ui/cli": "^2.4.0" }, "devDependencies": { "@types/dateformat": "^5.0.0", diff --git a/invokeai/frontend/web/src/services/events/middleware.ts b/invokeai/frontend/web/src/services/events/middleware.ts index 1449242afe..824e48648c 100644 --- a/invokeai/frontend/web/src/services/events/middleware.ts +++ b/invokeai/frontend/web/src/services/events/middleware.ts @@ -32,7 +32,7 @@ import { receivedModels } from 'services/thunks/model'; import { receivedOpenAPISchema } from 'services/thunks/schema'; import { isImageOutput } from 'services/types/guards'; import { imageReceived, thumbnailReceived } from 'services/thunks/image'; -import { setEventListeners } from './util/setEventListeners'; +import { setEventListeners } from 'services/events/util/setEventListeners'; export const socketMiddleware = () => { let areListenersSet = false; diff --git a/invokeai/frontend/web/src/services/events/util/setEventListeners.ts b/invokeai/frontend/web/src/services/events/util/setEventListeners.ts index a136c19f39..950cfb4083 100644 --- a/invokeai/frontend/web/src/services/events/util/setEventListeners.ts +++ b/invokeai/frontend/web/src/services/events/util/setEventListeners.ts @@ -1,5 +1,5 @@ import { MiddlewareAPI } from '@reduxjs/toolkit'; -import { AppDispatch, RootState } from 'app/store'; +import { AppDispatch, RootState } from 'app/store/store'; import { getTimestamp } from 'common/util/getTimestamp'; import { sessionCanceled } from 'services/thunks/session'; import { Socket } from 'socket.io-client'; From f0e07bff5a32e344fe0a665207cb08fd82e7f72c Mon Sep 17 00:00:00 2001 From: Lincoln Stein Date: Fri, 28 Apr 2023 15:39:00 -0400 Subject: [PATCH 28/68] fix bad logging path in config script --- invokeai/frontend/install/model_install.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/invokeai/frontend/install/model_install.py b/invokeai/frontend/install/model_install.py index 5822349bc6..12213b8b67 100644 --- a/invokeai/frontend/install/model_install.py +++ b/invokeai/frontend/install/model_install.py @@ -22,7 +22,7 @@ import torch from npyscreen import widget from omegaconf import OmegaConf -import invokeai.backend.logging as log +import invokeai.backend.util.logging as log from invokeai.backend.globals import Globals, global_config_dir from ...backend.config.model_install_backend import ( From e673ed08ec6d0cde2cb00480e0d5dfbc8f526d3a Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Fri, 28 Apr 2023 23:57:07 +1000 Subject: [PATCH 29/68] fix(ui): restore missing chakra-cli package (amending to try and get the workflow to run) --- invokeai/frontend/web/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/invokeai/frontend/web/package.json b/invokeai/frontend/web/package.json index 05ad90e89b..45f6b8e044 100644 --- a/invokeai/frontend/web/package.json +++ b/invokeai/frontend/web/package.json @@ -116,6 +116,7 @@ "@vitejs/plugin-react-swc": "^3.3.0", "axios": "^1.4.0", "babel-plugin-transform-imports": "^2.0.0", + "@chakra-ui/cli": "^2.4.0", "concurrently": "^8.0.1", "eslint": "^8.39.0", "eslint-config-prettier": "^8.8.0", From 8d837558acbeec3ed35bcdb360bb65b869daaea0 Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Sat, 29 Apr 2023 16:47:58 +1000 Subject: [PATCH 30/68] fix(ui): fix spelling of systemPersistDenylist.ts --- .../{systemPersistsDenylist.ts => systemPersistDenylist.ts} | 1 - 1 file changed, 1 deletion(-) rename invokeai/frontend/web/src/features/system/store/{systemPersistsDenylist.ts => systemPersistDenylist.ts} (96%) diff --git a/invokeai/frontend/web/src/features/system/store/systemPersistsDenylist.ts b/invokeai/frontend/web/src/features/system/store/systemPersistDenylist.ts similarity index 96% rename from invokeai/frontend/web/src/features/system/store/systemPersistsDenylist.ts rename to invokeai/frontend/web/src/features/system/store/systemPersistDenylist.ts index bac2a652b5..8a4d381775 100644 --- a/invokeai/frontend/web/src/features/system/store/systemPersistsDenylist.ts +++ b/invokeai/frontend/web/src/features/system/store/systemPersistDenylist.ts @@ -17,7 +17,6 @@ const itemsToDenylist: (keyof SystemState)[] = [ 'totalSteps', 'openModel', 'isCancelScheduled', - // 'sessionId', 'progressImage', 'wereModelsReceived', 'wasSchemaParsed', From a4c258e9ec138b377bd2b49d54ce0a09cf5087a8 Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Sat, 29 Apr 2023 16:50:54 +1000 Subject: [PATCH 31/68] feat(ui): add roarr logger --- invokeai/frontend/web/package.json | 8 +- invokeai/frontend/web/public/locales/en.json | 3 +- .../frontend/web/src/app/components/App.tsx | 6 +- .../frontend/web/src/app/logging/useLogger.ts | 93 +++++++++++++ invokeai/frontend/web/src/app/store/store.ts | 3 +- .../SettingsModal/SettingsModal.tsx | 21 ++- .../src/features/system/store/systemSlice.ts | 14 +- .../web/src/services/events/middleware.ts | 28 ++-- .../services/events/util/setEventListeners.ts | 9 +- .../web/src/services/thunks/gallery.ts | 7 + .../frontend/web/src/services/thunks/image.ts | 14 ++ .../frontend/web/src/services/thunks/model.ts | 8 +- .../web/src/services/thunks/schema.ts | 9 +- .../web/src/services/thunks/session.ts | 15 ++- invokeai/frontend/web/yarn.lock | 122 +++++++++++++++++- 15 files changed, 328 insertions(+), 32 deletions(-) create mode 100644 invokeai/frontend/web/src/app/logging/useLogger.ts diff --git a/invokeai/frontend/web/package.json b/invokeai/frontend/web/package.json index 45f6b8e044..6ee6a9c8f4 100644 --- a/invokeai/frontend/web/package.json +++ b/invokeai/frontend/web/package.json @@ -65,6 +65,7 @@ "@emotion/styled": "^11.10.6", "@fontsource/inter": "^4.5.15", "@reduxjs/toolkit": "^1.9.5", + "@roarr/browser-log-writer": "^1.1.5", "chakra-ui-contextmenu": "^1.0.5", "dateformat": "^5.0.3", "formik": "^2.2.9", @@ -93,17 +94,19 @@ "redux-deep-persist": "^1.0.7", "redux-dynamic-middlewares": "^2.2.0", "redux-persist": "^6.0.0", + "roarr": "^7.15.0", "socket.io-client": "^4.6.0", "use-image": "^1.1.0", "uuid": "^9.0.0" }, "peerDependencies": { + "@chakra-ui/cli": "^2.4.0", "react": "^18.2.0", "react-dom": "^18.2.0", - "ts-toolbelt": "^9.6.0", - "@chakra-ui/cli": "^2.4.0" + "ts-toolbelt": "^9.6.0" }, "devDependencies": { + "@chakra-ui/cli": "^2.4.0", "@types/dateformat": "^5.0.0", "@types/lodash-es": "^4.14.194", "@types/node": "^18.16.2", @@ -116,7 +119,6 @@ "@vitejs/plugin-react-swc": "^3.3.0", "axios": "^1.4.0", "babel-plugin-transform-imports": "^2.0.0", - "@chakra-ui/cli": "^2.4.0", "concurrently": "^8.0.1", "eslint": "^8.39.0", "eslint-config-prettier": "^8.8.0", diff --git a/invokeai/frontend/web/public/locales/en.json b/invokeai/frontend/web/public/locales/en.json index e5245c7ad5..d52f3c38c7 100644 --- a/invokeai/frontend/web/public/locales/en.json +++ b/invokeai/frontend/web/public/locales/en.json @@ -530,7 +530,8 @@ "resetWebUI": "Reset Web UI", "resetWebUIDesc1": "Resetting the web UI only resets the browser's local cache of your images and remembered settings. It does not delete any images from disk.", "resetWebUIDesc2": "If images aren't showing up in the gallery or something else isn't working, please try resetting before submitting an issue on GitHub.", - "resetComplete": "Web UI has been reset. Refresh the page to reload." + "resetComplete": "Web UI has been reset. Refresh the page to reload.", + "consoleLogLevel": "Console Log Level" }, "toast": { "serverError": "Server Error", diff --git a/invokeai/frontend/web/src/app/components/App.tsx b/invokeai/frontend/web/src/app/components/App.tsx index b33a7cac3f..b42c8a9c1a 100644 --- a/invokeai/frontend/web/src/app/components/App.tsx +++ b/invokeai/frontend/web/src/app/components/App.tsx @@ -27,6 +27,7 @@ import { PartialAppConfig } from 'app/types/invokeai'; import { useGlobalHotkeys } from 'common/hooks/useGlobalHotkeys'; import { configChanged } from 'features/system/store/configSlice'; import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus'; +import { useLogger } from 'app/logging/useLogger'; const DEFAULT_CONFIG = {}; @@ -37,6 +38,7 @@ interface Props extends PropsWithChildren { const App = ({ config = DEFAULT_CONFIG, children }: Props) => { useToastWatcher(); useGlobalHotkeys(); + const log = useLogger(); const currentTheme = useAppSelector((state) => state.ui.currentTheme); @@ -50,9 +52,9 @@ const App = ({ config = DEFAULT_CONFIG, children }: Props) => { const dispatch = useAppDispatch(); useEffect(() => { - console.log('Received config: ', config); + log.info({ namespace: 'App', data: config }, 'Received config'); dispatch(configChanged(config)); - }, [dispatch, config]); + }, [dispatch, config, log]); useEffect(() => { setColorMode(['light'].includes(currentTheme) ? 'light' : 'dark'); diff --git a/invokeai/frontend/web/src/app/logging/useLogger.ts b/invokeai/frontend/web/src/app/logging/useLogger.ts new file mode 100644 index 0000000000..ef1b27ad6b --- /dev/null +++ b/invokeai/frontend/web/src/app/logging/useLogger.ts @@ -0,0 +1,93 @@ +import { createSelector } from '@reduxjs/toolkit'; +import { useAppSelector } from 'app/store/storeHooks'; +import { systemSelector } from 'features/system/store/systemSelectors'; +import { isEqual } from 'lodash-es'; +import { useEffect } from 'react'; +import { LogLevelName, ROARR, Roarr } from 'roarr'; +import { createLogWriter } from '@roarr/browser-log-writer'; + +// Base logging context includes only the package name +const baseContext = { package: '@invoke-ai/invoke-ai-ui' }; + +// Create browser log writer +ROARR.write = createLogWriter(); + +// Module-scoped logger - can be imported and used anywhere +export let log = Roarr.child(baseContext); + +// Translate human-readable log levels to numbers, used for log filtering +export const LOG_LEVEL_MAP: Record = { + trace: 10, + debug: 20, + info: 30, + warn: 40, + error: 50, + fatal: 60, +}; + +export const VALID_LOG_LEVELS = [ + 'trace', + 'debug', + 'info', + 'warn', + 'error', + 'fatal', + 'none', +] as const; + +export type InvokeLogLevel = (typeof VALID_LOG_LEVELS)[number]; + +const selector = createSelector( + systemSelector, + (system) => { + const { app_version, consoleLogLevel } = system; + + return { + version: app_version, + consoleLogLevel, + }; + }, + { + memoizeOptions: { + resultEqualityCheck: isEqual, + }, + } +); + +export const useLogger = () => { + const { version, consoleLogLevel } = useAppSelector(selector); + + // The provided Roarr browser log writer uses localStorage to config logging to console + useEffect(() => { + if (consoleLogLevel === 'none') { + // Disable console log output + localStorage.setItem('ROARR_LOG', 'false'); + } else { + // Enable console log output + localStorage.setItem('ROARR_LOG', 'true'); + + // Use a filter to show only logs of the given level + localStorage.setItem( + 'ROARR_FILTER', + `context.logLevel:>=${LOG_LEVEL_MAP[consoleLogLevel]}` + ); + } + ROARR.write = createLogWriter(); + }, [consoleLogLevel]); + + // Update the module-scoped logger context as needed + useEffect(() => { + const newContext: Record = { + ...baseContext, + }; + + if (version) { + newContext.version = version; + } + + log = Roarr.child(newContext); + }, [version]); + + // Use the logger within components - no different than just importing it directly + return log; +}; diff --git a/invokeai/frontend/web/src/app/store/store.ts b/invokeai/frontend/web/src/app/store/store.ts index 8a805d6f16..627c4f0063 100644 --- a/invokeai/frontend/web/src/app/store/store.ts +++ b/invokeai/frontend/web/src/app/store/store.ts @@ -28,7 +28,7 @@ import { lightboxDenylist } from 'features/lightbox/store/lightboxPersistDenylis import { modelsDenylist } from 'features/system/store/modelsPersistDenylist'; import { nodesDenylist } from 'features/nodes/store/nodesPersistDenylist'; import { postprocessingDenylist } from 'features/parameters/store/postprocessingPersistDenylist'; -import { systemDenylist } from 'features/system/store/systemPersistsDenylist'; +import { systemDenylist } from 'features/system/store/systemPersistDenylist'; import { uiDenylist } from 'features/ui/store/uiPersistDenylist'; /** @@ -82,7 +82,6 @@ const rootPersistConfig = getPersistConfig({ 'hotkeys', 'config', ], - debounce: 300, }); const persistedReducer = persistReducer(rootPersistConfig, rootReducer); diff --git a/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsModal.tsx b/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsModal.tsx index 3edd6229a4..da4dbe2572 100644 --- a/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsModal.tsx +++ b/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsModal.tsx @@ -23,6 +23,7 @@ import IAISelect from 'common/components/IAISelect'; import IAISwitch from 'common/components/IAISwitch'; import { systemSelector } from 'features/system/store/systemSelectors'; import { + consoleLogLevelChanged, InProgressImageType, setEnableImageDebugging, setSaveIntermediatesInterval, @@ -39,8 +40,10 @@ import { import { UIState } from 'features/ui/store/uiTypes'; import { isEqual, map } from 'lodash-es'; import { persistor } from 'app/store/persistor'; -import { ChangeEvent, cloneElement, ReactElement } from 'react'; +import { ChangeEvent, cloneElement, ReactElement, useCallback } from 'react'; import { useTranslation } from 'react-i18next'; +import { InvokeLogLevel, VALID_LOG_LEVELS } from 'app/logging/useLogger'; +import { LogLevelName } from 'roarr'; const selector = createSelector( [systemSelector, uiSelector], @@ -52,6 +55,7 @@ const selector = createSelector( model_list, saveIntermediatesInterval, enableImageDebugging, + consoleLogLevel, } = system; const { shouldUseCanvasBetaLayout, shouldUseSliders } = ui; @@ -65,6 +69,7 @@ const selector = createSelector( enableImageDebugging, shouldUseCanvasBetaLayout, shouldUseSliders, + consoleLogLevel, }; }, { @@ -116,6 +121,7 @@ const SettingsModal = ({ children }: SettingsModalProps) => { enableImageDebugging, shouldUseCanvasBetaLayout, shouldUseSliders, + consoleLogLevel, } = useAppSelector(selector); /** @@ -135,6 +141,13 @@ const SettingsModal = ({ children }: SettingsModalProps) => { dispatch(setSaveIntermediatesInterval(value)); }; + const handleLogLevelChanged = useCallback( + (e: ChangeEvent) => { + dispatch(consoleLogLevelChanged(e.target.value as LogLevelName)); + }, + [dispatch] + ); + return ( <> {cloneElement(children, { @@ -211,6 +224,12 @@ const SettingsModal = ({ children }: SettingsModalProps) => { Developer + ) => { state.subscribedNodeIds = action.payload; }, + consoleLogLevelChanged: (state, action: PayloadAction) => { + state.consoleLogLevel = action.payload; + }, }, extraReducers(builder) { /** @@ -353,7 +363,6 @@ export const systemSlice = createSlice({ */ builder.addCase(socketSubscribed, (state, action) => { state.sessionId = action.payload.sessionId; - console.log(`Subscribed to session ${action.payload.sessionId}`); }); /** @@ -374,7 +383,7 @@ export const systemSlice = createSlice({ state.log.push({ timestamp, message: `Connected to server`, - level: 'info', + level: 'error', }); }); @@ -562,6 +571,7 @@ export const { scheduledCancelAborted, cancelTypeChanged, subscribedNodeIdsSet, + consoleLogLevelChanged, } = systemSlice.actions; export default systemSlice.reducer; diff --git a/invokeai/frontend/web/src/services/events/middleware.ts b/invokeai/frontend/web/src/services/events/middleware.ts index 824e48648c..0b52ae8f0b 100644 --- a/invokeai/frontend/web/src/services/events/middleware.ts +++ b/invokeai/frontend/web/src/services/events/middleware.ts @@ -6,13 +6,9 @@ import { ServerToClientEvents, } from 'services/events/types'; import { - generatorProgress, invocationComplete, - invocationError, - invocationStarted, socketConnected, socketDisconnected, - socketReset, socketSubscribed, socketUnsubscribed, } from './actions'; @@ -25,7 +21,6 @@ import { getTimestamp } from 'common/util/getTimestamp'; import { sessionInvoked, isFulfilledSessionCreatedAction, - sessionCanceled, } from 'services/thunks/session'; import { OpenAPI } from 'services/api'; import { receivedModels } from 'services/thunks/model'; @@ -33,6 +28,9 @@ import { receivedOpenAPISchema } from 'services/thunks/schema'; import { isImageOutput } from 'services/types/guards'; import { imageReceived, thumbnailReceived } from 'services/thunks/image'; import { setEventListeners } from 'services/events/util/setEventListeners'; +import { log } from 'app/logging/useLogger'; + +const moduleLog = log.child({ namespace: 'socketio' }); export const socketMiddleware = () => { let areListenersSet = false; @@ -91,6 +89,8 @@ export const socketMiddleware = () => { // Must happen in middleware to get access to `dispatch` if (!areListenersSet) { socket.on('connect', () => { + moduleLog.debug('Connected'); + dispatch(socketConnected({ timestamp: getTimestamp() })); const { results, uploads, models, nodes, config, system } = @@ -116,7 +116,10 @@ export const socketMiddleware = () => { } if (system.sessionId) { - console.log(`Re-subscribing to session ${system.sessionId}`); + const sessionLog = moduleLog.child({ sessionId: system.sessionId }); + + sessionLog.debug('Re-subscribe'); + socket.emit('subscribe', { session: system.sessionId }); dispatch( socketSubscribed({ @@ -124,11 +127,12 @@ export const socketMiddleware = () => { timestamp: getTimestamp(), }) ); - setEventListeners({ socket, store }); + setEventListeners({ socket, store, sessionLog }); } }); socket.on('disconnect', () => { + moduleLog.debug('Disconnected'); dispatch(socketDisconnected({ timestamp: getTimestamp() })); }); @@ -140,6 +144,8 @@ export const socketMiddleware = () => { // Everything else only happens once we have created a session if (isFulfilledSessionCreatedAction(action)) { + const sessionId = action.payload.id; + const sessionLog = moduleLog.child({ sessionId }); const oldSessionId = getState().system.sessionId; // const subscribedNodeIds = getState().system.subscribedNodeIds; @@ -152,6 +158,9 @@ export const socketMiddleware = () => { // }; if (oldSessionId) { + sessionLog + .child({ oldSessionId }) + .debug('Unsubscribe from old session'); // Unsubscribe when invocations complete socket.emit('unsubscribe', { session: oldSessionId, @@ -176,8 +185,7 @@ export const socketMiddleware = () => { }); } - const sessionId = action.payload.id; - + sessionLog.debug('Subscribe'); socket.emit('subscribe', { session: sessionId }); dispatch( socketSubscribed({ @@ -185,7 +193,7 @@ export const socketMiddleware = () => { timestamp: getTimestamp(), }) ); - setEventListeners({ socket, store }); + setEventListeners({ socket, store, sessionLog }); // Finally we actually invoke the session, starting processing dispatch(sessionInvoked({ sessionId })); diff --git a/invokeai/frontend/web/src/services/events/util/setEventListeners.ts b/invokeai/frontend/web/src/services/events/util/setEventListeners.ts index 950cfb4083..b7599df9cc 100644 --- a/invokeai/frontend/web/src/services/events/util/setEventListeners.ts +++ b/invokeai/frontend/web/src/services/events/util/setEventListeners.ts @@ -10,29 +10,36 @@ import { invocationStarted, } from '../actions'; import { ClientToServerEvents, ServerToClientEvents } from '../types'; +import { Logger } from 'roarr'; +import { JsonObject } from 'roarr/dist/types'; type SetEventListenersArg = { socket: Socket; store: MiddlewareAPI; + sessionLog: Logger; }; export const setEventListeners = (arg: SetEventListenersArg) => { - const { socket, store } = arg; + const { socket, store, sessionLog } = arg; const { dispatch, getState } = store; // Set up listeners for the present subscription socket.on('invocation_started', (data) => { + sessionLog.child({ data }).info('Invocation started'); dispatch(invocationStarted({ data, timestamp: getTimestamp() })); }); socket.on('generator_progress', (data) => { + sessionLog.child({ data }).trace('Generator progress'); dispatch(generatorProgress({ data, timestamp: getTimestamp() })); }); socket.on('invocation_error', (data) => { + sessionLog.child({ data }).error('Invocation error'); dispatch(invocationError({ data, timestamp: getTimestamp() })); }); socket.on('invocation_complete', (data) => { + sessionLog.child({ data }).info('Invocation complete'); const sessionId = data.graph_execution_state_id; const { cancelType, isCancelScheduled } = getState().system; diff --git a/invokeai/frontend/web/src/services/thunks/gallery.ts b/invokeai/frontend/web/src/services/thunks/gallery.ts index 4361ce1499..824baa1bca 100644 --- a/invokeai/frontend/web/src/services/thunks/gallery.ts +++ b/invokeai/frontend/web/src/services/thunks/gallery.ts @@ -1,8 +1,11 @@ +import { log } from 'app/logging/useLogger'; import { createAppAsyncThunk } from 'app/store/storeUtils'; import { ImagesService } from 'services/api'; export const IMAGES_PER_PAGE = 20; +const galleryLog = log.child({ namespace: 'gallery' }); + export const receivedResultImagesPage = createAppAsyncThunk( 'results/receivedResultImagesPage', async (_arg, { getState }) => { @@ -12,6 +15,8 @@ export const receivedResultImagesPage = createAppAsyncThunk( perPage: IMAGES_PER_PAGE, }); + galleryLog.info({ response }, 'Received page of results images'); + return response; } ); @@ -25,6 +30,8 @@ export const receivedUploadImagesPage = createAppAsyncThunk( perPage: IMAGES_PER_PAGE, }); + galleryLog.info({ response }, 'Received page of uploads images'); + return response; } ); diff --git a/invokeai/frontend/web/src/services/thunks/image.ts b/invokeai/frontend/web/src/services/thunks/image.ts index d9fdd1c589..7010e1565a 100644 --- a/invokeai/frontend/web/src/services/thunks/image.ts +++ b/invokeai/frontend/web/src/services/thunks/image.ts @@ -1,10 +1,13 @@ import { isFulfilled, isRejected } from '@reduxjs/toolkit'; +import { log } from 'app/logging/useLogger'; import { createAppAsyncThunk } from 'app/store/storeUtils'; import { imageSelected } from 'features/gallery/store/gallerySlice'; import { clamp } from 'lodash-es'; import { ImagesService } from 'services/api'; import { getHeaders } from 'services/util/getHeaders'; +const imagesLog = log.child({ namespace: 'image' }); + type ImageReceivedArg = Parameters<(typeof ImagesService)['getImage']>[0]; /** @@ -14,6 +17,9 @@ export const imageReceived = createAppAsyncThunk( 'api/imageReceived', async (arg: ImageReceivedArg, _thunkApi) => { const response = await ImagesService.getImage(arg); + + imagesLog.info({ arg, response }, 'Received image'); + return response; } ); @@ -29,6 +35,9 @@ export const thumbnailReceived = createAppAsyncThunk( 'api/thumbnailReceived', async (arg: ThumbnailReceivedArg, _thunkApi) => { const response = await ImagesService.getThumbnail(arg); + + imagesLog.info({ arg, response }, 'Received thumbnail'); + return response; } ); @@ -43,6 +52,9 @@ export const imageUploaded = createAppAsyncThunk( async (arg: ImageUploadedArg, _thunkApi) => { const response = await ImagesService.uploadImage(arg); const { location } = getHeaders(response); + + imagesLog.info({ arg: '', response, location }, 'Image uploaded'); + return { response, location }; } ); @@ -96,6 +108,8 @@ export const imageDeleted = createAppAsyncThunk( const response = await ImagesService.deleteImage(arg); + imagesLog.info({ arg, response }, 'Image deleted'); + return response; } ); diff --git a/invokeai/frontend/web/src/services/thunks/model.ts b/invokeai/frontend/web/src/services/thunks/model.ts index a4aac7563d..78d74569dc 100644 --- a/invokeai/frontend/web/src/services/thunks/model.ts +++ b/invokeai/frontend/web/src/services/thunks/model.ts @@ -1,14 +1,18 @@ +import { log } from 'app/logging/useLogger'; import { createAppAsyncThunk } from 'app/store/storeUtils'; import { Model } from 'features/system/store/modelSlice'; import { reduce } from 'lodash-es'; import { ModelsService } from 'services/api'; +const models = log.child({ namespace: 'model' }); + export const IMAGES_PER_PAGE = 20; export const receivedModels = createAppAsyncThunk( 'models/receivedModels', - async (_arg) => { + async (_) => { const response = await ModelsService.listModels(); + const deserializedModels = reduce( response.models, (modelsAccumulator, model, modelName) => { @@ -19,6 +23,8 @@ export const receivedModels = createAppAsyncThunk( {} as Record ); + models.info({ response }, 'Received models'); + return deserializedModels; } ); diff --git a/invokeai/frontend/web/src/services/thunks/schema.ts b/invokeai/frontend/web/src/services/thunks/schema.ts index 7da8514427..bc93fa0fae 100644 --- a/invokeai/frontend/web/src/services/thunks/schema.ts +++ b/invokeai/frontend/web/src/services/thunks/schema.ts @@ -1,16 +1,19 @@ import { createAsyncThunk } from '@reduxjs/toolkit'; +import { log } from 'app/logging/useLogger'; import { parsedOpenAPISchema } from 'features/nodes/store/nodesSlice'; import { OpenAPIV3 } from 'openapi-types'; +const schemaLog = log.child({ namespace: 'schema' }); + export const receivedOpenAPISchema = createAsyncThunk( 'nodes/receivedOpenAPISchema', async (_, { dispatch }): Promise => { const response = await fetch(`openapi.json`); - const openAPISchema = (await response.json()) as OpenAPIV3.Document; + const openAPISchema = await response.json(); - console.debug('OpenAPI schema: ', openAPISchema); + schemaLog.info({ openAPISchema }, 'Received OpenAPI schema'); - dispatch(parsedOpenAPISchema(openAPISchema)); + dispatch(parsedOpenAPISchema(openAPISchema as OpenAPIV3.Document)); return openAPISchema; } diff --git a/invokeai/frontend/web/src/services/thunks/session.ts b/invokeai/frontend/web/src/services/thunks/session.ts index ba796f7467..ff9592e8c8 100644 --- a/invokeai/frontend/web/src/services/thunks/session.ts +++ b/invokeai/frontend/web/src/services/thunks/session.ts @@ -3,6 +3,9 @@ import { SessionsService } from 'services/api'; import { buildLinearGraph as buildGenerateGraph } from 'features/nodes/util/linearGraphBuilder/buildLinearGraph'; import { isAnyOf, isFulfilled } from '@reduxjs/toolkit'; import { buildNodesGraph } from 'features/nodes/util/nodesGraphBuilder/buildNodesGraph'; +import { log } from 'app/logging/useLogger'; + +const sessionLog = log.child({ namespace: 'session' }); export const generateGraphBuilt = createAppAsyncThunk( 'api/generateGraphBuilt', @@ -43,12 +46,12 @@ type SessionCreatedArg = { export const sessionCreated = createAppAsyncThunk( 'api/sessionCreated', async (arg: SessionCreatedArg, { dispatch, getState }) => { - console.log('Session created, graph: ', arg.graph); - const response = await SessionsService.createSession({ requestBody: arg.graph, }); + sessionLog.info({ arg, response }, 'Session created'); + return response; } ); @@ -74,6 +77,8 @@ export const nodeAdded = createAppAsyncThunk( sessionId: arg.sessionId, }); + sessionLog.info({ arg, response }, 'Node added'); + return response; } ); @@ -91,6 +96,8 @@ export const sessionInvoked = createAppAsyncThunk( all: true, }); + sessionLog.info({ arg, response }, 'Session invoked'); + return response; } ); @@ -111,6 +118,8 @@ export const sessionCanceled = createAppAsyncThunk( sessionId, }); + sessionLog.info({ arg, response }, 'Session canceled'); + return response; } ); @@ -127,6 +136,8 @@ export const listedSessions = createAppAsyncThunk( async (arg: SessionsListedArg, _thunkApi) => { const response = await SessionsService.listSessions(arg); + sessionLog.info({ arg, response }, 'Sessions listed'); + return response; } ); diff --git a/invokeai/frontend/web/yarn.lock b/invokeai/frontend/web/yarn.lock index b0811ad877..f117d4f2de 100644 --- a/invokeai/frontend/web/yarn.lock +++ b/invokeai/frontend/web/yarn.lock @@ -1421,6 +1421,15 @@ redux-thunk "^2.4.2" reselect "^4.1.8" +"@roarr/browser-log-writer@^1.1.5": + version "1.1.5" + resolved "https://registry.yarnpkg.com/@roarr/browser-log-writer/-/browser-log-writer-1.1.5.tgz#755ff62ddaa297bb3488067408a7085db382352b" + integrity sha512-yLn//DRjh1/rUgZpZkwmT/5RqHYfkdOwGXWXnKBR3l/HE04DIhSVeYin3sc8aWHBa7s7WglQpYX/uw/WI6POpw== + dependencies: + boolean "^3.1.4" + globalthis "^1.0.2" + liqe "^3.6.0" + "@rollup/pluginutils@^4.2.1": version "4.2.1" resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-4.2.1.tgz#e6c6c3aba0744edce3fb2074922d3776c0af2a6d" @@ -2077,7 +2086,7 @@ aggregate-error@^3.0.0: clean-stack "^2.0.0" indent-string "^4.0.0" -ajv@^6.10.0, ajv@^6.12.4, ajv@~6.12.6: +ajv@^6.10.0, ajv@^6.11.0, ajv@^6.12.4, ajv@~6.12.6: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -2307,6 +2316,11 @@ bl@^4.1.0: inherits "^2.0.4" readable-stream "^3.4.0" +boolean@^3.1.4: + version "3.2.0" + resolved "https://registry.yarnpkg.com/boolean/-/boolean-3.2.0.tgz#9e5294af4e98314494cbb17979fa54ca159f116b" + integrity sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw== + boxen@^5.0.0: version "5.1.2" resolved "https://registry.yarnpkg.com/boxen/-/boxen-5.1.2.tgz#788cb686fc83c1f486dfa8a40c68fc2b831d2b50" @@ -2609,7 +2623,7 @@ commander@^10.0.0: resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== -commander@^2.16.0, commander@^2.20.0, commander@^2.20.3, commander@^2.8.1: +commander@^2.16.0, commander@^2.19.0, commander@^2.20.0, commander@^2.20.3, commander@^2.8.1: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== @@ -2828,6 +2842,11 @@ deepmerge@^2.1.1: resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-2.2.1.tgz#5d3ff22a01c00f645405a2fbc17d0778a1801170" integrity sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA== +deepmerge@^4.2.2: + version "4.3.1" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" + integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== + defaults@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.4.tgz#b0b02062c1e2aa62ff5d9528f0f98baa90978d7a" @@ -3031,6 +3050,11 @@ dir-glob@^3.0.1: dependencies: path-type "^4.0.0" +discontinuous-range@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/discontinuous-range/-/discontinuous-range-1.0.0.tgz#e38331f0844bba49b9a9cb71c771585aab1bc65a" + integrity sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ== + doctrine@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" @@ -3442,11 +3466,28 @@ fast-json-stable-stringify@^2.0.0: resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== +fast-json-stringify@^2.7.10: + version "2.7.13" + resolved "https://registry.yarnpkg.com/fast-json-stringify/-/fast-json-stringify-2.7.13.tgz#277aa86c2acba4d9851bd6108ed657aa327ed8c0" + integrity sha512-ar+hQ4+OIurUGjSJD1anvYSDcUflywhKjfxnsW4TBTD7+u0tJufv6DKRWoQk3vI6YBOWMoz0TQtfbe7dxbQmvA== + dependencies: + ajv "^6.11.0" + deepmerge "^4.2.2" + rfdc "^1.2.0" + string-similarity "^4.0.1" + fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== +fast-printf@^1.6.9: + version "1.6.9" + resolved "https://registry.yarnpkg.com/fast-printf/-/fast-printf-1.6.9.tgz#212f56570d2dc8ccdd057ee93d50dd414d07d676" + integrity sha512-FChq8hbz65WMj4rstcQsFB0O7Cy++nmbNfLYnD9cYv2cRn8EG6k/MGn9kO/tjO66t09DLDugj3yL+V2o6Qftrg== + dependencies: + boolean "^3.1.4" + fastq@^1.6.0: version "1.15.0" resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a" @@ -3768,7 +3809,7 @@ globals@^13.19.0: dependencies: type-fest "^0.20.2" -globalthis@^1.0.3: +globalthis@^1.0.2, globalthis@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf" integrity sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA== @@ -4465,6 +4506,14 @@ lint-staged@^13.2.2: string-argv "^0.3.1" yaml "^2.2.2" +liqe@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/liqe/-/liqe-3.6.0.tgz#2d05376e93ff9f4bfdb3e76481f6456d165b499f" + integrity sha512-CYVQr0bk5CCTkX3wW2MdyEWdr9FHLpiE/1cQXQ36Sdjn5gv7JIpm9jnkovFwiVzumw7f6JDFXpljwUY+fAcFYQ== + dependencies: + nearley "^2.20.1" + ts-error "^1.0.6" + listr2@^5.0.7: version "5.0.8" resolved "https://registry.yarnpkg.com/listr2/-/listr2-5.0.8.tgz#a9379ffeb4bd83a68931a65fb223a11510d6ba23" @@ -4714,6 +4763,11 @@ module-lookup-amd@^7.0.1: requirejs "^2.3.5" requirejs-config-file "^4.0.0" +moo@^0.5.0: + version "0.5.2" + resolved "https://registry.yarnpkg.com/moo/-/moo-0.5.2.tgz#f9fe82473bc7c184b0d32e2215d3f6e67278733c" + integrity sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q== + ms@2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" @@ -4734,6 +4788,16 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== +nearley@^2.20.1: + version "2.20.1" + resolved "https://registry.yarnpkg.com/nearley/-/nearley-2.20.1.tgz#246cd33eff0d012faf197ff6774d7ac78acdd474" + integrity sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ== + dependencies: + commander "^2.19.0" + moo "^0.5.0" + railroad-diagrams "^1.0.0" + randexp "0.4.6" + neo-async@^2.6.0: version "2.6.2" resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" @@ -5215,6 +5279,19 @@ quote-unquote@^1.0.0: resolved "https://registry.yarnpkg.com/quote-unquote/-/quote-unquote-1.0.0.tgz#67a9a77148effeaf81a4d428404a710baaac8a0b" integrity sha512-twwRO/ilhlG/FIgYeKGFqyHhoEhqgnKVkcmqMKi2r524gz3ZbDTcyFt38E9xjJI2vT+KbRNHVbnJ/e0I25Azwg== +railroad-diagrams@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz#eb7e6267548ddedfb899c1b90e57374559cddb7e" + integrity sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A== + +randexp@0.4.6: + version "0.4.6" + resolved "https://registry.yarnpkg.com/randexp/-/randexp-0.4.6.tgz#e986ad5e5e31dae13ddd6f7b3019aa7c87f60ca3" + integrity sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ== + dependencies: + discontinuous-range "1.0.0" + ret "~0.1.10" + rc@1.2.8, rc@^1.2.7, rc@^1.2.8: version "1.2.8" resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" @@ -5554,12 +5631,17 @@ restore-cursor@^3.1.0: onetime "^5.1.0" signal-exit "^3.0.2" +ret@~0.1.10: + version "0.1.15" + resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" + integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== + reusify@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== -rfdc@^1.3.0: +rfdc@^1.2.0, rfdc@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b" integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA== @@ -5578,6 +5660,18 @@ rimraf@^3.0.2: dependencies: glob "^7.1.3" +roarr@^7.15.0: + version "7.15.0" + resolved "https://registry.yarnpkg.com/roarr/-/roarr-7.15.0.tgz#09b792f0cd31b4a7f91030bb1c47550ceec98ee4" + integrity sha512-CV9WefQfUXTX6wr8CrEMhfNef3sjIt9wNhE/5PNu4tNWsaoDNDXqq+OGn/RW9A1UPb0qc7FQlswXRaJJJsqn8A== + dependencies: + boolean "^3.1.4" + fast-json-stringify "^2.7.10" + fast-printf "^1.6.9" + globalthis "^1.0.2" + safe-stable-stringify "^2.4.1" + semver-compare "^1.0.0" + rollup-plugin-visualizer@^5.9.0: version "5.9.0" resolved "https://registry.yarnpkg.com/rollup-plugin-visualizer/-/rollup-plugin-visualizer-5.9.0.tgz#013ac54fb6a9d7c9019e7eb77eced673399e5a0b" @@ -5630,6 +5724,11 @@ safe-regex-test@^1.0.0: get-intrinsic "^1.1.3" is-regex "^1.1.4" +safe-stable-stringify@^2.4.1: + version "2.4.3" + resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz#138c84b6f6edb3db5f8ef3ef7115b8f55ccbf886" + integrity sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g== + sass-lookup@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/sass-lookup/-/sass-lookup-3.0.0.tgz#3b395fa40569738ce857bc258e04df2617c48cac" @@ -5644,6 +5743,11 @@ scheduler@^0.23.0: dependencies: loose-envify "^1.1.0" +semver-compare@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc" + integrity sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow== + semver-diff@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-3.1.1.tgz#05f77ce59f325e00e2706afd67bb506ddb1ca32b" @@ -5810,6 +5914,11 @@ string-argv@^0.3.1, string-argv@~0.3.1: resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.1.tgz#95e2fbec0427ae19184935f816d74aaa4c5c19da" integrity sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg== +string-similarity@^4.0.1: + version "4.0.4" + resolved "https://registry.yarnpkg.com/string-similarity/-/string-similarity-4.0.4.tgz#42d01ab0b34660ea8a018da8f56a3309bb8b2a5b" + integrity sha512-/q/8Q4Bl4ZKAPjj8WerIBJWALKkaPRfrvhfF8k/B23i4nzrlRj2/go1m90In7nG/3XDSbOo0+pu6RvCTM9RGMQ== + string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" @@ -6032,6 +6141,11 @@ tree-kill@^1.2.2: resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc" integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== +ts-error@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/ts-error/-/ts-error-1.0.6.tgz#277496f2a28de6c184cfce8dfd5cdd03a4e6b0fc" + integrity sha512-tLJxacIQUM82IR7JO1UUkKlYuUTmoY9HBJAmNWFzheSlDS5SPMcNIepejHJa4BpPQLAcbRhRf3GDJzyj6rbKvA== + ts-graphviz@^1.5.0: version "1.6.1" resolved "https://registry.yarnpkg.com/ts-graphviz/-/ts-graphviz-1.6.1.tgz#f44525c048cb8c8c188b7324d2a91015fd31ceaf" From bffdede0fa355f3ca6f8ba57c0b8b68ab98ec309 Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Sat, 29 Apr 2023 17:20:49 +1000 Subject: [PATCH 32/68] feat(ui): improve log messages --- .../web/src/features/nodes/store/nodesSlice.ts | 9 ++++++++- .../web/src/services/events/actions.ts | 5 +++++ .../web/src/services/events/middleware.ts | 13 ++++++++----- .../services/events/util/setEventListeners.ts | 18 ++++++++++++++---- .../web/src/services/thunks/gallery.ts | 4 ++-- .../frontend/web/src/services/thunks/image.ts | 10 ++++++++-- .../frontend/web/src/services/thunks/model.ts | 4 ++-- .../web/src/services/thunks/session.ts | 13 ++++++++----- 8 files changed, 55 insertions(+), 21 deletions(-) diff --git a/invokeai/frontend/web/src/features/nodes/store/nodesSlice.ts b/invokeai/frontend/web/src/features/nodes/store/nodesSlice.ts index 960625135a..d0202a5932 100644 --- a/invokeai/frontend/web/src/features/nodes/store/nodesSlice.ts +++ b/invokeai/frontend/web/src/features/nodes/store/nodesSlice.ts @@ -16,6 +16,8 @@ import { receivedOpenAPISchema } from 'services/thunks/schema'; import { isFulfilledAnyGraphBuilt } from 'services/thunks/session'; import { InvocationTemplate, InvocationValue } from '../types/types'; import { parseSchema } from '../util/parseSchema'; +import { log } from 'app/logging/useLogger'; +import { size } from 'lodash-es'; export type NodesState = { nodes: Node[]; @@ -85,7 +87,12 @@ const nodesSlice = createSlice({ parsedOpenAPISchema: (state, action: PayloadAction) => { try { const parsedSchema = parseSchema(action.payload); - console.debug('Parsed schema: ', parsedSchema); + + // TODO: Achtung! Side effect in a reducer! + log.info( + { namespace: 'schema', nodes: parsedSchema }, + `Parsed ${size(parsedSchema)} nodes` + ); state.invocationTemplates = parsedSchema; } catch (err) { console.error(err); diff --git a/invokeai/frontend/web/src/services/events/actions.ts b/invokeai/frontend/web/src/services/events/actions.ts index 5ea0a1e9e1..84268773a9 100644 --- a/invokeai/frontend/web/src/services/events/actions.ts +++ b/invokeai/frontend/web/src/services/events/actions.ts @@ -1,6 +1,7 @@ import { createAction } from '@reduxjs/toolkit'; import { GeneratorProgressEvent, + GraphExecutionStateCompleteEvent, InvocationCompleteEvent, InvocationErrorEvent, InvocationStartedEvent, @@ -45,6 +46,10 @@ export const invocationError = createAction< BaseSocketPayload & { data: InvocationErrorEvent } >('socket/invocationError'); +export const graphExecutionStateComplete = createAction< + BaseSocketPayload & { data: GraphExecutionStateCompleteEvent } +>('socket/graphExecutionStateComplete'); + export const generatorProgress = createAction< BaseSocketPayload & { data: GeneratorProgressEvent } >('socket/generatorProgress'); diff --git a/invokeai/frontend/web/src/services/events/middleware.ts b/invokeai/frontend/web/src/services/events/middleware.ts index 0b52ae8f0b..e57851e19c 100644 --- a/invokeai/frontend/web/src/services/events/middleware.ts +++ b/invokeai/frontend/web/src/services/events/middleware.ts @@ -118,7 +118,9 @@ export const socketMiddleware = () => { if (system.sessionId) { const sessionLog = moduleLog.child({ sessionId: system.sessionId }); - sessionLog.debug('Re-subscribe'); + sessionLog.debug( + `Subscribed to existing session (${system.sessionId})` + ); socket.emit('subscribe', { session: system.sessionId }); dispatch( @@ -158,9 +160,10 @@ export const socketMiddleware = () => { // }; if (oldSessionId) { - sessionLog - .child({ oldSessionId }) - .debug('Unsubscribe from old session'); + sessionLog.debug( + { oldSessionId }, + `Unsubscribed from old session (${oldSessionId})` + ); // Unsubscribe when invocations complete socket.emit('unsubscribe', { session: oldSessionId, @@ -185,7 +188,7 @@ export const socketMiddleware = () => { }); } - sessionLog.debug('Subscribe'); + sessionLog.debug(`Subscribe to new session (${sessionId})`); socket.emit('subscribe', { session: sessionId }); dispatch( socketSubscribed({ diff --git a/invokeai/frontend/web/src/services/events/util/setEventListeners.ts b/invokeai/frontend/web/src/services/events/util/setEventListeners.ts index b7599df9cc..90a285d238 100644 --- a/invokeai/frontend/web/src/services/events/util/setEventListeners.ts +++ b/invokeai/frontend/web/src/services/events/util/setEventListeners.ts @@ -5,6 +5,7 @@ import { sessionCanceled } from 'services/thunks/session'; import { Socket } from 'socket.io-client'; import { generatorProgress, + graphExecutionStateComplete, invocationComplete, invocationError, invocationStarted, @@ -24,22 +25,22 @@ export const setEventListeners = (arg: SetEventListenersArg) => { const { dispatch, getState } = store; // Set up listeners for the present subscription socket.on('invocation_started', (data) => { - sessionLog.child({ data }).info('Invocation started'); + sessionLog.child({ data }).info(`Invocation started (${data.node.type})`); dispatch(invocationStarted({ data, timestamp: getTimestamp() })); }); socket.on('generator_progress', (data) => { - sessionLog.child({ data }).trace('Generator progress'); + sessionLog.child({ data }).trace(`Generator progress (${data.node.type})`); dispatch(generatorProgress({ data, timestamp: getTimestamp() })); }); socket.on('invocation_error', (data) => { - sessionLog.child({ data }).error('Invocation error'); + sessionLog.child({ data }).error(`Invocation error (${data.node.type})`); dispatch(invocationError({ data, timestamp: getTimestamp() })); }); socket.on('invocation_complete', (data) => { - sessionLog.child({ data }).info('Invocation complete'); + sessionLog.child({ data }).info(`Invocation complete (${data.node.type})`); const sessionId = data.graph_execution_state_id; const { cancelType, isCancelScheduled } = getState().system; @@ -58,4 +59,13 @@ export const setEventListeners = (arg: SetEventListenersArg) => { }) ); }); + + socket.on('graph_execution_state_complete', (data) => { + sessionLog + .child({ data }) + .info( + `Graph execution state complete (${data.graph_execution_state_id})` + ); + dispatch(graphExecutionStateComplete({ data, timestamp: getTimestamp() })); + }); }; diff --git a/invokeai/frontend/web/src/services/thunks/gallery.ts b/invokeai/frontend/web/src/services/thunks/gallery.ts index 824baa1bca..f908cbddcb 100644 --- a/invokeai/frontend/web/src/services/thunks/gallery.ts +++ b/invokeai/frontend/web/src/services/thunks/gallery.ts @@ -15,7 +15,7 @@ export const receivedResultImagesPage = createAppAsyncThunk( perPage: IMAGES_PER_PAGE, }); - galleryLog.info({ response }, 'Received page of results images'); + galleryLog.info({ response }, `Received ${response.items.length} results`); return response; } @@ -30,7 +30,7 @@ export const receivedUploadImagesPage = createAppAsyncThunk( perPage: IMAGES_PER_PAGE, }); - galleryLog.info({ response }, 'Received page of uploads images'); + galleryLog.info({ response }, `Received ${response.items.length} uploads`); return response; } diff --git a/invokeai/frontend/web/src/services/thunks/image.ts b/invokeai/frontend/web/src/services/thunks/image.ts index 7010e1565a..c4da9d9f16 100644 --- a/invokeai/frontend/web/src/services/thunks/image.ts +++ b/invokeai/frontend/web/src/services/thunks/image.ts @@ -53,7 +53,10 @@ export const imageUploaded = createAppAsyncThunk( const response = await ImagesService.uploadImage(arg); const { location } = getHeaders(response); - imagesLog.info({ arg: '', response, location }, 'Image uploaded'); + imagesLog.info( + { arg: '', response, location }, + `Image uploaded (${response.image_name})` + ); return { response, location }; } @@ -108,7 +111,10 @@ export const imageDeleted = createAppAsyncThunk( const response = await ImagesService.deleteImage(arg); - imagesLog.info({ arg, response }, 'Image deleted'); + imagesLog.info( + { arg, response }, + `Image deleted (${arg.imageType} - ${arg.imageName})` + ); return response; } diff --git a/invokeai/frontend/web/src/services/thunks/model.ts b/invokeai/frontend/web/src/services/thunks/model.ts index 78d74569dc..84f7a24e81 100644 --- a/invokeai/frontend/web/src/services/thunks/model.ts +++ b/invokeai/frontend/web/src/services/thunks/model.ts @@ -1,7 +1,7 @@ import { log } from 'app/logging/useLogger'; import { createAppAsyncThunk } from 'app/store/storeUtils'; import { Model } from 'features/system/store/modelSlice'; -import { reduce } from 'lodash-es'; +import { reduce, size } from 'lodash-es'; import { ModelsService } from 'services/api'; const models = log.child({ namespace: 'model' }); @@ -23,7 +23,7 @@ export const receivedModels = createAppAsyncThunk( {} as Record ); - models.info({ response }, 'Received models'); + models.info({ response }, `Received ${size(response.models)} models`); return deserializedModels; } diff --git a/invokeai/frontend/web/src/services/thunks/session.ts b/invokeai/frontend/web/src/services/thunks/session.ts index ff9592e8c8..0641437d52 100644 --- a/invokeai/frontend/web/src/services/thunks/session.ts +++ b/invokeai/frontend/web/src/services/thunks/session.ts @@ -50,7 +50,7 @@ export const sessionCreated = createAppAsyncThunk( requestBody: arg.graph, }); - sessionLog.info({ arg, response }, 'Session created'); + sessionLog.info({ arg, response }, `Session created (${response.id})`); return response; } @@ -77,7 +77,7 @@ export const nodeAdded = createAppAsyncThunk( sessionId: arg.sessionId, }); - sessionLog.info({ arg, response }, 'Node added'); + sessionLog.info({ arg, response }, `Node added (${response})`); return response; } @@ -96,7 +96,7 @@ export const sessionInvoked = createAppAsyncThunk( all: true, }); - sessionLog.info({ arg, response }, 'Session invoked'); + sessionLog.info({ arg, response }, `Session invoked (${sessionId})`); return response; } @@ -118,7 +118,7 @@ export const sessionCanceled = createAppAsyncThunk( sessionId, }); - sessionLog.info({ arg, response }, 'Session canceled'); + sessionLog.info({ arg, response }, `Session canceled (${sessionId})`); return response; } @@ -136,7 +136,10 @@ export const listedSessions = createAppAsyncThunk( async (arg: SessionsListedArg, _thunkApi) => { const response = await SessionsService.listSessions(arg); - sessionLog.info({ arg, response }, 'Sessions listed'); + sessionLog.info( + { arg, response }, + `Sessions listed (${response.items.length})` + ); return response; } From 6d6b986a668af8ffae55af90f45be8f10cdcf0a2 Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Sat, 29 Apr 2023 17:22:03 +1000 Subject: [PATCH 33/68] feat(ui): remove Console and redux logging state --- .../frontend/web/src/app/components/App.tsx | 4 - .../frontend/web/src/app/socketio/emitters.ts | 1 - .../web/src/app/socketio/listeners.ts | 1 - .../features/system/components/Console.tsx | 197 ------------------ .../src/features/system/store/systemSlice.ts | 65 +----- 5 files changed, 1 insertion(+), 267 deletions(-) delete mode 100644 invokeai/frontend/web/src/features/system/components/Console.tsx diff --git a/invokeai/frontend/web/src/app/components/App.tsx b/invokeai/frontend/web/src/app/components/App.tsx index b42c8a9c1a..37d0c7ba72 100644 --- a/invokeai/frontend/web/src/app/components/App.tsx +++ b/invokeai/frontend/web/src/app/components/App.tsx @@ -1,5 +1,4 @@ import ImageUploader from 'common/components/ImageUploader'; -import Console from 'features/system/components/Console'; import ProgressBar from 'features/system/components/ProgressBar'; import SiteHeader from 'features/system/components/SiteHeader'; import InvokeTabs from 'features/ui/components/InvokeTabs'; @@ -121,9 +120,6 @@ const App = ({ config = DEFAULT_CONFIG, children }: Props) => { - - - ); }; diff --git a/invokeai/frontend/web/src/app/socketio/emitters.ts b/invokeai/frontend/web/src/app/socketio/emitters.ts index 5c9057cac3..610f05b826 100644 --- a/invokeai/frontend/web/src/app/socketio/emitters.ts +++ b/invokeai/frontend/web/src/app/socketio/emitters.ts @@ -12,7 +12,6 @@ import { removeImage, } from 'features/gallery/store/gallerySlice'; import { - addLogEntry, generationRequested, modelChangeRequested, modelConvertRequested, diff --git a/invokeai/frontend/web/src/app/socketio/listeners.ts b/invokeai/frontend/web/src/app/socketio/listeners.ts index 39d4b4ec23..de2f86fd4c 100644 --- a/invokeai/frontend/web/src/app/socketio/listeners.ts +++ b/invokeai/frontend/web/src/app/socketio/listeners.ts @@ -6,7 +6,6 @@ import { v4 as uuidv4 } from 'uuid'; import * as InvokeAI from 'app/types/invokeai'; import { - addLogEntry, addToast, errorOccurred, processingCanceled, diff --git a/invokeai/frontend/web/src/features/system/components/Console.tsx b/invokeai/frontend/web/src/features/system/components/Console.tsx deleted file mode 100644 index 4f7946ee78..0000000000 --- a/invokeai/frontend/web/src/features/system/components/Console.tsx +++ /dev/null @@ -1,197 +0,0 @@ -import { Flex, Text, Tooltip } from '@chakra-ui/react'; -import { createSelector } from '@reduxjs/toolkit'; -import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; -import IAIIconButton from 'common/components/IAIIconButton'; -import { - errorSeen, - setShouldShowLogViewer, - SystemState, -} from 'features/system/store/systemSlice'; -import { isEqual } from 'lodash-es'; -import { Resizable } from 're-resizable'; -import { memo, useLayoutEffect, useRef, useState } from 'react'; -import { useHotkeys } from 'react-hotkeys-hook'; -import { useTranslation } from 'react-i18next'; -import { FaAngleDoubleDown, FaCode, FaMinus } from 'react-icons/fa'; -import { systemSelector } from '../store/systemSelectors'; - -const logSelector = createSelector( - systemSelector, - (system: SystemState) => system.log, - { - memoizeOptions: { - // We don't need a deep equality check for this selector. - resultEqualityCheck: (a, b) => a.length === b.length, - }, - } -); - -const consoleSelector = createSelector( - systemSelector, - (system: SystemState) => { - return { - shouldShowLogViewer: system.shouldShowLogViewer, - hasError: system.hasError, - wasErrorSeen: system.wasErrorSeen, - }; - }, - { - memoizeOptions: { - resultEqualityCheck: isEqual, - }, - } -); - -/** - * Basic log viewer, floats on bottom of page. - */ -const Console = () => { - const dispatch = useAppDispatch(); - const { t } = useTranslation(); - const log = useAppSelector(logSelector); - const { shouldShowLogViewer, hasError, wasErrorSeen } = - useAppSelector(consoleSelector); - - // Rudimentary autoscroll - const [shouldAutoscroll, setShouldAutoscroll] = useState(true); - const viewerRef = useRef(null); - - /** - * If autoscroll is on, scroll to the bottom when: - * - log updates - * - viewer is toggled - * - * Also scroll to the bottom whenever autoscroll is turned on. - */ - useLayoutEffect(() => { - if (viewerRef.current !== null && shouldAutoscroll) { - viewerRef.current.scrollTop = viewerRef.current.scrollHeight; - } - }, [shouldAutoscroll, log, shouldShowLogViewer]); - - const handleClickLogViewerToggle = () => { - dispatch(errorSeen()); - dispatch(setShouldShowLogViewer(!shouldShowLogViewer)); - }; - - useHotkeys( - '`', - () => { - dispatch(setShouldShowLogViewer(!shouldShowLogViewer)); - }, - [shouldShowLogViewer] - ); - - useHotkeys('esc', () => { - dispatch(setShouldShowLogViewer(false)); - }); - - const handleOnScroll = () => { - if (!viewerRef.current) return; - if ( - shouldAutoscroll && - viewerRef.current.scrollTop < - viewerRef.current.scrollHeight - viewerRef.current.clientHeight - ) { - setShouldAutoscroll(false); - } - }; - - return ( - <> - {shouldShowLogViewer && ( - - - {log.map((entry, i) => { - const { timestamp, message, level } = entry; - const colorScheme = level === 'info' ? 'base' : level; - return ( - - {timestamp}: - {message} - - ); - })} - - - )} - {shouldShowLogViewer && ( - - } - onClick={() => setShouldAutoscroll(!shouldAutoscroll)} - isChecked={shouldAutoscroll} - sx={{ - position: 'fixed', - insetInlineStart: 2, - bottom: 12, - zIndex: 1, - }} - /> - - )} - - : } - onClick={handleClickLogViewerToggle} - sx={{ - position: 'fixed', - insetInlineStart: 2, - bottom: 2, - zIndex: 1, - }} - colorScheme={hasError || !wasErrorSeen ? 'error' : 'base'} - /> - - - ); -}; - -export default memo(Console); diff --git a/invokeai/frontend/web/src/features/system/store/systemSlice.ts b/invokeai/frontend/web/src/features/system/store/systemSlice.ts index 17a0228ebe..0086389cd3 100644 --- a/invokeai/frontend/web/src/features/system/store/systemSlice.ts +++ b/invokeai/frontend/web/src/features/system/store/systemSlice.ts @@ -14,7 +14,6 @@ import { } from 'services/events/actions'; import i18n from 'i18n'; -import { isImageOutput } from 'services/types/guards'; import { ProgressImage } from 'services/events/types'; import { initialImageSelected } from 'features/parameters/store/generationSlice'; import { makeToast } from '../hooks/useToastWatcher'; @@ -22,7 +21,7 @@ import { sessionCanceled, sessionInvoked } from 'services/thunks/session'; import { receivedModels } from 'services/thunks/model'; import { parsedOpenAPISchema } from 'features/nodes/store/nodesSlice'; import { LogLevelName } from 'roarr'; -import { InvokeLogLevel, VALID_LOG_LEVELS } from 'app/logging/useLogger'; +import { InvokeLogLevel } from 'app/logging/useLogger'; export type LogLevel = 'info' | 'warning' | 'error'; @@ -44,7 +43,6 @@ export interface SystemState extends InvokeAI.SystemStatus, InvokeAI.SystemConfig { shouldDisplayInProgressType: InProgressImageType; - log: Array; shouldShowLogViewer: boolean; isGFPGANAvailable: boolean; isESRGANAvailable: boolean; @@ -108,7 +106,6 @@ export interface SystemState const initialSystemState: SystemState = { isConnected: false, isProcessing: false, - log: [], shouldShowLogViewer: false, shouldDisplayInProgressType: 'latents', shouldDisplayGuides: true, @@ -150,9 +147,6 @@ const initialSystemState: SystemState = { cancelType: 'immediate', isCancelScheduled: false, subscribedNodeIds: [], - // shouldTransformUrls: false, - // disabledTabs: [], - // disabledFeatures: [], wereModelsReceived: false, wasSchemaParsed: false, consoleLogLevel: 'info', @@ -196,25 +190,6 @@ export const systemSlice = createSlice({ ? i18n.t('common.statusConnected') : i18n.t('common.statusDisconnected'); }, - addLogEntry: ( - state, - action: PayloadAction<{ - timestamp: string; - message: string; - level?: LogLevel; - }> - ) => { - const { timestamp, message, level } = action.payload; - const logLevel = level || 'info'; - - const entry: LogEntry = { - timestamp, - message, - level: logLevel, - }; - - state.log.push(entry); - }, setShouldShowLogViewer: (state, action: PayloadAction) => { state.shouldShowLogViewer = action.payload; }, @@ -380,11 +355,6 @@ export const systemSlice = createSlice({ state.isConnected = true; state.currentStatus = i18n.t('common.statusConnected'); - state.log.push({ - timestamp, - message: `Connected to server`, - level: 'error', - }); }); /** @@ -395,11 +365,6 @@ export const systemSlice = createSlice({ state.isConnected = false; state.currentStatus = i18n.t('common.statusDisconnected'); - state.log.push({ - timestamp, - message: `Disconnected from server`, - level: 'error', - }); }); /** @@ -442,15 +407,6 @@ export const systemSlice = createSlice({ state.totalSteps = 0; state.progressImage = null; state.currentStatus = i18n.t('common.statusProcessingComplete'); - - // TODO: handle logging for other invocation types - if (isImageOutput(data.result)) { - state.log.push({ - timestamp, - message: `Generated: ${data.result.image.image_name}`, - level: 'info', - }); - } }); /** @@ -459,12 +415,6 @@ export const systemSlice = createSlice({ builder.addCase(invocationError, (state, action) => { const { data, timestamp } = action.payload; - state.log.push({ - timestamp, - message: `Server error: ${data.error}`, - level: 'error', - }); - state.wasErrorSeen = true; state.progressImage = null; state.isProcessing = false; @@ -472,12 +422,6 @@ export const systemSlice = createSlice({ state.toastQueue.push( makeToast({ title: i18n.t('toast.serverError'), status: 'error' }) ); - - state.log.push({ - timestamp, - message: `Server error: ${data.error}`, - level: 'error', - }); }); /** @@ -504,12 +448,6 @@ export const systemSlice = createSlice({ state.toastQueue.push( makeToast({ title: i18n.t('toast.canceled'), status: 'warning' }) ); - - state.log.push({ - timestamp, - message: `Processing canceled`, - level: 'warning', - }); }); /** @@ -538,7 +476,6 @@ export const systemSlice = createSlice({ export const { setShouldDisplayInProgressType, setIsProcessing, - addLogEntry, setShouldShowLogViewer, setIsConnected, setSocketId, From dc976cd665a20a4ed62eb33b93834a9662f85757 Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Sat, 29 Apr 2023 17:55:39 +1000 Subject: [PATCH 34/68] feat(ui): add switch for logging --- invokeai/frontend/web/public/locales/en.json | 3 ++- .../frontend/web/src/app/logging/useLogger.ts | 17 +++++++++-------- .../components/SettingsModal/SettingsModal.tsx | 18 ++++++++++++++++++ .../src/features/system/store/systemSlice.ts | 8 +++++++- 4 files changed, 36 insertions(+), 10 deletions(-) diff --git a/invokeai/frontend/web/public/locales/en.json b/invokeai/frontend/web/public/locales/en.json index d52f3c38c7..f98d864c55 100644 --- a/invokeai/frontend/web/public/locales/en.json +++ b/invokeai/frontend/web/public/locales/en.json @@ -531,7 +531,8 @@ "resetWebUIDesc1": "Resetting the web UI only resets the browser's local cache of your images and remembered settings. It does not delete any images from disk.", "resetWebUIDesc2": "If images aren't showing up in the gallery or something else isn't working, please try resetting before submitting an issue on GitHub.", "resetComplete": "Web UI has been reset. Refresh the page to reload.", - "consoleLogLevel": "Console Log Level" + "consoleLogLevel": "Log Level", + "shouldLogToConsole": "Console Logging" }, "toast": { "serverError": "Server Error", diff --git a/invokeai/frontend/web/src/app/logging/useLogger.ts b/invokeai/frontend/web/src/app/logging/useLogger.ts index ef1b27ad6b..c69b13dc72 100644 --- a/invokeai/frontend/web/src/app/logging/useLogger.ts +++ b/invokeai/frontend/web/src/app/logging/useLogger.ts @@ -32,7 +32,6 @@ export const VALID_LOG_LEVELS = [ 'warn', 'error', 'fatal', - 'none', ] as const; export type InvokeLogLevel = (typeof VALID_LOG_LEVELS)[number]; @@ -40,11 +39,12 @@ export type InvokeLogLevel = (typeof VALID_LOG_LEVELS)[number]; const selector = createSelector( systemSelector, (system) => { - const { app_version, consoleLogLevel } = system; + const { app_version, consoleLogLevel, shouldLogToConsole } = system; return { version: app_version, consoleLogLevel, + shouldLogToConsole, }; }, { @@ -55,14 +55,12 @@ const selector = createSelector( ); export const useLogger = () => { - const { version, consoleLogLevel } = useAppSelector(selector); + const { version, consoleLogLevel, shouldLogToConsole } = + useAppSelector(selector); // The provided Roarr browser log writer uses localStorage to config logging to console useEffect(() => { - if (consoleLogLevel === 'none') { - // Disable console log output - localStorage.setItem('ROARR_LOG', 'false'); - } else { + if (shouldLogToConsole) { // Enable console log output localStorage.setItem('ROARR_LOG', 'true'); @@ -71,9 +69,12 @@ export const useLogger = () => { 'ROARR_FILTER', `context.logLevel:>=${LOG_LEVEL_MAP[consoleLogLevel]}` ); + } else { + // Disable console log output + localStorage.setItem('ROARR_LOG', 'false'); } ROARR.write = createLogWriter(); - }, [consoleLogLevel]); + }, [consoleLogLevel, shouldLogToConsole]); // Update the module-scoped logger context as needed useEffect(() => { diff --git a/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsModal.tsx b/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsModal.tsx index da4dbe2572..be6e0c27a3 100644 --- a/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsModal.tsx +++ b/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsModal.tsx @@ -30,6 +30,7 @@ import { setShouldConfirmOnDelete, setShouldDisplayGuides, setShouldDisplayInProgressType, + shouldLogToConsoleChanged, SystemState, } from 'features/system/store/systemSlice'; import { uiSelector } from 'features/ui/store/uiSelectors'; @@ -44,6 +45,7 @@ import { ChangeEvent, cloneElement, ReactElement, useCallback } from 'react'; import { useTranslation } from 'react-i18next'; import { InvokeLogLevel, VALID_LOG_LEVELS } from 'app/logging/useLogger'; import { LogLevelName } from 'roarr'; +import { F } from 'ts-toolbelt'; const selector = createSelector( [systemSelector, uiSelector], @@ -56,6 +58,7 @@ const selector = createSelector( saveIntermediatesInterval, enableImageDebugging, consoleLogLevel, + shouldLogToConsole, } = system; const { shouldUseCanvasBetaLayout, shouldUseSliders } = ui; @@ -70,6 +73,7 @@ const selector = createSelector( shouldUseCanvasBetaLayout, shouldUseSliders, consoleLogLevel, + shouldLogToConsole, }; }, { @@ -122,6 +126,7 @@ const SettingsModal = ({ children }: SettingsModalProps) => { shouldUseCanvasBetaLayout, shouldUseSliders, consoleLogLevel, + shouldLogToConsole, } = useAppSelector(selector); /** @@ -148,6 +153,13 @@ const SettingsModal = ({ children }: SettingsModalProps) => { [dispatch] ); + const handleLogToConsoleChanged = useCallback( + (e: ChangeEvent) => { + dispatch(shouldLogToConsoleChanged(e.target.checked)); + }, + [dispatch] + ); + return ( <> {cloneElement(children, { @@ -224,7 +236,13 @@ const SettingsModal = ({ children }: SettingsModalProps) => { Developer + ) => { state.consoleLogLevel = action.payload; }, + shouldLogToConsoleChanged: (state, action: PayloadAction) => { + state.shouldLogToConsole = action.payload; + }, }, extraReducers(builder) { /** @@ -509,6 +514,7 @@ export const { cancelTypeChanged, subscribedNodeIdsSet, consoleLogLevelChanged, + shouldLogToConsoleChanged, } = systemSlice.actions; export default systemSlice.reducer; From d00d29d6b5aa2e42752ec674d9694658814ec116 Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Sat, 29 Apr 2023 18:25:02 +1000 Subject: [PATCH 35/68] feat(ui): update settings modal --- invokeai/frontend/web/public/locales/en.json | 4 ++- .../web/src/common/components/IAISelect.tsx | 36 ++++++++++++++++--- .../SettingsModal/SettingsModal.tsx | 16 ++++++--- 3 files changed, 46 insertions(+), 10 deletions(-) diff --git a/invokeai/frontend/web/public/locales/en.json b/invokeai/frontend/web/public/locales/en.json index f98d864c55..d3ccbcb395 100644 --- a/invokeai/frontend/web/public/locales/en.json +++ b/invokeai/frontend/web/public/locales/en.json @@ -532,7 +532,9 @@ "resetWebUIDesc2": "If images aren't showing up in the gallery or something else isn't working, please try resetting before submitting an issue on GitHub.", "resetComplete": "Web UI has been reset. Refresh the page to reload.", "consoleLogLevel": "Log Level", - "shouldLogToConsole": "Console Logging" + "shouldLogToConsole": "Console Logging", + "developer": "Developer", + "general": "General" }, "toast": { "serverError": "Server Error", diff --git a/invokeai/frontend/web/src/common/components/IAISelect.tsx b/invokeai/frontend/web/src/common/components/IAISelect.tsx index f0998b8937..7bc8952d94 100644 --- a/invokeai/frontend/web/src/common/components/IAISelect.tsx +++ b/invokeai/frontend/web/src/common/components/IAISelect.tsx @@ -16,13 +16,23 @@ type IAISelectProps = SelectProps & { validValues: | Array | Array<{ key: string; value: string | number }>; + horizontal?: boolean; + spaceEvenly?: boolean; }; /** * Customized Chakra FormControl + Select multi-part component. */ const IAISelect = (props: IAISelectProps) => { - const { label, isDisabled, validValues, tooltip, tooltipProps, ...rest } = - props; + const { + label, + isDisabled, + validValues, + tooltip, + tooltipProps, + horizontal, + spaceEvenly, + ...rest + } = props; return ( { e.nativeEvent.stopPropagation(); e.nativeEvent.cancelBubble = true; }} + sx={ + horizontal + ? { + display: 'flex', + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'space-between', + gap: 4, + } + : {} + } > - {label && {label}} + {label && ( + + {label} + + )} - {validValues.map((opt) => { return typeof opt === 'string' || typeof opt === 'number' ? ( diff --git a/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsModal.tsx b/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsModal.tsx index be6e0c27a3..a806ef262b 100644 --- a/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsModal.tsx +++ b/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsModal.tsx @@ -86,6 +86,7 @@ const modalSectionStyles: ChakraProps['sx'] = { gap: 2, p: 4, bg: 'base.900', + borderRadius: 'base', }; type SettingsModalProps = { @@ -170,15 +171,20 @@ const SettingsModal = ({ children }: SettingsModalProps) => { isOpen={isSettingsModalOpen} onClose={onSettingsModalClose} size="xl" + isCentered > {t('common.settingsLabel')} - + + {t('settings.general')} + { - - Developer - + {t('settings.developer')} { {t('settings.resetWebUIDesc1')} {t('settings.resetWebUIDesc2')} - + From 8db20e0d959e1f7aabaa0b737d41eafc471b3d0b Mon Sep 17 00:00:00 2001 From: Lincoln Stein Date: Sat, 29 Apr 2023 09:43:40 -0400 Subject: [PATCH 36/68] rename log to logger throughout --- invokeai/app/api/dependencies.py | 4 +- invokeai/app/api/routers/models.py | 10 +- invokeai/app/cli/commands.py | 4 +- invokeai/app/cli/completer.py | 4 +- invokeai/app/cli_app.py | 8 +- invokeai/app/invocations/util/choose_model.py | 4 +- .../app/services/model_manager_initializer.py | 16 +- invokeai/app/services/restoration_services.py | 20 +-- invokeai/backend/args.py | 14 +- invokeai/backend/generate.py | 78 +++++----- invokeai/backend/generator/base.py | 6 +- invokeai/backend/generator/embiggen.py | 22 +-- invokeai/backend/generator/txt2img2img.py | 4 +- invokeai/backend/image_util/patchmatch.py | 8 +- invokeai/backend/image_util/txt2mask.py | 4 +- .../convert_ckpt_to_diffusers.py | 16 +- .../backend/model_management/model_manager.py | 140 +++++++++--------- invokeai/backend/prompting/conditioning.py | 16 +- invokeai/backend/restoration/base.py | 12 +- invokeai/backend/restoration/codeformer.py | 8 +- invokeai/backend/restoration/gfpgan.py | 12 +- invokeai/backend/restoration/outcrop.py | 4 +- invokeai/backend/restoration/realesrgan.py | 8 +- invokeai/backend/safety_checker.py | 6 +- .../backend/stable_diffusion/concepts_lib.py | 18 +-- .../diffusion/cross_attention_control.py | 4 +- .../diffusion/shared_invokeai_diffusion.py | 12 +- .../image_degradation/utils_image.py | 4 +- .../textual_inversion_manager.py | 44 +++--- invokeai/backend/util/logging.py | 2 +- invokeai/backend/util/util.py | 28 ++-- invokeai/backend/web/invoke_ai_web_server.py | 52 +++---- invokeai/frontend/CLI/CLI.py | 132 ++++++++--------- invokeai/frontend/install/model_install.py | 12 +- invokeai/frontend/merge/merge_diffusers.py | 16 +- .../frontend/training/textual_inversion.py | 22 +-- 36 files changed, 387 insertions(+), 387 deletions(-) diff --git a/invokeai/app/api/dependencies.py b/invokeai/app/api/dependencies.py index 153176cd95..454c2bbbf6 100644 --- a/invokeai/app/api/dependencies.py +++ b/invokeai/app/api/dependencies.py @@ -2,7 +2,7 @@ import os -import invokeai.backend.util.logging as log +import invokeai.backend.util.logging as logger from ..services.default_graphs import create_system_graphs from ..services.latent_storage import DiskLatentsStorage, ForwardCacheLatentsStorage @@ -49,7 +49,7 @@ class ApiDependencies: Globals.disable_xformers = not config.xformers Globals.ckpt_convert = config.ckpt_convert - log.info(f"Internet connectivity is {Globals.internet_available}") + logger.info(f"Internet connectivity is {Globals.internet_available}") events = FastAPIEventService(event_handler_id) diff --git a/invokeai/app/api/routers/models.py b/invokeai/app/api/routers/models.py index 94dca8321e..9e567bab45 100644 --- a/invokeai/app/api/routers/models.py +++ b/invokeai/app/api/routers/models.py @@ -4,7 +4,7 @@ import shutil import asyncio from typing import Annotated, Any, List, Literal, Optional, Union -import invokeai.backend.util.logging as log +import invokeai.backend.util.logging as logger from fastapi.routing import APIRouter, HTTPException from pydantic import BaseModel, Field, parse_obj_as from pathlib import Path @@ -116,16 +116,16 @@ async def delete_model(model_name: str) -> None: model_exists = model_name in model_names # check if model exists - log.info(f"Checking for model {model_name}...") + logger.info(f"Checking for model {model_name}...") if model_exists: - log.info(f"Deleting Model: {model_name}") + logger.info(f"Deleting Model: {model_name}") ApiDependencies.invoker.services.model_manager.del_model(model_name, delete_files=True) - log.info(f"Model Deleted: {model_name}") + logger.info(f"Model Deleted: {model_name}") raise HTTPException(status_code=204, detail=f"Model '{model_name}' deleted successfully") else: - log.error(f"Model not found") + logger.error(f"Model not found") raise HTTPException(status_code=404, detail=f"Model '{model_name}' not found") diff --git a/invokeai/app/cli/commands.py b/invokeai/app/cli/commands.py index 156887da9d..01cd99bc35 100644 --- a/invokeai/app/cli/commands.py +++ b/invokeai/app/cli/commands.py @@ -7,7 +7,7 @@ from pydantic import BaseModel, Field import networkx as nx import matplotlib.pyplot as plt -import invokeai.backend.util.logging as log +import invokeai.backend.util.logging as logger from ..invocations.baseinvocation import BaseInvocation from ..invocations.image import ImageField from ..services.graph import GraphExecutionState, LibraryGraph, Edge @@ -230,7 +230,7 @@ class HistoryCommand(BaseCommand): for i in range(min(self.count, len(history))): entry_id = history[-1 - i] entry = context.get_session().graph.get_node(entry_id) - log.info(f"{entry_id}: {get_invocation_command(entry)}") + logger.info(f"{entry_id}: {get_invocation_command(entry)}") class SetDefaultCommand(BaseCommand): diff --git a/invokeai/app/cli/completer.py b/invokeai/app/cli/completer.py index b3e5b983a2..c84c430bd7 100644 --- a/invokeai/app/cli/completer.py +++ b/invokeai/app/cli/completer.py @@ -10,7 +10,7 @@ import shlex from pathlib import Path from typing import List, Dict, Literal, get_args, get_type_hints, get_origin -import invokeai.backend.util.logging as log +import invokeai.backend.util.logging as logger from ...backend import ModelManager, Globals from ..invocations.baseinvocation import BaseInvocation from .commands import BaseCommand @@ -161,7 +161,7 @@ def set_autocompleter(model_manager: ModelManager) -> Completer: pass except OSError: # file likely corrupted newname = f"{histfile}.old" - log.error( + logger.error( f"Your history file {histfile} couldn't be loaded and may be corrupted. Renaming it to {newname}" ) histfile.replace(Path(newname)) diff --git a/invokeai/app/cli_app.py b/invokeai/app/cli_app.py index 0e75bef67f..0d879e98d7 100644 --- a/invokeai/app/cli_app.py +++ b/invokeai/app/cli_app.py @@ -14,7 +14,7 @@ from pydantic import BaseModel from pydantic.fields import Field -import invokeai.backend.util.logging as log +import invokeai.backend.util.logging as logger from invokeai.app.services.metadata import PngMetadataService from .services.default_graphs import create_system_graphs from .services.latent_storage import DiskLatentsStorage, ForwardCacheLatentsStorage @@ -181,7 +181,7 @@ def invoke_all(context: CliContext): # Print any errors if context.session.has_error(): for n in context.session.errors: - log.error( + logger.error( f"Error in node {n} (source node {context.session.prepared_source_mapping[n]}): {context.session.errors[n]}" ) @@ -364,12 +364,12 @@ def invoke_cli(): invoke_all(context) except InvalidArgs: - log.warning('Invalid command, use "help" to list commands') + logger.warning('Invalid command, use "help" to list commands') continue except SessionError: # Start a new session - log.warning("Session error: creating a new session") + logger.warning("Session error: creating a new session") context.reset() except ExitCli: diff --git a/invokeai/app/invocations/util/choose_model.py b/invokeai/app/invocations/util/choose_model.py index b6fc31644e..99a4d14835 100644 --- a/invokeai/app/invocations/util/choose_model.py +++ b/invokeai/app/invocations/util/choose_model.py @@ -1,4 +1,4 @@ -import invokeai.backend.util.logging as log +import invokeai.backend.util.logging as logger from invokeai.backend.model_management.model_manager import ModelManager @@ -8,6 +8,6 @@ def choose_model(model_manager: ModelManager, model_name: str): model = model_manager.get_model(model_name) else: model = model_manager.get_model() - log.warning(f"{model_name}' is not a valid model name. Using default model \'{model['model_name']}\' instead.") + logger.warning(f"{model_name}' is not a valid model name. Using default model \'{model['model_name']}\' instead.") return model diff --git a/invokeai/app/services/model_manager_initializer.py b/invokeai/app/services/model_manager_initializer.py index 7f1ed28e49..7f78f303f2 100644 --- a/invokeai/app/services/model_manager_initializer.py +++ b/invokeai/app/services/model_manager_initializer.py @@ -7,7 +7,7 @@ from omegaconf import OmegaConf from pathlib import Path import invokeai.version -import invokeai.backend.util.logging as log +import invokeai.backend.util.logging as logger from ...backend import ModelManager from ...backend.util import choose_precision, choose_torch_device from ...backend import Globals @@ -21,8 +21,8 @@ def get_model_manager(config: Args) -> ModelManager: config, FileNotFoundError(f"The file {config_file} could not be found.") ) - log.info(f"{invokeai.version.__app_name__}, version {invokeai.version.__version__}") - log.info(f'InvokeAI runtime directory is "{Globals.root}"') + logger.info(f"{invokeai.version.__app_name__}, version {invokeai.version.__version__}") + logger.info(f'InvokeAI runtime directory is "{Globals.root}"') # these two lines prevent a horrible warning message from appearing # when the frozen CLIP tokenizer is imported @@ -67,7 +67,7 @@ def get_model_manager(config: Args) -> ModelManager: except (FileNotFoundError, TypeError, AssertionError) as e: report_model_error(config, e) except (IOError, KeyError) as e: - log.error(f"{e}. Aborting.") + logger.error(f"{e}. Aborting.") sys.exit(-1) # try to autoconvert new models @@ -81,13 +81,13 @@ def get_model_manager(config: Args) -> ModelManager: return model_manager def report_model_error(opt: Namespace, e: Exception): - log.error(f'An error occurred while attempting to initialize the model: "{str(e)}"') - log.error( + logger.error(f'An error occurred while attempting to initialize the model: "{str(e)}"') + logger.error( "This can be caused by a missing or corrupted models file, and can sometimes be fixed by (re)installing the models." ) yes_to_all = os.environ.get("INVOKE_MODEL_RECONFIGURE") if yes_to_all: - log.warning + logger.warning "Reconfiguration is being forced by environment variable INVOKE_MODEL_RECONFIGURE" ) else: @@ -97,7 +97,7 @@ def report_model_error(opt: Namespace, e: Exception): if response.startswith(("n", "N")): return - log.info("invokeai-configure is launching....\n") + logger.info("invokeai-configure is launching....\n") # Match arguments that were set on the CLI # only the arguments accepted by the configuration script are parsed diff --git a/invokeai/app/services/restoration_services.py b/invokeai/app/services/restoration_services.py index 5e908c0abe..7501b11e6b 100644 --- a/invokeai/app/services/restoration_services.py +++ b/invokeai/app/services/restoration_services.py @@ -1,7 +1,7 @@ import sys import traceback import torch -import invokeai.backend.util.logging as log +import invokeai.backend.util.logging as logger from ...backend.restoration import Restoration from ...backend.util import choose_torch_device, CPU_DEVICE, MPS_DEVICE @@ -21,16 +21,16 @@ class RestorationServices: args.gfpgan_model_path ) else: - log.info("Face restoration disabled") + logger.info("Face restoration disabled") if args.esrgan: esrgan = restoration.load_esrgan(args.esrgan_bg_tile) else: - log.info("Upscaling disabled") + logger.info("Upscaling disabled") else: - log.info("Face restoration and upscaling disabled") + logger.info("Face restoration and upscaling disabled") except (ModuleNotFoundError, ImportError): print(traceback.format_exc(), file=sys.stderr) - log.info("You may need to install the ESRGAN and/or GFPGAN modules") + logger.info("You may need to install the ESRGAN and/or GFPGAN modules") self.device = torch.device(choose_torch_device()) self.gfpgan = gfpgan self.codeformer = codeformer @@ -59,14 +59,14 @@ class RestorationServices: if self.gfpgan is not None or self.codeformer is not None: if facetool == "gfpgan": if self.gfpgan is None: - log.info( + logger.info( "GFPGAN not found. Face restoration is disabled." ) else: image = self.gfpgan.process(image, strength, seed) if facetool == "codeformer": if self.codeformer is None: - log.info( + logger.info( "CodeFormer not found. Face restoration is disabled." ) else: @@ -81,7 +81,7 @@ class RestorationServices: fidelity=codeformer_fidelity, ) else: - log.info("Face Restoration is disabled.") + logger.info("Face Restoration is disabled.") if upscale is not None: if self.esrgan is not None: if len(upscale) < 2: @@ -94,9 +94,9 @@ class RestorationServices: denoise_str=upscale_denoise_str, ) else: - log.info("ESRGAN is disabled. Image not upscaled.") + logger.info("ESRGAN is disabled. Image not upscaled.") except Exception as e: - log.info( + logger.info( f"Error running RealESRGAN or GFPGAN. Your image was not upscaled.\n{e}" ) diff --git a/invokeai/backend/args.py b/invokeai/backend/args.py index 4a1aea094c..eb8b396ee0 100644 --- a/invokeai/backend/args.py +++ b/invokeai/backend/args.py @@ -96,7 +96,7 @@ from pathlib import Path from typing import List import invokeai.version -import invokeai.backend.util.logging as log +import invokeai.backend.util.logging as logger from invokeai.backend.image_util import retrieve_metadata from .globals import Globals @@ -190,7 +190,7 @@ class Args(object): print(f"{APP_NAME} {APP_VERSION}") sys.exit(0) - log.info("Initializing, be patient...") + logger.info("Initializing, be patient...") Globals.root = Path(os.path.abspath(switches.root_dir or Globals.root)) Globals.try_patchmatch = switches.patchmatch @@ -198,12 +198,12 @@ class Args(object): initfile = os.path.expanduser(os.path.join(Globals.root, Globals.initfile)) legacyinit = os.path.expanduser("~/.invokeai") if os.path.exists(initfile): - log.info( + logger.info( f"Initialization file {initfile} found. Loading...", ) sysargs.insert(0, f"@{initfile}") elif os.path.exists(legacyinit): - log.warning( + logger.warning( f"Old initialization file found at {legacyinit}. This location is deprecated. Please move it to {Globals.root}/invokeai.init." ) sysargs.insert(0, f"@{legacyinit}") @@ -214,7 +214,7 @@ class Args(object): self._arg_switches = self._arg_parser.parse_args(sysargs) return self._arg_switches except Exception as e: - log.error(f"An exception has occurred: {e}") + logger.error(f"An exception has occurred: {e}") return None def parse_cmd(self, cmd_string): @@ -1154,7 +1154,7 @@ class Args(object): def format_metadata(**kwargs): - log.warning("format_metadata() is deprecated. Please use metadata_dumps()") + logger.warning("format_metadata() is deprecated. Please use metadata_dumps()") return metadata_dumps(kwargs) @@ -1326,7 +1326,7 @@ def metadata_loads(metadata) -> list: import sys import traceback - log.error("Could not read metadata") + logger.error("Could not read metadata") print(traceback.format_exc(), file=sys.stderr) return results diff --git a/invokeai/backend/generate.py b/invokeai/backend/generate.py index dfec9df59f..4f3df60f1c 100644 --- a/invokeai/backend/generate.py +++ b/invokeai/backend/generate.py @@ -27,7 +27,7 @@ from diffusers.utils.import_utils import is_xformers_available from omegaconf import OmegaConf from pathlib import Path -import invokeai.backend.util.logging as log +import invokeai.backend.util.logging as logger from .args import metadata_from_png from .generator import infill_methods from .globals import Globals, global_cache_dir @@ -196,12 +196,12 @@ class Generate: # device to Generate(). However the device was then ignored, so # it wasn't actually doing anything. This logic could be reinstated. self.device = torch.device(choose_torch_device()) - log.info(f"Using device_type {self.device.type}") + logger.info(f"Using device_type {self.device.type}") if full_precision: if self.precision != "auto": raise ValueError("Remove --full_precision / -F if using --precision") - log.warning("Please remove deprecated --full_precision / -F") - log.warning("If auto config does not work you can use --precision=float32") + logger.warning("Please remove deprecated --full_precision / -F") + logger.warning("If auto config does not work you can use --precision=float32") self.precision = "float32" if self.precision == "auto": self.precision = choose_precision(self.device) @@ -209,13 +209,13 @@ class Generate: if is_xformers_available(): if torch.cuda.is_available() and not Globals.disable_xformers: - log.info("xformers memory-efficient attention is available and enabled") + logger.info("xformers memory-efficient attention is available and enabled") else: - log.info( + logger.info( "xformers memory-efficient attention is available but disabled" ) else: - log.info("xformers not installed") + logger.info("xformers not installed") # model caching system for fast switching self.model_manager = ModelManager( @@ -230,7 +230,7 @@ class Generate: fallback = self.model_manager.default_model() or FALLBACK_MODEL_NAME model = model or fallback if not self.model_manager.valid_model(model): - log.warning( + logger.warning( f'"{model}" is not a known model name; falling back to {fallback}.' ) model = None @@ -247,10 +247,10 @@ class Generate: # load safety checker if requested if safety_checker: - log.info("Initializing NSFW checker") + logger.info("Initializing NSFW checker") self.safety_checker = SafetyChecker(self.device) else: - log.info("NSFW checker is disabled") + logger.info("NSFW checker is disabled") def prompt2png(self, prompt, outdir, **kwargs): """ @@ -568,7 +568,7 @@ class Generate: self.clear_cuda_cache() if catch_interrupts: - log.warning("Interrupted** Partial results will be returned.") + logger.warning("Interrupted** Partial results will be returned.") else: raise KeyboardInterrupt except RuntimeError: @@ -576,11 +576,11 @@ class Generate: self.clear_cuda_cache() print(traceback.format_exc(), file=sys.stderr) - log.info("Could not generate image.") + logger.info("Could not generate image.") toc = time.time() - log.info("Usage stats:") - log.info(f"{len(results)} image(s) generated in "+"%4.2fs" % (toc - tic)) + logger.info("Usage stats:") + logger.info(f"{len(results)} image(s) generated in "+"%4.2fs" % (toc - tic)) self.print_cuda_stats() return results @@ -610,14 +610,14 @@ class Generate: def print_cuda_stats(self): if self._has_cuda(): self.gather_cuda_stats() - log.info( + logger.info( "Max VRAM used for this generation: "+ "%4.2fG. " % (self.max_memory_allocated / 1e9)+ "Current VRAM utilization: "+ "%4.2fG" % (self.memory_allocated / 1e9) ) - log.info( + logger.info( "Max VRAM used since script start: " + "%4.2fG" % (self.session_peakmem / 1e9) ) @@ -648,7 +648,7 @@ class Generate: seed = random.randrange(0, np.iinfo(np.uint32).max) prompt = opt.prompt or args.prompt or "" - log.info(f'using seed {seed} and prompt "{prompt}" for {image_path}') + logger.info(f'using seed {seed} and prompt "{prompt}" for {image_path}') # try to reuse the same filename prefix as the original file. # we take everything up to the first period @@ -697,7 +697,7 @@ class Generate: try: extend_instructions[direction] = int(pixels) except ValueError: - log.warning( + logger.warning( 'invalid extension instruction. Use ..., as in "top 64 left 128 right 64 bottom 64"' ) @@ -721,7 +721,7 @@ class Generate: # fetch the metadata from the image generator = self.select_generator(embiggen=True) opt.strength = opt.embiggen_strength or 0.40 - log.info( + logger.info( f"Setting img2img strength to {opt.strength} for happy embiggening" ) generator.generate( @@ -749,12 +749,12 @@ class Generate: return restorer.process(opt, args, image_callback=callback, prefix=prefix) elif tool is None: - log.warning( + logger.warning( "please provide at least one postprocessing option, such as -G or -U" ) return None else: - log.warning(f"postprocessing tool {tool} is not yet supported") + logger.warning(f"postprocessing tool {tool} is not yet supported") return None def select_generator( @@ -798,7 +798,7 @@ class Generate: image = self._load_img(img) if image.width < self.width and image.height < self.height: - log.warning( + logger.warning( f"img2img and inpainting may produce unexpected results with initial images smaller than {self.width}x{self.height} in both dimensions" ) @@ -810,7 +810,7 @@ class Generate: if (image.width * image.height) > ( self.width * self.height ) and self.size_matters: - log.info( + logger.info( "This input is larger than your defaults. If you run out of memory, please use a smaller image." ) self.size_matters = False @@ -892,11 +892,11 @@ class Generate: try: model_data = cache.get_model(model_name) except Exception as e: - log.warning(f"model {model_name} could not be loaded: {str(e)}") + logger.warning(f"model {model_name} could not be loaded: {str(e)}") print(traceback.format_exc(), file=sys.stderr) if previous_model_name is None: raise e - log.warning("trying to reload previous model") + logger.warning("trying to reload previous model") model_data = cache.get_model(previous_model_name) # load previous if model_data is None: raise e @@ -963,14 +963,14 @@ class Generate: if self.gfpgan is not None or self.codeformer is not None: if facetool == "gfpgan": if self.gfpgan is None: - log.info( + logger.info( "GFPGAN not found. Face restoration is disabled." ) else: image = self.gfpgan.process(image, strength, seed) if facetool == "codeformer": if self.codeformer is None: - log.info( + logger.info( "CodeFormer not found. Face restoration is disabled." ) else: @@ -985,7 +985,7 @@ class Generate: fidelity=codeformer_fidelity, ) else: - log.info("Face Restoration is disabled.") + logger.info("Face Restoration is disabled.") if upscale is not None: if self.esrgan is not None: if len(upscale) < 2: @@ -998,9 +998,9 @@ class Generate: denoise_str=upscale_denoise_str, ) else: - log.info("ESRGAN is disabled. Image not upscaled.") + logger.info("ESRGAN is disabled. Image not upscaled.") except Exception as e: - log.info( + logger.info( f"Error running RealESRGAN or GFPGAN. Your image was not upscaled.\n{e}" ) @@ -1077,7 +1077,7 @@ class Generate: ) self.sampler = default - log.info(msg) + logger.info(msg) if not hasattr(self.sampler, "uses_inpainting_model"): # FIXME: terrible kludge! @@ -1086,17 +1086,17 @@ class Generate: def _load_img(self, img) -> Image: if isinstance(img, Image.Image): image = img - log.info(f"using provided input image of size {image.width}x{image.height}") + logger.info(f"using provided input image of size {image.width}x{image.height}") elif isinstance(img, str): assert os.path.exists(img), f"{img}: File not found" image = Image.open(img) - log.info( + logger.info( f"loaded input image of size {image.width}x{image.height} from {img}" ) else: image = Image.open(img) - log.info(f"loaded input image of size {image.width}x{image.height}") + logger.info(f"loaded input image of size {image.width}x{image.height}") image = ImageOps.exif_transpose(image) return image @@ -1184,11 +1184,11 @@ class Generate: def _transparency_check_and_warning(self, image, mask, force_outpaint=False): if not mask: - log.info( + logger.info( "Initial image has transparent areas. Will inpaint in these regions." ) if (not force_outpaint) and self._check_for_erasure(image): - log.info( + logger.info( "Colors underneath the transparent region seem to have been erased.\n" + "Inpainting will be suboptimal. Please preserve the colors when making\n" + "a transparency mask, or provide mask explicitly using --init_mask (-M)." @@ -1202,10 +1202,10 @@ class Generate: def _fit_image(self, image, max_dimensions): w, h = max_dimensions - log.info(f"image will be resized to fit inside a box {w}x{h} in size.") + logger.info(f"image will be resized to fit inside a box {w}x{h} in size.") # note that InitImageResizer does the multiple of 64 truncation internally image = InitImageResizer(image).resize(width=w, height=h) - log.info( + logger.info( f"after adjusting image dimensions to be multiples of 64, init image is {image.width}x{image.height}" ) return image @@ -1217,7 +1217,7 @@ class Generate: ) # resize to integer multiple of 64 if h != height or w != width: if log: - log.info( + logger.info( f"Provided width and height must be multiples of 64. Auto-resizing to {w}x{h}" ) height = h diff --git a/invokeai/backend/generator/base.py b/invokeai/backend/generator/base.py index 00ee61af2d..8ad9dec026 100644 --- a/invokeai/backend/generator/base.py +++ b/invokeai/backend/generator/base.py @@ -25,7 +25,7 @@ from typing import Callable, List, Iterator, Optional, Type from dataclasses import dataclass, field from diffusers.schedulers import SchedulerMixin as Scheduler -import invokeai.backend.util.logging as log +import invokeai.backend.util.logging as logger from ..image_util import configure_model_padding from ..util.util import rand_perlin_2d from ..safety_checker import SafetyChecker @@ -373,7 +373,7 @@ class Generator: try: x_T = self.get_noise(width, height) except: - log.error("An error occurred while getting initial noise") + logger.error("An error occurred while getting initial noise") print(traceback.format_exc()) # Pass on the seed in case a layer beneath us needs to generate noise on its own. @@ -608,7 +608,7 @@ class Generator: image = self.sample_to_image(sample) dirname = os.path.dirname(filepath) or "." if not os.path.exists(dirname): - log.info(f"creating directory {dirname}") + logger.info(f"creating directory {dirname}") os.makedirs(dirname, exist_ok=True) image.save(filepath, "PNG") diff --git a/invokeai/backend/generator/embiggen.py b/invokeai/backend/generator/embiggen.py index 4ac72016b9..6eae5732b0 100644 --- a/invokeai/backend/generator/embiggen.py +++ b/invokeai/backend/generator/embiggen.py @@ -8,7 +8,7 @@ import torch from PIL import Image from tqdm import trange -import invokeai.backend.util.logging as log +import invokeai.backend.util.logging as logger from .base import Generator from .img2img import Img2Img @@ -73,21 +73,21 @@ class Embiggen(Generator): embiggen = [1.0] # If not specified, assume no scaling elif embiggen[0] < 0: embiggen[0] = 1.0 - log.warning( + logger.warning( "Embiggen scaling factor cannot be negative, fell back to the default of 1.0 !" ) if len(embiggen) < 2: embiggen.append(0.75) elif embiggen[1] > 1.0 or embiggen[1] < 0: embiggen[1] = 0.75 - log.warning( + logger.warning( "Embiggen upscaling strength for ESRGAN must be between 0 and 1, fell back to the default of 0.75 !" ) if len(embiggen) < 3: embiggen.append(0.25) elif embiggen[2] < 0: embiggen[2] = 0.25 - log.warning( + logger.warning( "Overlap size for Embiggen must be a positive ratio between 0 and 1 OR a number of pixels, fell back to the default of 0.25 !" ) @@ -98,7 +98,7 @@ class Embiggen(Generator): embiggen_tiles.sort() if strength >= 0.5: - log.warning( + logger.warning( f"Embiggen may produce mirror motifs if the strength (-f) is too high (currently {strength}). Try values between 0.35-0.45." ) @@ -122,7 +122,7 @@ class Embiggen(Generator): from ..restoration.realesrgan import ESRGAN esrgan = ESRGAN() - log.info( + logger.info( f"ESRGAN upscaling init image prior to cutting with Embiggen with strength {embiggen[1]}" ) if embiggen[0] > 2: @@ -313,9 +313,9 @@ class Embiggen(Generator): def make_image(): # Make main tiles ------------------------------------------------- if embiggen_tiles: - log.info(f"Making {len(embiggen_tiles)} Embiggen tiles...") + logger.info(f"Making {len(embiggen_tiles)} Embiggen tiles...") else: - log.info( + logger.info( f"Making {(emb_tiles_x * emb_tiles_y)} Embiggen tiles ({emb_tiles_x}x{emb_tiles_y})..." ) @@ -362,11 +362,11 @@ class Embiggen(Generator): # newinitimage.save(newinitimagepath) if embiggen_tiles: - log.debug( + logger.debug( f"Making tile #{tile + 1} ({embiggen_tiles.index(tile) + 1} of {len(embiggen_tiles)} requested)" ) else: - log.debug(f"Starting {tile + 1} of {(emb_tiles_x * emb_tiles_y)} tiles") + logger.debug(f"Starting {tile + 1} of {(emb_tiles_x * emb_tiles_y)} tiles") # create a torch tensor from an Image newinitimage = np.array(newinitimage).astype(np.float32) / 255.0 @@ -548,7 +548,7 @@ class Embiggen(Generator): # Layer tile onto final image outputsuperimage.alpha_composite(intileimage, (left, top)) else: - log.error( + logger.error( "Could not find all Embiggen output tiles in memory? Something must have gone wrong with img2img generation." ) diff --git a/invokeai/backend/generator/txt2img2img.py b/invokeai/backend/generator/txt2img2img.py index 2dfd2c79e9..1257a44fb1 100644 --- a/invokeai/backend/generator/txt2img2img.py +++ b/invokeai/backend/generator/txt2img2img.py @@ -14,7 +14,7 @@ from ..stable_diffusion.diffusers_pipeline import StableDiffusionGeneratorPipeli from ..stable_diffusion.diffusers_pipeline import ConditioningData from ..stable_diffusion.diffusers_pipeline import trim_to_multiple_of -import invokeai.backend.util.logging as log +import invokeai.backend.util.logging as logger class Txt2Img2Img(Generator): def __init__(self, model, precision): @@ -79,7 +79,7 @@ class Txt2Img2Img(Generator): # the message below is accurate. init_width = first_pass_latent_output.size()[3] * self.downsampling_factor init_height = first_pass_latent_output.size()[2] * self.downsampling_factor - log.info( + logger.info( f"Interpolating from {init_width}x{init_height} to {width}x{height} using DDIM sampling" ) diff --git a/invokeai/backend/image_util/patchmatch.py b/invokeai/backend/image_util/patchmatch.py index 3989786c58..5b5dd75f68 100644 --- a/invokeai/backend/image_util/patchmatch.py +++ b/invokeai/backend/image_util/patchmatch.py @@ -5,7 +5,7 @@ wraps the actual patchmatch object. It respects the global be suppressed or deferred """ import numpy as np -import invokeai.backend.util.logging as log +import invokeai.backend.util.logging as logger from invokeai.backend.globals import Globals class PatchMatch: @@ -27,12 +27,12 @@ class PatchMatch: from patchmatch import patch_match as pm if pm.patchmatch_available: - log.info("Patchmatch initialized") + logger.info("Patchmatch initialized") else: - log.info("Patchmatch not loaded (nonfatal)") + logger.info("Patchmatch not loaded (nonfatal)") self.patch_match = pm else: - log.info("Patchmatch loading disabled") + logger.info("Patchmatch loading disabled") self.tried_load = True @classmethod diff --git a/invokeai/backend/image_util/txt2mask.py b/invokeai/backend/image_util/txt2mask.py index a82e56ffd7..248f19d81d 100644 --- a/invokeai/backend/image_util/txt2mask.py +++ b/invokeai/backend/image_util/txt2mask.py @@ -32,7 +32,7 @@ import torch from PIL import Image, ImageOps from transformers import AutoProcessor, CLIPSegForImageSegmentation -import invokeai.backend.util.logging as log +import invokeai.backend.util.logging as logger from invokeai.backend.globals import global_cache_dir CLIPSEG_MODEL = "CIDAS/clipseg-rd64-refined" @@ -83,7 +83,7 @@ class Txt2Mask(object): """ def __init__(self, device="cpu", refined=False): - log.info("Initializing clipseg model for text to mask inference") + logger.info("Initializing clipseg model for text to mask inference") # BUG: we are not doing anything with the device option at this time self.device = device diff --git a/invokeai/backend/model_management/convert_ckpt_to_diffusers.py b/invokeai/backend/model_management/convert_ckpt_to_diffusers.py index d08f146d8e..8aec5a01d9 100644 --- a/invokeai/backend/model_management/convert_ckpt_to_diffusers.py +++ b/invokeai/backend/model_management/convert_ckpt_to_diffusers.py @@ -25,7 +25,7 @@ from typing import Union import torch from safetensors.torch import load_file -import invokeai.backend.util.logging as log +import invokeai.backend.util.logging as logger from invokeai.backend.globals import global_cache_dir, global_config_dir from .model_manager import ModelManager, SDLegacyType @@ -373,9 +373,9 @@ def convert_ldm_unet_checkpoint(checkpoint, config, path=None, extract_ema=False unet_key = "model.diffusion_model." # at least a 100 parameters have to start with `model_ema` in order for the checkpoint to be EMA if sum(k.startswith("model_ema") for k in keys) > 100: - log.debug(f"Checkpoint {path} has both EMA and non-EMA weights.") + logger.debug(f"Checkpoint {path} has both EMA and non-EMA weights.") if extract_ema: - log.debug("Extracting EMA weights (usually better for inference)") + logger.debug("Extracting EMA weights (usually better for inference)") for key in keys: if key.startswith("model.diffusion_model"): flat_ema_key = "model_ema." + "".join(key.split(".")[1:]) @@ -393,7 +393,7 @@ def convert_ldm_unet_checkpoint(checkpoint, config, path=None, extract_ema=False key ) else: - log.debug( + logger.debug( "Extracting only the non-EMA weights (usually better for fine-tuning)" ) @@ -1116,7 +1116,7 @@ def load_pipeline_from_original_stable_diffusion_ckpt( if "global_step" in checkpoint: global_step = checkpoint["global_step"] else: - log.debug("global_step key not found in model") + logger.debug("global_step key not found in model") global_step = None # sometimes there is a state_dict key and sometimes not @@ -1230,15 +1230,15 @@ def load_pipeline_from_original_stable_diffusion_ckpt( # If a replacement VAE path was specified, we'll incorporate that into # the checkpoint model and then convert it if vae_path: - log.debug(f"Converting VAE {vae_path}") + logger.debug(f"Converting VAE {vae_path}") replace_checkpoint_vae(checkpoint,vae_path) # otherwise we use the original VAE, provided that # an externally loaded diffusers VAE was not passed elif not vae: - log.debug("Using checkpoint model's original VAE") + logger.debug("Using checkpoint model's original VAE") if vae: - log.debug("Using replacement diffusers VAE") + logger.debug("Using replacement diffusers VAE") else: # convert the original or replacement VAE vae_config = create_vae_diffusers_config( original_config, image_size=image_size diff --git a/invokeai/backend/model_management/model_manager.py b/invokeai/backend/model_management/model_manager.py index f10cd8c4f5..3f921828d5 100644 --- a/invokeai/backend/model_management/model_manager.py +++ b/invokeai/backend/model_management/model_manager.py @@ -24,7 +24,7 @@ import safetensors import safetensors.torch import torch import transformers -import invokeai.backend.util.logging as log +import invokeai.backend.util.logging as logger from diffusers import ( AutoencoderKL, UNet2DConditionModel, @@ -133,7 +133,7 @@ class ModelManager(object): ) if not self.valid_model(model_name): - log.error( + logger.error( f'"{model_name}" is not a known model name. Please check your models.yaml file' ) return self.current_model @@ -145,7 +145,7 @@ class ModelManager(object): if model_name in self.models: requested_model = self.models[model_name]["model"] - log.info(f"Retrieving model {model_name} from system RAM cache") + logger.info(f"Retrieving model {model_name} from system RAM cache") requested_model.ready() width = self.models[model_name]["width"] height = self.models[model_name]["height"] @@ -380,7 +380,7 @@ class ModelManager(object): """ omega = self.config if model_name not in omega: - log.error(f"Unknown model {model_name}") + logger.error(f"Unknown model {model_name}") return # save these for use in deletion later conf = omega[model_name] @@ -393,13 +393,13 @@ class ModelManager(object): self.stack.remove(model_name) if delete_files: if weights: - log.info(f"Deleting file {weights}") + logger.info(f"Deleting file {weights}") Path(weights).unlink(missing_ok=True) elif path: - log.info(f"Deleting directory {path}") + logger.info(f"Deleting directory {path}") rmtree(path, ignore_errors=True) elif repo_id: - log.info(f"Deleting the cached model directory for {repo_id}") + logger.info(f"Deleting the cached model directory for {repo_id}") self._delete_model_from_cache(repo_id) def add_model( @@ -440,7 +440,7 @@ class ModelManager(object): def _load_model(self, model_name: str): """Load and initialize the model from configuration variables passed at object creation time""" if model_name not in self.config: - log.error( + logger.error( f'"{model_name}" is not a known model name. Please check your models.yaml file' ) return @@ -458,7 +458,7 @@ class ModelManager(object): model_format = mconfig.get("format", "ckpt") if model_format == "ckpt": weights = mconfig.weights - log.info(f"Loading {model_name} from {weights}") + logger.info(f"Loading {model_name} from {weights}") model, width, height, model_hash = self._load_ckpt_model( model_name, mconfig ) @@ -474,13 +474,13 @@ class ModelManager(object): # usage statistics toc = time.time() - log.info("Model loaded in " + "%4.2fs" % (toc - tic)) + logger.info("Model loaded in " + "%4.2fs" % (toc - tic)) if self._has_cuda(): - log.info( + logger.info( "Max VRAM used to load the model: "+ "%4.2fG" % (torch.cuda.max_memory_allocated() / 1e9) ) - log.info( + logger.info( "Current VRAM usage: "+ "%4.2fG" % (torch.cuda.memory_allocated() / 1e9) ) @@ -490,11 +490,11 @@ class ModelManager(object): name_or_path = self.model_name_or_path(mconfig) using_fp16 = self.precision == "float16" - log.info(f"Loading diffusers model from {name_or_path}") + logger.info(f"Loading diffusers model from {name_or_path}") if using_fp16: - log.debug("Using faster float16 precision") + logger.debug("Using faster float16 precision") else: - log.debug("Using more accurate float32 precision") + logger.debug("Using more accurate float32 precision") # TODO: scan weights maybe? pipeline_args: dict[str, Any] = dict( @@ -526,7 +526,7 @@ class ModelManager(object): if str(e).startswith("fp16 is not a valid"): pass else: - log.error( + logger.error( f"An unexpected error occurred while downloading the model: {e})" ) if pipeline: @@ -545,7 +545,7 @@ class ModelManager(object): # square images??? width = pipeline.unet.config.sample_size * pipeline.vae_scale_factor height = width - log.debug(f"Default image dimensions = {width} x {height}") + logger.debug(f"Default image dimensions = {width} x {height}") return pipeline, width, height, model_hash @@ -562,7 +562,7 @@ class ModelManager(object): weights = os.path.normpath(os.path.join(Globals.root, weights)) # Convert to diffusers and return a diffusers pipeline - log.info(f"Converting legacy checkpoint {model_name} into a diffusers model...") + logger.info(f"Converting legacy checkpoint {model_name} into a diffusers model...") from . import load_pipeline_from_original_stable_diffusion_ckpt @@ -627,7 +627,7 @@ class ModelManager(object): if model_name not in self.models: return - log.info(f"Offloading {model_name} to CPU") + logger.info(f"Offloading {model_name} to CPU") model = self.models[model_name]["model"] model.offload_all() self.current_model = None @@ -643,26 +643,26 @@ class ModelManager(object): and option to exit if an infected file is identified. """ # scan model - log.debug(f"Scanning Model: {model_name}") + logger.debug(f"Scanning Model: {model_name}") scan_result = scan_file_path(checkpoint) if scan_result.infected_files != 0: if scan_result.infected_files == 1: - log.critical(f"Issues Found In Model: {scan_result.issues_count}") - log.critical("The model you are trying to load seems to be infected.") - log.critical("For your safety, InvokeAI will not load this model.") - log.critical("Please use checkpoints from trusted sources.") - log.critical("Exiting InvokeAI") + logger.critical(f"Issues Found In Model: {scan_result.issues_count}") + logger.critical("The model you are trying to load seems to be infected.") + logger.critical("For your safety, InvokeAI will not load this model.") + logger.critical("Please use checkpoints from trusted sources.") + logger.critical("Exiting InvokeAI") sys.exit() else: - log.warning("InvokeAI was unable to scan the model you are using.") + logger.warning("InvokeAI was unable to scan the model you are using.") model_safe_check_fail = ask_user( "Do you want to to continue loading the model?", ["y", "n"] ) if model_safe_check_fail.lower() != "y": - log.critical("Exiting InvokeAI") + logger.critical("Exiting InvokeAI") sys.exit() else: - log.debug("Model scanned ok") + logger.debug("Model scanned ok") def import_diffuser_model( self, @@ -779,24 +779,24 @@ class ModelManager(object): model_path: Path = None thing = path_url_or_repo # to save typing - log.info(f"Probing {thing} for import") + logger.info(f"Probing {thing} for import") if thing.startswith(("http:", "https:", "ftp:")): - log.info(f"{thing} appears to be a URL") + logger.info(f"{thing} appears to be a URL") model_path = self._resolve_path( thing, "models/ldm/stable-diffusion-v1" ) # _resolve_path does a download if needed elif Path(thing).is_file() and thing.endswith((".ckpt", ".safetensors")): if Path(thing).stem in ["model", "diffusion_pytorch_model"]: - log.debug(f"{Path(thing).name} appears to be part of a diffusers model. Skipping import") + logger.debug(f"{Path(thing).name} appears to be part of a diffusers model. Skipping import") return else: - log.debug(f"{thing} appears to be a checkpoint file on disk") + logger.debug(f"{thing} appears to be a checkpoint file on disk") model_path = self._resolve_path(thing, "models/ldm/stable-diffusion-v1") elif Path(thing).is_dir() and Path(thing, "model_index.json").exists(): - log.debug(f"{thing} appears to be a diffusers file on disk") + logger.debug(f"{thing} appears to be a diffusers file on disk") model_name = self.import_diffuser_model( thing, vae=dict(repo_id="stabilityai/sd-vae-ft-mse"), @@ -807,30 +807,30 @@ class ModelManager(object): elif Path(thing).is_dir(): if (Path(thing) / "model_index.json").exists(): - log.debug(f"{thing} appears to be a diffusers model.") + logger.debug(f"{thing} appears to be a diffusers model.") model_name = self.import_diffuser_model( thing, commit_to_conf=commit_to_conf ) else: - log.debug(f"{thing} appears to be a directory. Will scan for models to import") + logger.debug(f"{thing} appears to be a directory. Will scan for models to import") for m in list(Path(thing).rglob("*.ckpt")) + list( Path(thing).rglob("*.safetensors") ): if model_name := self.heuristic_import( str(m), commit_to_conf=commit_to_conf ): - log.info(f"{model_name} successfully imported") + logger.info(f"{model_name} successfully imported") return model_name elif re.match(r"^[\w.+-]+/[\w.+-]+$", thing): - log.debug(f"{thing} appears to be a HuggingFace diffusers repo_id") + logger.debug(f"{thing} appears to be a HuggingFace diffusers repo_id") model_name = self.import_diffuser_model( thing, commit_to_conf=commit_to_conf ) pipeline, _, _, _ = self._load_diffusers_model(self.config[model_name]) return model_name else: - log.warning(f"{thing}: Unknown thing. Please provide a URL, file path, directory or HuggingFace repo_id") + logger.warning(f"{thing}: Unknown thing. Please provide a URL, file path, directory or HuggingFace repo_id") # Model_path is set in the event of a legacy checkpoint file. # If not set, we're all done @@ -838,7 +838,7 @@ class ModelManager(object): return if model_path.stem in self.config: # already imported - log.debug("Already imported. Skipping") + logger.debug("Already imported. Skipping") return model_path.stem # another round of heuristics to guess the correct config file. @@ -854,38 +854,38 @@ class ModelManager(object): # look for a like-named .yaml file in same directory if model_path.with_suffix(".yaml").exists(): model_config_file = model_path.with_suffix(".yaml") - log.debug(f"Using config file {model_config_file.name}") + logger.debug(f"Using config file {model_config_file.name}") else: model_type = self.probe_model_type(checkpoint) if model_type == SDLegacyType.V1: - log.debug("SD-v1 model detected") + logger.debug("SD-v1 model detected") model_config_file = Path( Globals.root, "configs/stable-diffusion/v1-inference.yaml" ) elif model_type == SDLegacyType.V1_INPAINT: - log.debug("SD-v1 inpainting model detected") + logger.debug("SD-v1 inpainting model detected") model_config_file = Path( Globals.root, "configs/stable-diffusion/v1-inpainting-inference.yaml", ) elif model_type == SDLegacyType.V2_v: - log.debug("SD-v2-v model detected") + logger.debug("SD-v2-v model detected") model_config_file = Path( Globals.root, "configs/stable-diffusion/v2-inference-v.yaml" ) elif model_type == SDLegacyType.V2_e: - log.debug("SD-v2-e model detected") + logger.debug("SD-v2-e model detected") model_config_file = Path( Globals.root, "configs/stable-diffusion/v2-inference.yaml" ) elif model_type == SDLegacyType.V2: - log.warning( + logger.warning( f"{thing} is a V2 checkpoint file, but its parameterization cannot be determined. Please provide configuration file path." ) return else: - log.warning( + logger.warning( f"{thing} is a legacy checkpoint file but not a known Stable Diffusion model. Please provide configuration file path." ) return @@ -902,7 +902,7 @@ class ModelManager(object): for suffix in ["pt", "ckpt", "safetensors"]: if (model_path.with_suffix(f".vae.{suffix}")).exists(): vae_path = model_path.with_suffix(f".vae.{suffix}") - log.debug(f"Using VAE file {vae_path.name}") + logger.debug(f"Using VAE file {vae_path.name}") vae = None if vae_path else dict(repo_id="stabilityai/sd-vae-ft-mse") diffuser_path = Path( @@ -948,14 +948,14 @@ class ModelManager(object): from . import convert_ckpt_to_diffusers if diffusers_path.exists(): - log.error( + logger.error( f"The path {str(diffusers_path)} already exists. Please move or remove it and try again." ) return model_name = model_name or diffusers_path.name model_description = model_description or f"Converted version of {model_name}" - log.debug(f"Converting {model_name} to diffusers (30-60s)") + logger.debug(f"Converting {model_name} to diffusers (30-60s)") try: # By passing the specified VAE to the conversion function, the autoencoder # will be built into the model rather than tacked on afterward via the config file @@ -972,10 +972,10 @@ class ModelManager(object): vae_path=vae_path, scan_needed=scan_needed, ) - log.debug( + logger.debug( f"Success. Converted model is now located at {str(diffusers_path)}" ) - log.debug(f"Writing new config file entry for {model_name}") + logger.debug(f"Writing new config file entry for {model_name}") new_config = dict( path=str(diffusers_path), description=model_description, @@ -986,17 +986,17 @@ class ModelManager(object): self.add_model(model_name, new_config, True) if commit_to_conf: self.commit(commit_to_conf) - log.debug("Conversion succeeded") + logger.debug("Conversion succeeded") except Exception as e: - log.warning(f"Conversion failed: {str(e)}") - log.warning( + logger.warning(f"Conversion failed: {str(e)}") + logger.warning( "If you are trying to convert an inpainting or 2.X model, please indicate the correct config file (e.g. v1-inpainting-inference.yaml)" ) return model_name def search_models(self, search_folder): - log.info(f"Finding Models In: {search_folder}") + logger.info(f"Finding Models In: {search_folder}") models_folder_ckpt = Path(search_folder).glob("**/*.ckpt") models_folder_safetensors = Path(search_folder).glob("**/*.safetensors") @@ -1020,7 +1020,7 @@ class ModelManager(object): num_loaded_models = len(self.models) if num_loaded_models >= self.max_loaded_models: least_recent_model = self._pop_oldest_model() - log.info( + logger.info( f"Cache limit (max={self.max_loaded_models}) reached. Purging {least_recent_model}" ) if least_recent_model is not None: @@ -1029,7 +1029,7 @@ class ModelManager(object): def print_vram_usage(self) -> None: if self._has_cuda: - log.info( + logger.info( "Current VRAM usage:"+ "%4.2fG" % (torch.cuda.memory_allocated() / 1e9), ) @@ -1119,10 +1119,10 @@ class ModelManager(object): dest = hub / model.stem if dest.exists() and not source.exists(): continue - log.info(f"{source} => {dest}") + logger.info(f"{source} => {dest}") if source.exists(): if dest.is_symlink(): - log.warning(f"Found symlink at {dest.name}. Not migrating.") + logger.warning(f"Found symlink at {dest.name}. Not migrating.") elif dest.exists(): if source.is_dir(): rmtree(source) @@ -1139,7 +1139,7 @@ class ModelManager(object): ] for d in empty: os.rmdir(d) - log.info("Migration is done. Continuing...") + logger.info("Migration is done. Continuing...") def _resolve_path( self, source: Union[str, Path], dest_directory: str @@ -1182,14 +1182,14 @@ class ModelManager(object): def _add_embeddings_to_model(self, model: StableDiffusionGeneratorPipeline): if self.embedding_path is not None: - log.info(f"Loading embeddings from {self.embedding_path}") + logger.info(f"Loading embeddings from {self.embedding_path}") for root, _, files in os.walk(self.embedding_path): for name in files: ti_path = os.path.join(root, name) model.textual_inversion_manager.load_textual_inversion( ti_path, defer_injecting_tokens=True ) - log.info( + logger.info( f'Textual inversion triggers: {", ".join(sorted(model.textual_inversion_manager.get_all_trigger_strings()))}' ) @@ -1212,7 +1212,7 @@ class ModelManager(object): with open(hashpath) as f: hash = f.read() return hash - log.debug("Calculating sha256 hash of model files") + logger.debug("Calculating sha256 hash of model files") tic = time.time() sha = hashlib.sha256() count = 0 @@ -1224,7 +1224,7 @@ class ModelManager(object): sha.update(chunk) hash = sha.hexdigest() toc = time.time() - log.debug(f"sha256 = {hash} ({count} files hashed in", "%4.2fs)" % (toc - tic)) + logger.debug(f"sha256 = {hash} ({count} files hashed in", "%4.2fs)" % (toc - tic)) with open(hashpath, "w") as f: f.write(hash) return hash @@ -1242,13 +1242,13 @@ class ModelManager(object): hash = f.read() return hash - log.debug("Calculating sha256 hash of weights file") + logger.debug("Calculating sha256 hash of weights file") tic = time.time() sha = hashlib.sha256() sha.update(data) hash = sha.hexdigest() toc = time.time() - log.debug(f"sha256 = {hash} "+"(%4.2fs)" % (toc - tic)) + logger.debug(f"sha256 = {hash} "+"(%4.2fs)" % (toc - tic)) with open(hashpath, "w") as f: f.write(hash) @@ -1269,12 +1269,12 @@ class ModelManager(object): local_files_only=not Globals.internet_available, ) - log.debug(f"Loading diffusers VAE from {name_or_path}") + logger.debug(f"Loading diffusers VAE from {name_or_path}") if using_fp16: vae_args.update(torch_dtype=torch.float16) fp_args_list = [{"revision": "fp16"}, {}] else: - log.debug("Using more accurate float32 precision") + logger.debug("Using more accurate float32 precision") fp_args_list = [{}] vae = None @@ -1298,7 +1298,7 @@ class ModelManager(object): break if not vae and deferred_error: - log.warning(f"Could not load VAE {name_or_path}: {str(deferred_error)}") + logger.warning(f"Could not load VAE {name_or_path}: {str(deferred_error)}") return vae @@ -1314,7 +1314,7 @@ class ModelManager(object): for revision in repo.revisions: hashes_to_delete.add(revision.commit_hash) strategy = cache_info.delete_revisions(*hashes_to_delete) - log.warning( + logger.warning( f"Deletion of this model is expected to free {strategy.expected_freed_size_str}" ) strategy.execute() diff --git a/invokeai/backend/prompting/conditioning.py b/invokeai/backend/prompting/conditioning.py index 355cba2a6f..d9130ace04 100644 --- a/invokeai/backend/prompting/conditioning.py +++ b/invokeai/backend/prompting/conditioning.py @@ -18,7 +18,7 @@ from compel.prompt_parser import ( PromptParser, ) -import invokeai.backend.util.logging as log +import invokeai.backend.util.logging as logger from invokeai.backend.globals import Globals from ..stable_diffusion import InvokeAIDiffuserComponent @@ -163,8 +163,8 @@ def log_tokenization( negative_prompt: Union[Blend, FlattenedPrompt], tokenizer, ): - log.info(f"[TOKENLOG] Parsed Prompt: {positive_prompt}") - log.info(f"[TOKENLOG] Parsed Negative Prompt: {negative_prompt}") + logger.info(f"[TOKENLOG] Parsed Prompt: {positive_prompt}") + logger.info(f"[TOKENLOG] Parsed Negative Prompt: {negative_prompt}") log_tokenization_for_prompt_object(positive_prompt, tokenizer) log_tokenization_for_prompt_object( @@ -238,12 +238,12 @@ def log_tokenization_for_text(text, tokenizer, display_label=None, truncate_if_t usedTokens += 1 if usedTokens > 0: - log.info(f'[TOKENLOG] Tokens {display_label or ""} ({usedTokens}):') - log.debug(f"{tokenized}\x1b[0m") + logger.info(f'[TOKENLOG] Tokens {display_label or ""} ({usedTokens}):') + logger.debug(f"{tokenized}\x1b[0m") if discarded != "": - log.info(f"[TOKENLOG] Tokens Discarded ({totalTokens - usedTokens}):") - log.debug(f"{discarded}\x1b[0m") + logger.info(f"[TOKENLOG] Tokens Discarded ({totalTokens - usedTokens}):") + logger.debug(f"{discarded}\x1b[0m") def try_parse_legacy_blend(text: str, skip_normalize: bool = False) -> Optional[Blend]: @@ -296,7 +296,7 @@ def split_weighted_subprompts(text, skip_normalize=False) -> list: return parsed_prompts weight_sum = sum(map(lambda x: x[1], parsed_prompts)) if weight_sum == 0: - log.warning( + logger.warning( "Subprompt weights add up to zero. Discarding and using even weights instead." ) equal_weight = 1 / max(len(parsed_prompts), 1) diff --git a/invokeai/backend/restoration/base.py b/invokeai/backend/restoration/base.py index 794d7502da..f6f01da17d 100644 --- a/invokeai/backend/restoration/base.py +++ b/invokeai/backend/restoration/base.py @@ -1,4 +1,4 @@ -import invokeai.backend.util.logging as log +import invokeai.backend.util.logging as logger class Restoration: def __init__(self) -> None: @@ -10,17 +10,17 @@ class Restoration: # Load GFPGAN gfpgan = self.load_gfpgan(gfpgan_model_path) if gfpgan.gfpgan_model_exists: - log.info("GFPGAN Initialized") + logger.info("GFPGAN Initialized") else: - log.info("GFPGAN Disabled") + logger.info("GFPGAN Disabled") gfpgan = None # Load CodeFormer codeformer = self.load_codeformer() if codeformer.codeformer_model_exists: - log.info("CodeFormer Initialized") + logger.info("CodeFormer Initialized") else: - log.info("CodeFormer Disabled") + logger.info("CodeFormer Disabled") codeformer = None return gfpgan, codeformer @@ -41,5 +41,5 @@ class Restoration: from .realesrgan import ESRGAN esrgan = ESRGAN(esrgan_bg_tile) - log.info("ESRGAN Initialized") + logger.info("ESRGAN Initialized") return esrgan diff --git a/invokeai/backend/restoration/codeformer.py b/invokeai/backend/restoration/codeformer.py index db2a4fb1dd..5b578af082 100644 --- a/invokeai/backend/restoration/codeformer.py +++ b/invokeai/backend/restoration/codeformer.py @@ -5,7 +5,7 @@ import warnings import numpy as np import torch -import invokeai.backend.util.logging as log +import invokeai.backend.util.logging as logger from ..globals import Globals pretrained_model_url = ( @@ -24,12 +24,12 @@ class CodeFormerRestoration: self.codeformer_model_exists = os.path.isfile(self.model_path) if not self.codeformer_model_exists: - log.error("NOT FOUND: CodeFormer model not found at " + self.model_path) + logger.error("NOT FOUND: CodeFormer model not found at " + self.model_path) sys.path.append(os.path.abspath(codeformer_dir)) def process(self, image, strength, device, seed=None, fidelity=0.75): if seed is not None: - log.info(f"CodeFormer - Restoring Faces for image seed:{seed}") + logger.info(f"CodeFormer - Restoring Faces for image seed:{seed}") with warnings.catch_warnings(): warnings.filterwarnings("ignore", category=DeprecationWarning) warnings.filterwarnings("ignore", category=UserWarning) @@ -98,7 +98,7 @@ class CodeFormerRestoration: del output torch.cuda.empty_cache() except RuntimeError as error: - log.error(f"Failed inference for CodeFormer: {error}.") + logger.error(f"Failed inference for CodeFormer: {error}.") restored_face = cropped_face restored_face = restored_face.astype("uint8") diff --git a/invokeai/backend/restoration/gfpgan.py b/invokeai/backend/restoration/gfpgan.py index adcab2424c..b5c0278362 100644 --- a/invokeai/backend/restoration/gfpgan.py +++ b/invokeai/backend/restoration/gfpgan.py @@ -6,7 +6,7 @@ import numpy as np import torch from PIL import Image -import invokeai.backend.util.logging as log +import invokeai.backend.util.logging as logger from invokeai.backend.globals import Globals class GFPGAN: @@ -19,7 +19,7 @@ class GFPGAN: self.gfpgan_model_exists = os.path.isfile(self.model_path) if not self.gfpgan_model_exists: - log.error("NOT FOUND: GFPGAN model not found at " + self.model_path) + logger.error("NOT FOUND: GFPGAN model not found at " + self.model_path) return None def model_exists(self): @@ -27,7 +27,7 @@ class GFPGAN: def process(self, image, strength: float, seed: str = None): if seed is not None: - log.info(f"GFPGAN - Restoring Faces for image seed:{seed}") + logger.info(f"GFPGAN - Restoring Faces for image seed:{seed}") with warnings.catch_warnings(): warnings.filterwarnings("ignore", category=DeprecationWarning) @@ -47,13 +47,13 @@ class GFPGAN: except Exception: import traceback - log.error("Error loading GFPGAN:", file=sys.stderr) + logger.error("Error loading GFPGAN:", file=sys.stderr) print(traceback.format_exc(), file=sys.stderr) os.chdir(cwd) if self.gfpgan is None: - log.warning("WARNING: GFPGAN not initialized.") - log.warning( + logger.warning("WARNING: GFPGAN not initialized.") + logger.warning( f"Download https://github.com/TencentARC/GFPGAN/releases/download/v1.3.0/GFPGANv1.4.pth to {self.model_path}" ) diff --git a/invokeai/backend/restoration/outcrop.py b/invokeai/backend/restoration/outcrop.py index bc508b01ea..07f76d6bf9 100644 --- a/invokeai/backend/restoration/outcrop.py +++ b/invokeai/backend/restoration/outcrop.py @@ -1,7 +1,7 @@ import math from PIL import Image -import invokeai.backend.util.logging as log +import invokeai.backend.util.logging as logger class Outcrop(object): def __init__( @@ -82,7 +82,7 @@ class Outcrop(object): pixels = extents[direction] # round pixels up to the nearest 64 pixels = math.ceil(pixels / 64) * 64 - log.info(f"extending image {direction}ward by {pixels} pixels") + logger.info(f"extending image {direction}ward by {pixels} pixels") image = self._rotate(image, direction) image = self._extend(image, pixels) image = self._rotate(image, direction, reverse=True) diff --git a/invokeai/backend/restoration/realesrgan.py b/invokeai/backend/restoration/realesrgan.py index 15afb1f92f..9f26cc63ac 100644 --- a/invokeai/backend/restoration/realesrgan.py +++ b/invokeai/backend/restoration/realesrgan.py @@ -6,7 +6,7 @@ import torch from PIL import Image from PIL.Image import Image as ImageType -import invokeai.backend.util.logging as log +import invokeai.backend.util.logging as logger from invokeai.backend.globals import Globals class ESRGAN: @@ -69,15 +69,15 @@ class ESRGAN: import sys import traceback - log.error("Error loading Real-ESRGAN:") + logger.error("Error loading Real-ESRGAN:") print(traceback.format_exc(), file=sys.stderr) if upsampler_scale == 0: - log.warning("Real-ESRGAN: Invalid scaling option. Image not upscaled.") + logger.warning("Real-ESRGAN: Invalid scaling option. Image not upscaled.") return image if seed is not None: - log.info( + logger.info( f"Real-ESRGAN Upscaling seed:{seed}, scale:{upsampler_scale}x, tile:{self.bg_tile_size}, denoise:{denoise_str}" ) # ESRGAN outputs images with partial transparency if given RGBA images; convert to RGB diff --git a/invokeai/backend/safety_checker.py b/invokeai/backend/safety_checker.py index 97e3387fb4..3003981888 100644 --- a/invokeai/backend/safety_checker.py +++ b/invokeai/backend/safety_checker.py @@ -14,7 +14,7 @@ from PIL import Image, ImageFilter from transformers import AutoFeatureExtractor import invokeai.assets.web as web_assets -import invokeai.backend.util.logging as log +import invokeai.backend.util.logging as logger from .globals import global_cache_dir from .util import CPU_DEVICE @@ -41,7 +41,7 @@ class SafetyChecker(object): cache_dir=safety_model_path, ) except Exception: - log.error( + logger.error( "An error was encountered while installing the safety checker:" ) print(traceback.format_exc()) @@ -66,7 +66,7 @@ class SafetyChecker(object): ) self.safety_checker.to(CPU_DEVICE) # offload if has_nsfw_concept[0]: - log.warning( + logger.warning( "An image with potential non-safe content has been detected. A blurred image will be returned." ) return self.blur(image) diff --git a/invokeai/backend/stable_diffusion/concepts_lib.py b/invokeai/backend/stable_diffusion/concepts_lib.py index 85b3d81287..ebbcc9c3e9 100644 --- a/invokeai/backend/stable_diffusion/concepts_lib.py +++ b/invokeai/backend/stable_diffusion/concepts_lib.py @@ -17,7 +17,7 @@ from huggingface_hub import ( hf_hub_url, ) -import invokeai.backend.util.logging as log +import invokeai.backend.util.logging as logger from invokeai.backend.globals import Globals @@ -67,10 +67,10 @@ class HuggingFaceConceptsLibrary(object): # when init, add all in dir. when not init, add only concepts added between init and now self.concept_list.extend(list(local_concepts_to_add)) except Exception as e: - log.warning( + logger.warning( f"Hugging Face textual inversion concepts libraries could not be loaded. The error was {str(e)}." ) - log.warning( + logger.warning( "You may load .bin and .pt file(s) manually using the --embedding_directory argument." ) return self.concept_list @@ -84,7 +84,7 @@ class HuggingFaceConceptsLibrary(object): be downloaded. """ if not concept_name in self.list_concepts(): - log.warning( + logger.warning( f"{concept_name} is not a local embedding trigger, nor is it a HuggingFace concept. Generation will continue without the concept." ) return None @@ -222,7 +222,7 @@ class HuggingFaceConceptsLibrary(object): if chunk == 0: bytes += total - log.info(f"Downloading {repo_id}...", end="") + logger.info(f"Downloading {repo_id}...", end="") try: for file in ( "README.md", @@ -236,22 +236,22 @@ class HuggingFaceConceptsLibrary(object): ) except ul_error.HTTPError as e: if e.code == 404: - log.warning( + logger.warning( f"Concept {concept_name} is not known to the Hugging Face library. Generation will continue without the concept." ) else: - log.warning( + logger.warning( f"Failed to download {concept_name}/{file} ({str(e)}. Generation will continue without the concept.)" ) os.rmdir(dest) return False except ul_error.URLError as e: - log.error( + logger.error( f"an error occurred while downloading {concept_name}: {str(e)}. This may reflect a network issue. Generation will continue without the concept." ) os.rmdir(dest) return False - log.info("...{:.2f}Kb".format(bytes / 1024)) + logger.info("...{:.2f}Kb".format(bytes / 1024)) return succeeded def _concept_id(self, concept_name: str) -> str: diff --git a/invokeai/backend/stable_diffusion/diffusion/cross_attention_control.py b/invokeai/backend/stable_diffusion/diffusion/cross_attention_control.py index 1959269711..dfd19ea964 100644 --- a/invokeai/backend/stable_diffusion/diffusion/cross_attention_control.py +++ b/invokeai/backend/stable_diffusion/diffusion/cross_attention_control.py @@ -13,7 +13,7 @@ from compel.cross_attention_control import Arguments from diffusers.models.attention_processor import AttentionProcessor from torch import nn -import invokeai.backend.util.logging as log +import invokeai.backend.util.logging as logger from ...util import torch_dtype class CrossAttentionType(enum.Enum): @@ -421,7 +421,7 @@ def get_cross_attention_modules( expected_count = 16 if cross_attention_modules_in_model_count != expected_count: # non-fatal error but .swap() won't work. - log.error( + logger.error( f"Error! CrossAttentionControl found an unexpected number of {cross_attention_class} modules in the model " + f"(expected {expected_count}, found {cross_attention_modules_in_model_count}). Either monkey-patching failed " + "or some assumption has changed about the structure of the model itself. Please fix the monkey-patching, " diff --git a/invokeai/backend/stable_diffusion/diffusion/shared_invokeai_diffusion.py b/invokeai/backend/stable_diffusion/diffusion/shared_invokeai_diffusion.py index 827e114be8..b0c85e9fd3 100644 --- a/invokeai/backend/stable_diffusion/diffusion/shared_invokeai_diffusion.py +++ b/invokeai/backend/stable_diffusion/diffusion/shared_invokeai_diffusion.py @@ -8,7 +8,7 @@ import torch from diffusers.models.attention_processor import AttentionProcessor from typing_extensions import TypeAlias -import invokeai.backend.util.logging as log +import invokeai.backend.util.logging as logger from invokeai.backend.globals import Globals from .cross_attention_control import ( @@ -467,13 +467,13 @@ class InvokeAIDiffuserComponent: outside = torch.count_nonzero( (latents < -current_threshold) | (latents > current_threshold) ) - log.info( + logger.info( f"Threshold: %={percent_through} threshold={current_threshold:.3f} (of {threshold:.3f})" ) - log.debug( + logger.debug( f"min, mean, max = {minval:.3f}, {mean:.3f}, {maxval:.3f}\tstd={std}" ) - log.debug( + logger.debug( f"{outside / latents.numel() * 100:.2f}% values outside threshold" ) @@ -501,10 +501,10 @@ class InvokeAIDiffuserComponent: ) if self.debug_thresholding: - log.debug( + logger.debug( f"min, , max = {minval:.3f}, , {maxval:.3f}\t(scaled by {scale})" ) - log.debug( + logger.debug( f"{num_altered / latents.numel() * 100:.2f}% values altered" ) diff --git a/invokeai/backend/stable_diffusion/image_degradation/utils_image.py b/invokeai/backend/stable_diffusion/image_degradation/utils_image.py index 31f5300949..c4d37a24bf 100644 --- a/invokeai/backend/stable_diffusion/image_degradation/utils_image.py +++ b/invokeai/backend/stable_diffusion/image_degradation/utils_image.py @@ -10,7 +10,7 @@ from torchvision.utils import make_grid # import matplotlib.pyplot as plt # TODO: check with Dominik, also bsrgan.py vs bsrgan_light.py -import invokeai.backend.util.logging as log +import invokeai.backend.util.logging as logger os.environ["KMP_DUPLICATE_LIB_OK"] = "TRUE" @@ -191,7 +191,7 @@ def mkdirs(paths): def mkdir_and_rename(path): if os.path.exists(path): new_name = path + "_archived_" + get_timestamp() - log.error("Path already exists. Rename it to [{:s}]".format(new_name)) + logger.error("Path already exists. Rename it to [{:s}]".format(new_name)) os.replace(path, new_name) os.makedirs(path) diff --git a/invokeai/backend/stable_diffusion/textual_inversion_manager.py b/invokeai/backend/stable_diffusion/textual_inversion_manager.py index 1d27c7b813..9476c12dc5 100644 --- a/invokeai/backend/stable_diffusion/textual_inversion_manager.py +++ b/invokeai/backend/stable_diffusion/textual_inversion_manager.py @@ -10,7 +10,7 @@ from compel.embeddings_provider import BaseTextualInversionManager from picklescan.scanner import scan_file_path from transformers import CLIPTextModel, CLIPTokenizer -import invokeai.backend.util.logging as log +import invokeai.backend.util.logging as logger from .concepts_lib import HuggingFaceConceptsLibrary @dataclass @@ -60,12 +60,12 @@ class TextualInversionManager(BaseTextualInversionManager): or self.has_textual_inversion_for_trigger_string(concept_name) or self.has_textual_inversion_for_trigger_string(f"<{concept_name}>") ): # in case a token with literal angle brackets encountered - log.info(f"Loaded local embedding for trigger {concept_name}") + logger.info(f"Loaded local embedding for trigger {concept_name}") continue bin_file = self.hf_concepts_library.get_concept_model_path(concept_name) if not bin_file: continue - log.info(f"Loaded remote embedding for trigger {concept_name}") + logger.info(f"Loaded remote embedding for trigger {concept_name}") self.load_textual_inversion(bin_file) self.hf_concepts_library.concepts_loaded[concept_name] = True @@ -86,7 +86,7 @@ class TextualInversionManager(BaseTextualInversionManager): embedding_list = self._parse_embedding(str(ckpt_path)) for embedding_info in embedding_list: if (self.text_encoder.get_input_embeddings().weight.data[0].shape[0] != embedding_info.token_dim): - log.warning( + logger.warning( f"Notice: {ckpt_path.parents[0].name}/{ckpt_path.name} was trained on a model with an incompatible token dimension: {self.text_encoder.get_input_embeddings().weight.data[0].shape[0]} vs {embedding_info.token_dim}." ) continue @@ -106,7 +106,7 @@ class TextualInversionManager(BaseTextualInversionManager): if ckpt_path.name == "learned_embeds.bin" else f"<{ckpt_path.stem}>" ) - log.info( + logger.info( f"{sourcefile}: Trigger token '{trigger_str}' is already claimed by '{self.trigger_to_sourcefile[trigger_str]}'. Trigger this concept with {replacement_trigger_str}" ) trigger_str = replacement_trigger_str @@ -121,8 +121,8 @@ class TextualInversionManager(BaseTextualInversionManager): self.trigger_to_sourcefile[trigger_str] = sourcefile except ValueError as e: - log.debug(f'Ignoring incompatible embedding {embedding_info["name"]}') - log.debug(f"The error was {str(e)}") + logger.debug(f'Ignoring incompatible embedding {embedding_info["name"]}') + logger.debug(f"The error was {str(e)}") def _add_textual_inversion( self, trigger_str, embedding, defer_injecting_tokens=False @@ -134,7 +134,7 @@ class TextualInversionManager(BaseTextualInversionManager): :return: The token id for the added embedding, either existing or newly-added. """ if trigger_str in [ti.trigger_string for ti in self.textual_inversions]: - log.warning( + logger.warning( f"TextualInversionManager refusing to overwrite already-loaded token '{trigger_str}'" ) return @@ -156,10 +156,10 @@ class TextualInversionManager(BaseTextualInversionManager): except ValueError as e: if str(e).startswith("Warning"): - log.warning(f"{str(e)}") + logger.warning(f"{str(e)}") else: traceback.print_exc() - log.error( + logger.error( f"TextualInversionManager was unable to add a textual inversion with trigger string {trigger_str}." ) raise @@ -220,16 +220,16 @@ class TextualInversionManager(BaseTextualInversionManager): for ti in self.textual_inversions: if ti.trigger_token_id is None and ti.trigger_string in prompt_string: if ti.embedding_vector_length > 1: - log.info( + logger.info( f"Preparing tokens for textual inversion {ti.trigger_string}..." ) try: self._inject_tokens_and_assign_embeddings(ti) except ValueError as e: - log.debug( + logger.debug( f"Ignoring incompatible embedding trigger {ti.trigger_string}" ) - log.debug(f"The error was {str(e)}") + logger.debug(f"The error was {str(e)}") continue injected_token_ids.append(ti.trigger_token_id) injected_token_ids.extend(ti.pad_token_ids) @@ -307,16 +307,16 @@ class TextualInversionManager(BaseTextualInversionManager): if suffix in [".pt",".ckpt",".bin"]: scan_result = scan_file_path(embedding_file) if scan_result.infected_files > 0: - log.critical( + logger.critical( f"Security Issues Found in Model: {scan_result.issues_count}" ) - log.critical("For your safety, InvokeAI will not load this embed.") + logger.critical("For your safety, InvokeAI will not load this embed.") return list() ckpt = torch.load(embedding_file,map_location="cpu") else: ckpt = safetensors.torch.load_file(embedding_file) except Exception as e: - log.warning(f"Notice: unrecognized embedding file format: {embedding_file}: {e}") + logger.warning(f"Notice: unrecognized embedding file format: {embedding_file}: {e}") return list() # try to figure out what kind of embedding file it is and parse accordingly @@ -335,7 +335,7 @@ class TextualInversionManager(BaseTextualInversionManager): def _parse_embedding_v1(self, embedding_ckpt: dict, file_path: str)->List[EmbeddingInfo]: basename = Path(file_path).stem - log.debug(f'Loading v1 embedding file: {basename}') + logger.debug(f'Loading v1 embedding file: {basename}') embeddings = list() token_counter = -1 @@ -366,7 +366,7 @@ class TextualInversionManager(BaseTextualInversionManager): This handles embedding .pt file variant #2. """ basename = Path(file_path).stem - log.debug(f'Loading v2 embedding file: {basename}') + logger.debug(f'Loading v2 embedding file: {basename}') embeddings = list() if isinstance( @@ -385,7 +385,7 @@ class TextualInversionManager(BaseTextualInversionManager): ) embeddings.append(embedding_info) else: - log.warning(f"{basename}: Unrecognized embedding format") + logger.warning(f"{basename}: Unrecognized embedding format") return embeddings @@ -394,7 +394,7 @@ class TextualInversionManager(BaseTextualInversionManager): Parse 'version 3' of the .pt textual inversion embedding files. """ basename = Path(file_path).stem - log.debug(f'Loading v3 embedding file: {basename}') + logger.debug(f'Loading v3 embedding file: {basename}') embedding = embedding_ckpt['emb_params'] embedding_info = EmbeddingInfo( name = f'<{basename}>', @@ -412,11 +412,11 @@ class TextualInversionManager(BaseTextualInversionManager): basename = Path(filepath).stem short_path = Path(filepath).parents[0].name+'/'+Path(filepath).name - log.debug(f'Loading v4 embedding file: {short_path}') + logger.debug(f'Loading v4 embedding file: {short_path}') embeddings = list() if list(embedding_ckpt.keys()) == 0: - log.warning(f"Invalid embeddings file: {short_path}") + logger.warning(f"Invalid embeddings file: {short_path}") else: for token,embedding in embedding_ckpt.items(): embedding_info = EmbeddingInfo( diff --git a/invokeai/backend/util/logging.py b/invokeai/backend/util/logging.py index 1f820977ed..73f980aeff 100644 --- a/invokeai/backend/util/logging.py +++ b/invokeai/backend/util/logging.py @@ -26,7 +26,7 @@ Console messages: Another way: import invokeai.backend.util.logging as ialog -ialog.debug('this is a debugging message') +ialogger.debug('this is a debugging message') """ import logging diff --git a/invokeai/backend/util/util.py b/invokeai/backend/util/util.py index 95403a57e6..edc6a7b04b 100644 --- a/invokeai/backend/util/util.py +++ b/invokeai/backend/util/util.py @@ -18,7 +18,7 @@ import torch from PIL import Image, ImageDraw, ImageFont from tqdm import tqdm -import invokeai.backend.util.logging as log +import invokeai.backend.util.logging as logger from .devices import torch_dtype @@ -39,7 +39,7 @@ def log_txt_as_img(wh, xc, size=10): try: draw.text((0, 0), lines, fill="black", font=font) except UnicodeEncodeError: - log.warning("Cant encode string for logging. Skipping.") + logger.warning("Cant encode string for logging. Skipping.") txt = np.array(txt).transpose(2, 0, 1) / 127.5 - 1.0 txts.append(txt) @@ -81,7 +81,7 @@ def mean_flat(tensor): def count_params(model, verbose=False): total_params = sum(p.numel() for p in model.parameters()) if verbose: - log.debug( + logger.debug( f"{model.__class__.__name__} has {total_params * 1.e-6:.2f} M params." ) return total_params @@ -133,7 +133,7 @@ def parallel_data_prefetch( raise ValueError("list expected but function got ndarray.") elif isinstance(data, abc.Iterable): if isinstance(data, dict): - log.warning( + logger.warning( '"data" argument passed to parallel_data_prefetch is a dict: Using only its values and disregarding keys.' ) data = list(data.values()) @@ -176,7 +176,7 @@ def parallel_data_prefetch( processes += [p] # start processes - log.info("Start prefetching...") + logger.info("Start prefetching...") import time start = time.time() @@ -195,7 +195,7 @@ def parallel_data_prefetch( gather_res[res[0]] = res[1] except Exception as e: - log.error("Exception: ", e) + logger.error("Exception: ", e) for p in processes: p.terminate() @@ -203,7 +203,7 @@ def parallel_data_prefetch( finally: for p in processes: p.join() - log.info(f"Prefetching complete. [{time.time() - start} sec.]") + logger.info(f"Prefetching complete. [{time.time() - start} sec.]") if target_data_type == "ndarray": if not isinstance(gather_res[0], np.ndarray): @@ -319,23 +319,23 @@ def download_with_resume(url: str, dest: Path, access_token: str = None) -> Path resp = requests.get(url, headers=header, stream=True) # new request with range if exist_size > content_length: - log.warning("corrupt existing file found. re-downloading") + logger.warning("corrupt existing file found. re-downloading") os.remove(dest) exist_size = 0 if resp.status_code == 416 or exist_size == content_length: - log.warning(f"{dest}: complete file found. Skipping.") + logger.warning(f"{dest}: complete file found. Skipping.") return dest elif resp.status_code == 206 or exist_size > 0: - log.warning(f"{dest}: partial file found. Resuming...") + logger.warning(f"{dest}: partial file found. Resuming...") elif resp.status_code != 200: - log.error(f"An error occurred during downloading {dest}: {resp.reason}") + logger.error(f"An error occurred during downloading {dest}: {resp.reason}") else: - log.error(f"{dest}: Downloading...") + logger.error(f"{dest}: Downloading...") try: if content_length < 2000: - log.error(f"ERROR DOWNLOADING {url}: {resp.text}") + logger.error(f"ERROR DOWNLOADING {url}: {resp.text}") return None with open(dest, open_mode) as file, tqdm( @@ -350,7 +350,7 @@ def download_with_resume(url: str, dest: Path, access_token: str = None) -> Path size = file.write(data) bar.update(size) except Exception as e: - log.error(f"An error occurred while downloading {dest}: {str(e)}") + logger.error(f"An error occurred while downloading {dest}: {str(e)}") return None return dest diff --git a/invokeai/backend/web/invoke_ai_web_server.py b/invokeai/backend/web/invoke_ai_web_server.py index e7c02d212a..84478d5cb6 100644 --- a/invokeai/backend/web/invoke_ai_web_server.py +++ b/invokeai/backend/web/invoke_ai_web_server.py @@ -19,7 +19,7 @@ from PIL import Image from PIL.Image import Image as ImageType from werkzeug.utils import secure_filename -import invokeai.backend.util.logging as log +import invokeai.backend.util.logging as logger import invokeai.frontend.web.dist as frontend from .. import Generate @@ -214,7 +214,7 @@ class InvokeAIWebServer: self.load_socketio_listeners(self.socketio) if args.gui: - log.info("Launching Invoke AI GUI") + logger.info("Launching Invoke AI GUI") try: from flaskwebgui import FlaskUI @@ -232,16 +232,16 @@ class InvokeAIWebServer: sys.exit(0) else: useSSL = args.certfile or args.keyfile - log.info("Started Invoke AI Web Server") + logger.info("Started Invoke AI Web Server") if self.host == "0.0.0.0": - log.info( + logger.info( f"Point your browser at http{'s' if useSSL else ''}://localhost:{self.port} or use the host's DNS name or IP address." ) else: - log.info( + logger.info( "Default host address now 127.0.0.1 (localhost). Use --host 0.0.0.0 to bind any address." ) - log.info( + logger.info( f"Point your browser at http{'s' if useSSL else ''}://{self.host}:{self.port}" ) if not useSSL: @@ -274,7 +274,7 @@ class InvokeAIWebServer: # path for thumbnail images self.thumbnail_image_path = os.path.join(self.result_path, "thumbnails/") # txt log - self.log_path = os.path.join(self.result_path, "invoke_log.txt") + self.log_path = os.path.join(self.result_path, "invoke_logger.txt") # make all output paths [ os.makedirs(path, exist_ok=True) @@ -291,7 +291,7 @@ class InvokeAIWebServer: def load_socketio_listeners(self, socketio): @socketio.on("requestSystemConfig") def handle_request_capabilities(): - log.info("System config requested") + logger.info("System config requested") config = self.get_system_config() config["model_list"] = self.generate.model_manager.list_models() config["infill_methods"] = infill_methods() @@ -331,7 +331,7 @@ class InvokeAIWebServer: if model_name in current_model_list: update = True - log.info(f"Adding New Model: {model_name}") + logger.info(f"Adding New Model: {model_name}") self.generate.model_manager.add_model( model_name=model_name, @@ -349,14 +349,14 @@ class InvokeAIWebServer: "update": update, }, ) - log.info(f"New Model Added: {model_name}") + logger.info(f"New Model Added: {model_name}") except Exception as e: self.handle_exceptions(e) @socketio.on("deleteModel") def handle_delete_model(model_name: str): try: - log.info(f"Deleting Model: {model_name}") + logger.info(f"Deleting Model: {model_name}") self.generate.model_manager.del_model(model_name) self.generate.model_manager.commit(opt.conf) updated_model_list = self.generate.model_manager.list_models() @@ -367,14 +367,14 @@ class InvokeAIWebServer: "model_list": updated_model_list, }, ) - log.info(f"Model Deleted: {model_name}") + logger.info(f"Model Deleted: {model_name}") except Exception as e: self.handle_exceptions(e) @socketio.on("requestModelChange") def handle_set_model(model_name: str): try: - log.info(f"Model change requested: {model_name}") + logger.info(f"Model change requested: {model_name}") model = self.generate.set_model(model_name) model_list = self.generate.model_manager.list_models() if model is None: @@ -455,7 +455,7 @@ class InvokeAIWebServer: "update": True, }, ) - log.info(f"Model Converted: {model_name}") + logger.info(f"Model Converted: {model_name}") except Exception as e: self.handle_exceptions(e) @@ -491,7 +491,7 @@ class InvokeAIWebServer: if vae := self.generate.model_manager.config[models_to_merge[0]].get( "vae", None ): - log.info(f"Using configured VAE assigned to {models_to_merge[0]}") + logger.info(f"Using configured VAE assigned to {models_to_merge[0]}") merged_model_config.update(vae=vae) self.generate.model_manager.import_diffuser_model( @@ -508,8 +508,8 @@ class InvokeAIWebServer: "update": True, }, ) - log.info(f"Models Merged: {models_to_merge}") - log.info(f"New Model Added: {model_merge_info['merged_model_name']}") + logger.info(f"Models Merged: {models_to_merge}") + logger.info(f"New Model Added: {model_merge_info['merged_model_name']}") except Exception as e: self.handle_exceptions(e) @@ -699,7 +699,7 @@ class InvokeAIWebServer: } ) except Exception as e: - log.info(f"Unable to load {path}") + logger.info(f"Unable to load {path}") socketio.emit( "error", {"message": f"Unable to load {path}: {str(e)}"} ) @@ -736,9 +736,9 @@ class InvokeAIWebServer: printable_parameters["init_mask"][:64] + "..." ) - log.info(f"Image Generation Parameters:\n\n{printable_parameters}\n") - log.info(f"ESRGAN Parameters: {esrgan_parameters}") - log.info(f"Facetool Parameters: {facetool_parameters}") + logger.info(f"Image Generation Parameters:\n\n{printable_parameters}\n") + logger.info(f"ESRGAN Parameters: {esrgan_parameters}") + logger.info(f"Facetool Parameters: {facetool_parameters}") self.generate_images( generation_parameters, @@ -751,7 +751,7 @@ class InvokeAIWebServer: @socketio.on("runPostprocessing") def handle_run_postprocessing(original_image, postprocessing_parameters): try: - log.info( + logger.info( f'Postprocessing requested for "{original_image["url"]}": {postprocessing_parameters}' ) @@ -862,14 +862,14 @@ class InvokeAIWebServer: @socketio.on("cancel") def handle_cancel(): - log.info("Cancel processing requested") + logger.info("Cancel processing requested") self.canceled.set() # TODO: I think this needs a safety mechanism. @socketio.on("deleteImage") def handle_delete_image(url, thumbnail, uuid, category): try: - log.info(f'Delete requested "{url}"') + logger.info(f'Delete requested "{url}"') from send2trash import send2trash path = self.get_image_path_from_url(url) @@ -1264,7 +1264,7 @@ class InvokeAIWebServer: image, os.path.basename(path), self.thumbnail_image_path ) - log.info(f'Image generated: "{path}"\n') + logger.info(f'Image generated: "{path}"\n') self.write_log_message(f'[Generated] "{path}": {command}') if progress.total_iterations > progress.current_iteration: @@ -1330,7 +1330,7 @@ class InvokeAIWebServer: except Exception as e: # Clear the CUDA cache on an exception self.empty_cuda_cache() - log.error(e) + logger.error(e) self.handle_exceptions(e) def empty_cuda_cache(self): diff --git a/invokeai/frontend/CLI/CLI.py b/invokeai/frontend/CLI/CLI.py index 85a4d1a37d..aa0c4bea5f 100644 --- a/invokeai/frontend/CLI/CLI.py +++ b/invokeai/frontend/CLI/CLI.py @@ -16,7 +16,7 @@ if sys.platform == "darwin": import pyparsing # type: ignore import invokeai.version as invokeai -import invokeai.backend.util.logging as log +import invokeai.backend.util.logging as logger from ...backend import Generate, ModelManager from ...backend.args import Args, dream_cmd_from_png, metadata_dumps, metadata_from_png @@ -70,7 +70,7 @@ def main(): # run any post-install patches needed run_patches() - log.info(f"Internet connectivity is {Globals.internet_available}") + logger.info(f"Internet connectivity is {Globals.internet_available}") if not args.conf: config_file = os.path.join(Globals.root, "configs", "models.yaml") @@ -79,8 +79,8 @@ def main(): opt, FileNotFoundError(f"The file {config_file} could not be found.") ) - log.info(f"{invokeai.__app_name__}, version {invokeai.__version__}") - log.info(f'InvokeAI runtime directory is "{Globals.root}"') + logger.info(f"{invokeai.__app_name__}, version {invokeai.__version__}") + logger.info(f'InvokeAI runtime directory is "{Globals.root}"') # loading here to avoid long delays on startup # these two lines prevent a horrible warning message from appearing @@ -122,7 +122,7 @@ def main(): else: raise FileNotFoundError(f"{opt.infile} not found.") except (FileNotFoundError, IOError) as e: - log.critical('Aborted',exc_info=True) + logger.critical('Aborted',exc_info=True) sys.exit(-1) # creating a Generate object: @@ -144,11 +144,11 @@ def main(): except (FileNotFoundError, TypeError, AssertionError) as e: report_model_error(opt, e) except (IOError, KeyError): - log.critical("Aborted",exc_info=True) + logger.critical("Aborted",exc_info=True) sys.exit(-1) if opt.seamless: - log.info("Changed to seamless tiling mode") + logger.info("Changed to seamless tiling mode") # preload the model try: @@ -181,7 +181,7 @@ def main(): f'\nGoodbye!\nYou can start InvokeAI again by running the "invoke.bat" (or "invoke.sh") script from {Globals.root}' ) except Exception: - log.error("An error occurred",exc_info=True) + logger.error("An error occurred",exc_info=True) # TODO: main_loop() has gotten busy. Needs to be refactored. def main_loop(gen, opt): @@ -247,7 +247,7 @@ def main_loop(gen, opt): if not opt.prompt: oldargs = metadata_from_png(opt.init_img) opt.prompt = oldargs.prompt - log.info(f'Retrieved old prompt "{opt.prompt}" from {opt.init_img}') + logger.info(f'Retrieved old prompt "{opt.prompt}" from {opt.init_img}') except (OSError, AttributeError, KeyError): pass @@ -264,9 +264,9 @@ def main_loop(gen, opt): if opt.init_img is not None and re.match("^-\\d+$", opt.init_img): try: opt.init_img = last_results[int(opt.init_img)][0] - log.info(f"Reusing previous image {opt.init_img}") + logger.info(f"Reusing previous image {opt.init_img}") except IndexError: - log.info(f"No previous initial image at position {opt.init_img} found") + logger.info(f"No previous initial image at position {opt.init_img} found") opt.init_img = None continue @@ -287,9 +287,9 @@ def main_loop(gen, opt): if opt.seed is not None and opt.seed < 0 and operation != "postprocess": try: opt.seed = last_results[opt.seed][1] - log.info(f"Reusing previous seed {opt.seed}") + logger.info(f"Reusing previous seed {opt.seed}") except IndexError: - log.info(f"No previous seed at position {opt.seed} found") + logger.info(f"No previous seed at position {opt.seed} found") opt.seed = None continue @@ -308,7 +308,7 @@ def main_loop(gen, opt): subdir = subdir[: (path_max - 39 - len(os.path.abspath(opt.outdir)))] current_outdir = os.path.join(opt.outdir, subdir) - log.info('Writing files to directory: "' + current_outdir + '"') + logger.info('Writing files to directory: "' + current_outdir + '"') # make sure the output directory exists if not os.path.exists(current_outdir): @@ -438,13 +438,13 @@ def main_loop(gen, opt): **vars(opt), ) except (PromptParser.ParsingException, pyparsing.ParseException): - log.error("An error occurred while processing your prompt",exc_info=True) + logger.error("An error occurred while processing your prompt",exc_info=True) elif operation == "postprocess": - log.info(f"fixing {opt.prompt}") + logger.info(f"fixing {opt.prompt}") opt.last_operation = do_postprocess(gen, opt, image_writer) elif operation == "mask": - log.info(f"generating masks from {opt.prompt}") + logger.info(f"generating masks from {opt.prompt}") do_textmask(gen, opt, image_writer) if opt.grid and len(grid_images) > 0: @@ -468,11 +468,11 @@ def main_loop(gen, opt): results = [[path, formatted_dream_prompt]] except AssertionError: - log.error(e) + logger.error(e) continue except OSError as e: - log.error(e) + logger.error(e) continue print("Outputs:") @@ -511,7 +511,7 @@ def do_command(command: str, gen, opt: Args, completer) -> tuple: gen.set_model(model_name) add_embedding_terms(gen, completer) except KeyError as e: - log.error(e) + logger.error(e) except Exception as e: report_model_error(opt, e) completer.add_history(command) @@ -525,7 +525,7 @@ def do_command(command: str, gen, opt: Args, completer) -> tuple: elif command.startswith("!import"): path = shlex.split(command) if len(path) < 2: - log.warning( + logger.warning( "please provide (1) a URL to a .ckpt file to import; (2) a local path to a .ckpt file; or (3) a diffusers repository id in the form stabilityai/stable-diffusion-2-1" ) else: @@ -539,7 +539,7 @@ def do_command(command: str, gen, opt: Args, completer) -> tuple: elif command.startswith(("!convert", "!optimize")): path = shlex.split(command) if len(path) < 2: - log.warning("please provide the path to a .ckpt or .safetensors model") + logger.warning("please provide the path to a .ckpt or .safetensors model") else: try: convert_model(path[1], gen, opt, completer) @@ -551,7 +551,7 @@ def do_command(command: str, gen, opt: Args, completer) -> tuple: elif command.startswith("!edit"): path = shlex.split(command) if len(path) < 2: - log.warning("please provide the name of a model") + logger.warning("please provide the name of a model") else: edit_model(path[1], gen, opt, completer) completer.add_history(command) @@ -560,7 +560,7 @@ def do_command(command: str, gen, opt: Args, completer) -> tuple: elif command.startswith("!del"): path = shlex.split(command) if len(path) < 2: - log.warning("please provide the name of a model") + logger.warning("please provide the name of a model") else: del_config(path[1], gen, opt, completer) completer.add_history(command) @@ -641,7 +641,7 @@ def import_model(model_path: str, gen, opt, completer): default_name = url_attachment_name(model_path) default_name = Path(default_name).stem except Exception: - log.warning(f"A problem occurred while assigning the name of the downloaded model",exc_info=True) + logger.warning(f"A problem occurred while assigning the name of the downloaded model",exc_info=True) model_name, model_desc = _get_model_name_and_desc( gen.model_manager, completer, @@ -662,11 +662,11 @@ def import_model(model_path: str, gen, opt, completer): model_config_file=config_file, ) if not imported_name: - log.error("Aborting import.") + logger.error("Aborting import.") return if not _verify_load(imported_name, gen): - log.error("model failed to load. Discarding configuration entry") + logger.error("model failed to load. Discarding configuration entry") gen.model_manager.del_model(imported_name) return if click.confirm("Make this the default model?", default=False): @@ -674,7 +674,7 @@ def import_model(model_path: str, gen, opt, completer): gen.model_manager.commit(opt.conf) completer.update_models(gen.model_manager.list_models()) - log.info(f"{imported_name} successfully installed") + logger.info(f"{imported_name} successfully installed") def _pick_configuration_file(completer)->Path: print( @@ -718,21 +718,21 @@ Please select the type of this model: return choice def _verify_load(model_name: str, gen) -> bool: - log.info("Verifying that new model loads...") + logger.info("Verifying that new model loads...") current_model = gen.model_name try: if not gen.set_model(model_name): return except Exception as e: - log.warning(f"model failed to load: {str(e)}") - log.warning( + logger.warning(f"model failed to load: {str(e)}") + logger.warning( "** note that importing 2.X checkpoints is not supported. Please use !convert_model instead." ) return False if click.confirm("Keep model loaded?", default=True): gen.set_model(model_name) else: - log.info("Restoring previous model") + logger.info("Restoring previous model") gen.set_model(current_model) return True @@ -755,7 +755,7 @@ def convert_model(model_name_or_path: Union[Path, str], gen, opt, completer): ckpt_path = None original_config_file = None if model_name_or_path == gen.model_name: - log.warning("Can't convert the active model. !switch to another model first. **") + logger.warning("Can't convert the active model. !switch to another model first. **") return elif model_info := manager.model_info(model_name_or_path): if "weights" in model_info: @@ -765,7 +765,7 @@ def convert_model(model_name_or_path: Union[Path, str], gen, opt, completer): model_description = model_info["description"] vae_path = model_info.get("vae") else: - log.warning(f"{model_name_or_path} is not a legacy .ckpt weights file") + logger.warning(f"{model_name_or_path} is not a legacy .ckpt weights file") return model_name = manager.convert_and_import( ckpt_path, @@ -786,16 +786,16 @@ def convert_model(model_name_or_path: Union[Path, str], gen, opt, completer): manager.commit(opt.conf) if click.confirm(f"Delete the original .ckpt file at {ckpt_path}?", default=False): ckpt_path.unlink(missing_ok=True) - log.warning(f"{ckpt_path} deleted") + logger.warning(f"{ckpt_path} deleted") def del_config(model_name: str, gen, opt, completer): current_model = gen.model_name if model_name == current_model: - log.warning("Can't delete active model. !switch to another model first. **") + logger.warning("Can't delete active model. !switch to another model first. **") return if model_name not in gen.model_manager.config: - log.warning(f"Unknown model {model_name}") + logger.warning(f"Unknown model {model_name}") return if not click.confirm( @@ -808,17 +808,17 @@ def del_config(model_name: str, gen, opt, completer): ) gen.model_manager.del_model(model_name, delete_files=delete_completely) gen.model_manager.commit(opt.conf) - log.warning(f"{model_name} deleted") + logger.warning(f"{model_name} deleted") completer.update_models(gen.model_manager.list_models()) def edit_model(model_name: str, gen, opt, completer): manager = gen.model_manager if not (info := manager.model_info(model_name)): - log.warning(f"** Unknown model {model_name}") + logger.warning(f"** Unknown model {model_name}") return print() - log.info(f"Editing model {model_name} from configuration file {opt.conf}") + logger.info(f"Editing model {model_name} from configuration file {opt.conf}") new_name = _get_model_name(manager.list_models(), completer, model_name) for attribute in info.keys(): @@ -856,7 +856,7 @@ def edit_model(model_name: str, gen, opt, completer): manager.set_default_model(new_name) manager.commit(opt.conf) completer.update_models(manager.list_models()) - log.info("Model successfully updated") + logger.info("Model successfully updated") def _get_model_name(existing_names, completer, default_name: str = "") -> str: @@ -867,11 +867,11 @@ def _get_model_name(existing_names, completer, default_name: str = "") -> str: if len(model_name) == 0: model_name = default_name if not re.match("^[\w._+:/-]+$", model_name): - log.warning( + logger.warning( 'model name must contain only words, digits and the characters "._+:/-" **' ) elif model_name != default_name and model_name in existing_names: - log.warning(f"the name {model_name} is already in use. Pick another.") + logger.warning(f"the name {model_name} is already in use. Pick another.") else: done = True return model_name @@ -938,10 +938,10 @@ def do_postprocess(gen, opt, callback): opt=opt, ) except OSError: - log.error(f"{file_path}: file could not be read",exc_info=True) + logger.error(f"{file_path}: file could not be read",exc_info=True) return except (KeyError, AttributeError): - log.error(f"an error occurred while applying the {tool} postprocessor",exc_info=True) + logger.error(f"an error occurred while applying the {tool} postprocessor",exc_info=True) return return opt.last_operation @@ -996,12 +996,12 @@ def prepare_image_metadata( try: filename = opt.fnformat.format(**wildcards) except KeyError as e: - log.error( + logger.error( f"The filename format contains an unknown key '{e.args[0]}'. Will use {{prefix}}.{{seed}}.png' instead" ) filename = f"{prefix}.{seed}.png" except IndexError: - log.error( + logger.error( "The filename format is broken or complete. Will use '{prefix}.{seed}.png' instead" ) filename = f"{prefix}.{seed}.png" @@ -1091,14 +1091,14 @@ def split_variations(variations_string) -> list: for part in variations_string.split(","): seed_and_weight = part.split(":") if len(seed_and_weight) != 2: - log.warning(f'Could not parse with_variation part "{part}"') + logger.warning(f'Could not parse with_variation part "{part}"') broken = True break try: seed = int(seed_and_weight[0]) weight = float(seed_and_weight[1]) except ValueError: - log.warning(f'Could not parse with_variation part "{part}"') + logger.warning(f'Could not parse with_variation part "{part}"') broken = True break parts.append([seed, weight]) @@ -1122,23 +1122,23 @@ def load_face_restoration(opt): opt.gfpgan_model_path ) else: - log.info("Face restoration disabled") + logger.info("Face restoration disabled") if opt.esrgan: esrgan = restoration.load_esrgan(opt.esrgan_bg_tile) else: - log.info("Upscaling disabled") + logger.info("Upscaling disabled") else: - log.info("Face restoration and upscaling disabled") + logger.info("Face restoration and upscaling disabled") except (ModuleNotFoundError, ImportError): print(traceback.format_exc(), file=sys.stderr) - log.info("You may need to install the ESRGAN and/or GFPGAN modules") + logger.info("You may need to install the ESRGAN and/or GFPGAN modules") return gfpgan, codeformer, esrgan def make_step_callback(gen, opt, prefix): destination = os.path.join(opt.outdir, "intermediates", prefix) os.makedirs(destination, exist_ok=True) - log.info(f"Intermediate images will be written into {destination}") + logger.info(f"Intermediate images will be written into {destination}") def callback(state: PipelineIntermediateState): latents = state.latents @@ -1180,11 +1180,11 @@ def retrieve_dream_command(opt, command, completer): try: cmd = dream_cmd_from_png(path) except OSError: - log.error(f"{tokens[0]}: file could not be read") + logger.error(f"{tokens[0]}: file could not be read") except (KeyError, AttributeError, IndexError): - log.error(f"{tokens[0]}: file has no metadata") + logger.error(f"{tokens[0]}: file has no metadata") except: - log.error(f"{tokens[0]}: file could not be processed") + logger.error(f"{tokens[0]}: file could not be processed") if len(cmd) > 0: completer.set_line(cmd) @@ -1193,7 +1193,7 @@ def write_commands(opt, file_path: str, outfilepath: str): try: paths = sorted(list(Path(dir).glob(basename))) except ValueError: - log.error(f'"{basename}": unacceptable pattern') + logger.error(f'"{basename}": unacceptable pattern') return commands = [] @@ -1202,9 +1202,9 @@ def write_commands(opt, file_path: str, outfilepath: str): try: cmd = dream_cmd_from_png(path) except (KeyError, AttributeError, IndexError): - log.error(f"{path}: file has no metadata") + logger.error(f"{path}: file has no metadata") except: - log.error(f"{path}: file could not be processed") + logger.error(f"{path}: file could not be processed") if cmd: commands.append(f"# {path}") commands.append(cmd) @@ -1214,17 +1214,17 @@ def write_commands(opt, file_path: str, outfilepath: str): outfilepath = os.path.join(opt.outdir, basename) with open(outfilepath, "w", encoding="utf-8") as f: f.write("\n".join(commands)) - log.info(f"File {outfilepath} with commands created") + logger.info(f"File {outfilepath} with commands created") def report_model_error(opt: Namespace, e: Exception): - log.warning(f'An error occurred while attempting to initialize the model: "{str(e)}"') - log.warning( + logger.warning(f'An error occurred while attempting to initialize the model: "{str(e)}"') + logger.warning( "This can be caused by a missing or corrupted models file, and can sometimes be fixed by (re)installing the models." ) yes_to_all = os.environ.get("INVOKE_MODEL_RECONFIGURE") if yes_to_all: - log.warning( + logger.warning( "Reconfiguration is being forced by environment variable INVOKE_MODEL_RECONFIGURE" ) else: @@ -1234,7 +1234,7 @@ def report_model_error(opt: Namespace, e: Exception): ): return - log.info("invokeai-configure is launching....\n") + logger.info("invokeai-configure is launching....\n") # Match arguments that were set on the CLI # only the arguments accepted by the configuration script are parsed @@ -1251,7 +1251,7 @@ def report_model_error(opt: Namespace, e: Exception): from ..install import invokeai_configure invokeai_configure() - log.warning("InvokeAI will now restart") + logger.warning("InvokeAI will now restart") sys.argv = previous_args main() # would rather do a os.exec(), but doesn't exist? sys.exit(0) diff --git a/invokeai/frontend/install/model_install.py b/invokeai/frontend/install/model_install.py index 12213b8b67..c12104033f 100644 --- a/invokeai/frontend/install/model_install.py +++ b/invokeai/frontend/install/model_install.py @@ -22,7 +22,7 @@ import torch from npyscreen import widget from omegaconf import OmegaConf -import invokeai.backend.util.logging as log +import invokeai.backend.util.logging as logger from invokeai.backend.globals import Globals, global_config_dir from ...backend.config.model_install_backend import ( @@ -456,7 +456,7 @@ def main(): Globals.root = os.path.expanduser(get_root(opt.root) or "") if not global_config_dir().exists(): - log.info( + logger.info( "Your InvokeAI root directory is not set up. Calling invokeai-configure." ) from invokeai.frontend.install import invokeai_configure @@ -467,17 +467,17 @@ def main(): try: select_and_download_models(opt) except AssertionError as e: - log.error(e) + logger.error(e) sys.exit(-1) except KeyboardInterrupt: - log.info("Goodbye! Come back soon.") + logger.info("Goodbye! Come back soon.") except widget.NotEnoughSpaceForWidget as e: if str(e).startswith("Height of 1 allocated"): - log.error( + logger.error( "Insufficient vertical space for the interface. Please make your window taller and try again" ) elif str(e).startswith("addwstr"): - log.error( + logger.error( "Insufficient horizontal space for the interface. Please make your window wider and try again." ) diff --git a/invokeai/frontend/merge/merge_diffusers.py b/invokeai/frontend/merge/merge_diffusers.py index 7c2b621025..524118ba7c 100644 --- a/invokeai/frontend/merge/merge_diffusers.py +++ b/invokeai/frontend/merge/merge_diffusers.py @@ -28,7 +28,7 @@ from ...backend.globals import ( global_set_root, ) -import invokeai.backend.util.logging as log +import invokeai.backend.util.logging as logger from ...backend.model_management import ModelManager from ...frontend.install.widgets import FloatTitleSlider @@ -115,7 +115,7 @@ def merge_diffusion_models_and_commit( model_name=merged_model_name, description=f'Merge of models {", ".join(models)}' ) if vae := model_manager.config[models[0]].get("vae", None): - log.info(f"Using configured VAE assigned to {models[0]}") + logger.info(f"Using configured VAE assigned to {models[0]}") import_args.update(vae=vae) model_manager.import_diffuser_model(dump_path, **import_args) model_manager.commit(config_file) @@ -414,7 +414,7 @@ def run_gui(args: Namespace): args = mergeapp.merge_arguments merge_diffusion_models_and_commit(**args) - log.info(f'Models merged into new model: "{args["merged_model_name"]}".') + logger.info(f'Models merged into new model: "{args["merged_model_name"]}".') def run_cli(args: Namespace): @@ -425,7 +425,7 @@ def run_cli(args: Namespace): if not args.merged_model_name: args.merged_model_name = "+".join(args.models) - log.info( + logger.info( f'No --merged_model_name provided. Defaulting to "{args.merged_model_name}"' ) @@ -435,7 +435,7 @@ def run_cli(args: Namespace): ), f'A model named "{args.merged_model_name}" already exists. Use --clobber to overwrite.' merge_diffusion_models_and_commit(**vars(args)) - log.info(f'Models merged into new model: "{args.merged_model_name}".') + logger.info(f'Models merged into new model: "{args.merged_model_name}".') def main(): @@ -455,16 +455,16 @@ def main(): run_cli(args) except widget.NotEnoughSpaceForWidget as e: if str(e).startswith("Height of 1 allocated"): - log.error( + logger.error( "You need to have at least two diffusers models defined in models.yaml in order to merge" ) else: - log.error( + logger.error( "Not enough room for the user interface. Try making this window larger." ) sys.exit(-1) except Exception as e: - log.error(e) + logger.error(e) sys.exit(-1) except KeyboardInterrupt: sys.exit(-1) diff --git a/invokeai/frontend/training/textual_inversion.py b/invokeai/frontend/training/textual_inversion.py index 82fe450d93..23134d2736 100755 --- a/invokeai/frontend/training/textual_inversion.py +++ b/invokeai/frontend/training/textual_inversion.py @@ -20,7 +20,7 @@ import npyscreen from npyscreen import widget from omegaconf import OmegaConf -import invokeai.backend.util.logging as log +import invokeai.backend.util.logging as logger from invokeai.backend.globals import Globals, global_set_root from ...backend.training import do_textual_inversion_training, parse_args @@ -369,14 +369,14 @@ def copy_to_embeddings_folder(args: dict): dest_dir_name = args["placeholder_token"].strip("<>") destination = Path(Globals.root, "embeddings", dest_dir_name) os.makedirs(destination, exist_ok=True) - log.info(f"Training completed. Copying learned_embeds.bin into {str(destination)}") + logger.info(f"Training completed. Copying learned_embeds.bin into {str(destination)}") shutil.copy(source, destination) if ( input("Delete training logs and intermediate checkpoints? [y] ") or "y" ).startswith(("y", "Y")): shutil.rmtree(Path(args["output_dir"])) else: - log.info(f'Keeping {args["output_dir"]}') + logger.info(f'Keeping {args["output_dir"]}') def save_args(args: dict): @@ -423,10 +423,10 @@ def do_front_end(args: Namespace): do_textual_inversion_training(**args) copy_to_embeddings_folder(args) except Exception as e: - log.error("An exception occurred during training. The exception was:") - log.error(str(e)) - log.error("DETAILS:") - log.error(traceback.format_exc()) + logger.error("An exception occurred during training. The exception was:") + logger.error(str(e)) + logger.error("DETAILS:") + logger.error(traceback.format_exc()) def main(): @@ -438,21 +438,21 @@ def main(): else: do_textual_inversion_training(**vars(args)) except AssertionError as e: - log.error(e) + logger.error(e) sys.exit(-1) except KeyboardInterrupt: pass except (widget.NotEnoughSpaceForWidget, Exception) as e: if str(e).startswith("Height of 1 allocated"): - log.error( + logger.error( "You need to have at least one diffusers models defined in models.yaml in order to train" ) elif str(e).startswith("addwstr"): - log.error( + logger.error( "Not enough window space for the interface. Please make your window larger and try again." ) else: - log.error(e) + logger.error(e) sys.exit(-1) From 974841926d7889326859747ed1742d6ba0a45749 Mon Sep 17 00:00:00 2001 From: Lincoln Stein Date: Sat, 29 Apr 2023 10:48:50 -0400 Subject: [PATCH 37/68] logger is a interchangeable service --- invokeai/app/api/dependencies.py | 5 +- invokeai/app/api/routers/models.py | 6 +- invokeai/app/cli_app.py | 11 +- invokeai/app/invocations/util/choose_model.py | 2 +- invokeai/app/services/invocation_services.py | 6 +- .../app/services/model_manager_initializer.py | 16 +- invokeai/app/services/restoration_services.py | 16 +- .../backend/model_management/model_manager.py | 146 +++++++++--------- 8 files changed, 108 insertions(+), 100 deletions(-) diff --git a/invokeai/app/api/dependencies.py b/invokeai/app/api/dependencies.py index 454c2bbbf6..5f4a66ce6b 100644 --- a/invokeai/app/api/dependencies.py +++ b/invokeai/app/api/dependencies.py @@ -67,8 +67,9 @@ class ApiDependencies: db_location = os.path.join(output_folder, "invokeai.db") services = InvocationServices( - model_manager=get_model_manager(config), + model_manager=get_model_manager(config,logger), events=events, + logger=logger, latents=latents, images=images, metadata=metadata, @@ -80,7 +81,7 @@ class ApiDependencies: filename=db_location, table_name="graph_executions" ), processor=DefaultInvocationProcessor(), - restoration=RestorationServices(config), + restoration=RestorationServices(config,logger), ) create_system_graphs(services.graph_library) diff --git a/invokeai/app/api/routers/models.py b/invokeai/app/api/routers/models.py index 9e567bab45..ca83b44bf3 100644 --- a/invokeai/app/api/routers/models.py +++ b/invokeai/app/api/routers/models.py @@ -4,15 +4,10 @@ import shutil import asyncio from typing import Annotated, Any, List, Literal, Optional, Union -import invokeai.backend.util.logging as logger from fastapi.routing import APIRouter, HTTPException from pydantic import BaseModel, Field, parse_obj_as from pathlib import Path from ..dependencies import ApiDependencies -from invokeai.backend.globals import Globals, global_converted_ckpts_dir -from invokeai.backend.args import Args - - models_router = APIRouter(prefix="/v1/models", tags=["models"]) @@ -113,6 +108,7 @@ async def update_model( async def delete_model(model_name: str) -> None: """Delete Model""" model_names = ApiDependencies.invoker.services.model_manager.model_names() + logger = ApiDependencies.invoker.services.logger model_exists = model_name in model_names # check if model exists diff --git a/invokeai/app/cli_app.py b/invokeai/app/cli_app.py index 0d879e98d7..abe672820b 100644 --- a/invokeai/app/cli_app.py +++ b/invokeai/app/cli_app.py @@ -181,7 +181,7 @@ def invoke_all(context: CliContext): # Print any errors if context.session.has_error(): for n in context.session.errors: - logger.error( + context.invoker.services.logger.error( f"Error in node {n} (source node {context.session.prepared_source_mapping[n]}): {context.session.errors[n]}" ) @@ -191,7 +191,7 @@ def invoke_all(context: CliContext): def invoke_cli(): config = Args() config.parse_args() - model_manager = get_model_manager(config) + model_manager = get_model_manager(config,logger=logger) # This initializes the autocompleter and returns it. # Currently nothing is done with the returned Completer @@ -224,7 +224,8 @@ def invoke_cli(): filename=db_location, table_name="graph_executions" ), processor=DefaultInvocationProcessor(), - restoration=RestorationServices(config), + restoration=RestorationServices(config,logger=logger), + logger=logger, ) system_graphs = create_system_graphs(services.graph_library) @@ -364,12 +365,12 @@ def invoke_cli(): invoke_all(context) except InvalidArgs: - logger.warning('Invalid command, use "help" to list commands') + invoker.services.logger.warning('Invalid command, use "help" to list commands') continue except SessionError: # Start a new session - logger.warning("Session error: creating a new session") + invoker.services.logger.warning("Session error: creating a new session") context.reset() except ExitCli: diff --git a/invokeai/app/invocations/util/choose_model.py b/invokeai/app/invocations/util/choose_model.py index 99a4d14835..cd03ce87a8 100644 --- a/invokeai/app/invocations/util/choose_model.py +++ b/invokeai/app/invocations/util/choose_model.py @@ -1,9 +1,9 @@ -import invokeai.backend.util.logging as logger from invokeai.backend.model_management.model_manager import ModelManager def choose_model(model_manager: ModelManager, model_name: str): """Returns the default model if the `model_name` not a valid model, else returns the selected model.""" + logger = model_manager.logger if model_manager.valid_model(model_name): model = model_manager.get_model(model_name) else: diff --git a/invokeai/app/services/invocation_services.py b/invokeai/app/services/invocation_services.py index 1ff42f063d..47b3b6cf07 100644 --- a/invokeai/app/services/invocation_services.py +++ b/invokeai/app/services/invocation_services.py @@ -1,4 +1,6 @@ -# Copyright (c) 2022 Kyle Schouviller (https://github.com/kyle0654) +# Copyright (c) 2022 Kyle Schouviller (https://github.com/kyle0654) and the InvokeAI Team + +from typing import types from invokeai.app.services.metadata import MetadataServiceBase from invokeai.backend import ModelManager @@ -29,6 +31,7 @@ class InvocationServices: self, model_manager: ModelManager, events: EventServiceBase, + logger: types.ModuleType, latents: LatentsStorageBase, images: ImageStorageBase, metadata: MetadataServiceBase, @@ -40,6 +43,7 @@ class InvocationServices: ): self.model_manager = model_manager self.events = events + self.logger = logger self.latents = latents self.images = images self.metadata = metadata diff --git a/invokeai/app/services/model_manager_initializer.py b/invokeai/app/services/model_manager_initializer.py index 7f78f303f2..2b1aac1f36 100644 --- a/invokeai/app/services/model_manager_initializer.py +++ b/invokeai/app/services/model_manager_initializer.py @@ -5,20 +5,20 @@ from argparse import Namespace from invokeai.backend import Args from omegaconf import OmegaConf from pathlib import Path +from typing import types import invokeai.version -import invokeai.backend.util.logging as logger from ...backend import ModelManager from ...backend.util import choose_precision, choose_torch_device from ...backend import Globals # TODO: Replace with an abstract class base ModelManagerBase -def get_model_manager(config: Args) -> ModelManager: +def get_model_manager(config: Args, logger: types.ModuleType) -> ModelManager: if not config.conf: config_file = os.path.join(Globals.root, "configs", "models.yaml") if not os.path.exists(config_file): report_model_error( - config, FileNotFoundError(f"The file {config_file} could not be found.") + config, FileNotFoundError(f"The file {config_file} could not be found."), logger ) logger.info(f"{invokeai.version.__app_name__}, version {invokeai.version.__version__}") @@ -63,9 +63,10 @@ def get_model_manager(config: Args) -> ModelManager: device_type=device, max_loaded_models=config.max_loaded_models, embedding_path = Path(embedding_path), + logger = logger, ) except (FileNotFoundError, TypeError, AssertionError) as e: - report_model_error(config, e) + report_model_error(config, e, logger) except (IOError, KeyError) as e: logger.error(f"{e}. Aborting.") sys.exit(-1) @@ -77,17 +78,17 @@ def get_model_manager(config: Args) -> ModelManager: conf_path=config.conf, weights_directory=path, ) - + logger.info('Model manager initialized') return model_manager -def report_model_error(opt: Namespace, e: Exception): +def report_model_error(opt: Namespace, e: Exception, logger: types.ModuleType): logger.error(f'An error occurred while attempting to initialize the model: "{str(e)}"') logger.error( "This can be caused by a missing or corrupted models file, and can sometimes be fixed by (re)installing the models." ) yes_to_all = os.environ.get("INVOKE_MODEL_RECONFIGURE") if yes_to_all: - logger.warning + logger.warning( "Reconfiguration is being forced by environment variable INVOKE_MODEL_RECONFIGURE" ) else: @@ -103,7 +104,6 @@ def report_model_error(opt: Namespace, e: Exception): # only the arguments accepted by the configuration script are parsed root_dir = ["--root", opt.root_dir] if opt.root_dir is not None else [] config = ["--config", opt.conf] if opt.conf is not None else [] - previous_config = sys.argv sys.argv = ["invokeai-configure"] sys.argv.extend(root_dir) sys.argv.extend(config.to_dict()) diff --git a/invokeai/app/services/restoration_services.py b/invokeai/app/services/restoration_services.py index 7501b11e6b..7bd264444e 100644 --- a/invokeai/app/services/restoration_services.py +++ b/invokeai/app/services/restoration_services.py @@ -1,7 +1,7 @@ import sys import traceback import torch -import invokeai.backend.util.logging as logger +from typing import types from ...backend.restoration import Restoration from ...backend.util import choose_torch_device, CPU_DEVICE, MPS_DEVICE @@ -11,7 +11,7 @@ from ...backend.util import choose_torch_device, CPU_DEVICE, MPS_DEVICE class RestorationServices: '''Face restoration and upscaling''' - def __init__(self,args): + def __init__(self,args,logger:types.ModuleType): try: gfpgan, codeformer, esrgan = None, None, None if args.restore or args.esrgan: @@ -35,6 +35,8 @@ class RestorationServices: self.gfpgan = gfpgan self.codeformer = codeformer self.esrgan = esrgan + self.logger = logger + self.logger.info('Face restoration initialized') # note that this one method does gfpgan and codepath reconstruction, as well as # esrgan upscaling @@ -59,14 +61,14 @@ class RestorationServices: if self.gfpgan is not None or self.codeformer is not None: if facetool == "gfpgan": if self.gfpgan is None: - logger.info( + self.logger.info( "GFPGAN not found. Face restoration is disabled." ) else: image = self.gfpgan.process(image, strength, seed) if facetool == "codeformer": if self.codeformer is None: - logger.info( + self.logger.info( "CodeFormer not found. Face restoration is disabled." ) else: @@ -81,7 +83,7 @@ class RestorationServices: fidelity=codeformer_fidelity, ) else: - logger.info("Face Restoration is disabled.") + self.logger.info("Face Restoration is disabled.") if upscale is not None: if self.esrgan is not None: if len(upscale) < 2: @@ -94,9 +96,9 @@ class RestorationServices: denoise_str=upscale_denoise_str, ) else: - logger.info("ESRGAN is disabled. Image not upscaled.") + self.logger.info("ESRGAN is disabled. Image not upscaled.") except Exception as e: - logger.info( + self.logger.info( f"Error running RealESRGAN or GFPGAN. Your image was not upscaled.\n{e}" ) diff --git a/invokeai/backend/model_management/model_manager.py b/invokeai/backend/model_management/model_manager.py index 3f921828d5..a0a899a319 100644 --- a/invokeai/backend/model_management/model_manager.py +++ b/invokeai/backend/model_management/model_manager.py @@ -18,7 +18,7 @@ import warnings from enum import Enum, auto from pathlib import Path from shutil import move, rmtree -from typing import Any, Optional, Union, Callable +from typing import Any, Optional, Union, Callable, types import safetensors import safetensors.torch @@ -76,6 +76,8 @@ class ModelManager(object): Model manager handles loading, caching, importing, deleting, converting, and editing models. """ + logger: types.ModuleType = logger + def __init__( self, config: OmegaConf | Path, @@ -84,6 +86,7 @@ class ModelManager(object): max_loaded_models=DEFAULT_MAX_MODELS, sequential_offload=False, embedding_path: Path = None, + logger: types.ModuleType = logger, ): """ Initialize with the path to the models.yaml config file or @@ -105,6 +108,7 @@ class ModelManager(object): self.current_model = None self.sequential_offload = sequential_offload self.embedding_path = embedding_path + self.logger = logger def valid_model(self, model_name: str) -> bool: """ @@ -133,7 +137,7 @@ class ModelManager(object): ) if not self.valid_model(model_name): - logger.error( + self.logger.error( f'"{model_name}" is not a known model name. Please check your models.yaml file' ) return self.current_model @@ -145,7 +149,7 @@ class ModelManager(object): if model_name in self.models: requested_model = self.models[model_name]["model"] - logger.info(f"Retrieving model {model_name} from system RAM cache") + self.logger.info(f"Retrieving model {model_name} from system RAM cache") requested_model.ready() width = self.models[model_name]["width"] height = self.models[model_name]["height"] @@ -380,7 +384,7 @@ class ModelManager(object): """ omega = self.config if model_name not in omega: - logger.error(f"Unknown model {model_name}") + self.logger.error(f"Unknown model {model_name}") return # save these for use in deletion later conf = omega[model_name] @@ -393,13 +397,13 @@ class ModelManager(object): self.stack.remove(model_name) if delete_files: if weights: - logger.info(f"Deleting file {weights}") + self.logger.info(f"Deleting file {weights}") Path(weights).unlink(missing_ok=True) elif path: - logger.info(f"Deleting directory {path}") + self.logger.info(f"Deleting directory {path}") rmtree(path, ignore_errors=True) elif repo_id: - logger.info(f"Deleting the cached model directory for {repo_id}") + self.logger.info(f"Deleting the cached model directory for {repo_id}") self._delete_model_from_cache(repo_id) def add_model( @@ -440,7 +444,7 @@ class ModelManager(object): def _load_model(self, model_name: str): """Load and initialize the model from configuration variables passed at object creation time""" if model_name not in self.config: - logger.error( + self.logger.error( f'"{model_name}" is not a known model name. Please check your models.yaml file' ) return @@ -458,7 +462,7 @@ class ModelManager(object): model_format = mconfig.get("format", "ckpt") if model_format == "ckpt": weights = mconfig.weights - logger.info(f"Loading {model_name} from {weights}") + self.logger.info(f"Loading {model_name} from {weights}") model, width, height, model_hash = self._load_ckpt_model( model_name, mconfig ) @@ -474,13 +478,13 @@ class ModelManager(object): # usage statistics toc = time.time() - logger.info("Model loaded in " + "%4.2fs" % (toc - tic)) + self.logger.info("Model loaded in " + "%4.2fs" % (toc - tic)) if self._has_cuda(): - logger.info( + self.logger.info( "Max VRAM used to load the model: "+ "%4.2fG" % (torch.cuda.max_memory_allocated() / 1e9) ) - logger.info( + self.logger.info( "Current VRAM usage: "+ "%4.2fG" % (torch.cuda.memory_allocated() / 1e9) ) @@ -490,11 +494,11 @@ class ModelManager(object): name_or_path = self.model_name_or_path(mconfig) using_fp16 = self.precision == "float16" - logger.info(f"Loading diffusers model from {name_or_path}") + self.logger.info(f"Loading diffusers model from {name_or_path}") if using_fp16: - logger.debug("Using faster float16 precision") + self.logger.debug("Using faster float16 precision") else: - logger.debug("Using more accurate float32 precision") + self.logger.debug("Using more accurate float32 precision") # TODO: scan weights maybe? pipeline_args: dict[str, Any] = dict( @@ -526,7 +530,7 @@ class ModelManager(object): if str(e).startswith("fp16 is not a valid"): pass else: - logger.error( + self.logger.error( f"An unexpected error occurred while downloading the model: {e})" ) if pipeline: @@ -545,7 +549,7 @@ class ModelManager(object): # square images??? width = pipeline.unet.config.sample_size * pipeline.vae_scale_factor height = width - logger.debug(f"Default image dimensions = {width} x {height}") + self.logger.debug(f"Default image dimensions = {width} x {height}") return pipeline, width, height, model_hash @@ -562,7 +566,7 @@ class ModelManager(object): weights = os.path.normpath(os.path.join(Globals.root, weights)) # Convert to diffusers and return a diffusers pipeline - logger.info(f"Converting legacy checkpoint {model_name} into a diffusers model...") + self.logger.info(f"Converting legacy checkpoint {model_name} into a diffusers model...") from . import load_pipeline_from_original_stable_diffusion_ckpt @@ -627,7 +631,7 @@ class ModelManager(object): if model_name not in self.models: return - logger.info(f"Offloading {model_name} to CPU") + self.logger.info(f"Offloading {model_name} to CPU") model = self.models[model_name]["model"] model.offload_all() self.current_model = None @@ -643,26 +647,26 @@ class ModelManager(object): and option to exit if an infected file is identified. """ # scan model - logger.debug(f"Scanning Model: {model_name}") + self.logger.debug(f"Scanning Model: {model_name}") scan_result = scan_file_path(checkpoint) if scan_result.infected_files != 0: if scan_result.infected_files == 1: - logger.critical(f"Issues Found In Model: {scan_result.issues_count}") - logger.critical("The model you are trying to load seems to be infected.") - logger.critical("For your safety, InvokeAI will not load this model.") - logger.critical("Please use checkpoints from trusted sources.") - logger.critical("Exiting InvokeAI") + self.logger.critical(f"Issues Found In Model: {scan_result.issues_count}") + self.logger.critical("The model you are trying to load seems to be infected.") + self.logger.critical("For your safety, InvokeAI will not load this model.") + self.logger.critical("Please use checkpoints from trusted sources.") + self.logger.critical("Exiting InvokeAI") sys.exit() else: - logger.warning("InvokeAI was unable to scan the model you are using.") + self.logger.warning("InvokeAI was unable to scan the model you are using.") model_safe_check_fail = ask_user( "Do you want to to continue loading the model?", ["y", "n"] ) if model_safe_check_fail.lower() != "y": - logger.critical("Exiting InvokeAI") + self.logger.critical("Exiting InvokeAI") sys.exit() else: - logger.debug("Model scanned ok") + self.logger.debug("Model scanned ok") def import_diffuser_model( self, @@ -779,24 +783,24 @@ class ModelManager(object): model_path: Path = None thing = path_url_or_repo # to save typing - logger.info(f"Probing {thing} for import") + self.logger.info(f"Probing {thing} for import") if thing.startswith(("http:", "https:", "ftp:")): - logger.info(f"{thing} appears to be a URL") + self.logger.info(f"{thing} appears to be a URL") model_path = self._resolve_path( thing, "models/ldm/stable-diffusion-v1" ) # _resolve_path does a download if needed elif Path(thing).is_file() and thing.endswith((".ckpt", ".safetensors")): if Path(thing).stem in ["model", "diffusion_pytorch_model"]: - logger.debug(f"{Path(thing).name} appears to be part of a diffusers model. Skipping import") + self.logger.debug(f"{Path(thing).name} appears to be part of a diffusers model. Skipping import") return else: - logger.debug(f"{thing} appears to be a checkpoint file on disk") + self.logger.debug(f"{thing} appears to be a checkpoint file on disk") model_path = self._resolve_path(thing, "models/ldm/stable-diffusion-v1") elif Path(thing).is_dir() and Path(thing, "model_index.json").exists(): - logger.debug(f"{thing} appears to be a diffusers file on disk") + self.logger.debug(f"{thing} appears to be a diffusers file on disk") model_name = self.import_diffuser_model( thing, vae=dict(repo_id="stabilityai/sd-vae-ft-mse"), @@ -807,30 +811,30 @@ class ModelManager(object): elif Path(thing).is_dir(): if (Path(thing) / "model_index.json").exists(): - logger.debug(f"{thing} appears to be a diffusers model.") + self.logger.debug(f"{thing} appears to be a diffusers model.") model_name = self.import_diffuser_model( thing, commit_to_conf=commit_to_conf ) else: - logger.debug(f"{thing} appears to be a directory. Will scan for models to import") + self.logger.debug(f"{thing} appears to be a directory. Will scan for models to import") for m in list(Path(thing).rglob("*.ckpt")) + list( Path(thing).rglob("*.safetensors") ): if model_name := self.heuristic_import( str(m), commit_to_conf=commit_to_conf ): - logger.info(f"{model_name} successfully imported") + self.logger.info(f"{model_name} successfully imported") return model_name elif re.match(r"^[\w.+-]+/[\w.+-]+$", thing): - logger.debug(f"{thing} appears to be a HuggingFace diffusers repo_id") + self.logger.debug(f"{thing} appears to be a HuggingFace diffusers repo_id") model_name = self.import_diffuser_model( thing, commit_to_conf=commit_to_conf ) pipeline, _, _, _ = self._load_diffusers_model(self.config[model_name]) return model_name else: - logger.warning(f"{thing}: Unknown thing. Please provide a URL, file path, directory or HuggingFace repo_id") + self.logger.warning(f"{thing}: Unknown thing. Please provide a URL, file path, directory or HuggingFace repo_id") # Model_path is set in the event of a legacy checkpoint file. # If not set, we're all done @@ -838,7 +842,7 @@ class ModelManager(object): return if model_path.stem in self.config: # already imported - logger.debug("Already imported. Skipping") + self.logger.debug("Already imported. Skipping") return model_path.stem # another round of heuristics to guess the correct config file. @@ -854,38 +858,38 @@ class ModelManager(object): # look for a like-named .yaml file in same directory if model_path.with_suffix(".yaml").exists(): model_config_file = model_path.with_suffix(".yaml") - logger.debug(f"Using config file {model_config_file.name}") + self.logger.debug(f"Using config file {model_config_file.name}") else: model_type = self.probe_model_type(checkpoint) if model_type == SDLegacyType.V1: - logger.debug("SD-v1 model detected") + self.logger.debug("SD-v1 model detected") model_config_file = Path( Globals.root, "configs/stable-diffusion/v1-inference.yaml" ) elif model_type == SDLegacyType.V1_INPAINT: - logger.debug("SD-v1 inpainting model detected") + self.logger.debug("SD-v1 inpainting model detected") model_config_file = Path( Globals.root, "configs/stable-diffusion/v1-inpainting-inference.yaml", ) elif model_type == SDLegacyType.V2_v: - logger.debug("SD-v2-v model detected") + self.logger.debug("SD-v2-v model detected") model_config_file = Path( Globals.root, "configs/stable-diffusion/v2-inference-v.yaml" ) elif model_type == SDLegacyType.V2_e: - logger.debug("SD-v2-e model detected") + self.logger.debug("SD-v2-e model detected") model_config_file = Path( Globals.root, "configs/stable-diffusion/v2-inference.yaml" ) elif model_type == SDLegacyType.V2: - logger.warning( + self.logger.warning( f"{thing} is a V2 checkpoint file, but its parameterization cannot be determined. Please provide configuration file path." ) return else: - logger.warning( + self.logger.warning( f"{thing} is a legacy checkpoint file but not a known Stable Diffusion model. Please provide configuration file path." ) return @@ -902,7 +906,7 @@ class ModelManager(object): for suffix in ["pt", "ckpt", "safetensors"]: if (model_path.with_suffix(f".vae.{suffix}")).exists(): vae_path = model_path.with_suffix(f".vae.{suffix}") - logger.debug(f"Using VAE file {vae_path.name}") + self.logger.debug(f"Using VAE file {vae_path.name}") vae = None if vae_path else dict(repo_id="stabilityai/sd-vae-ft-mse") diffuser_path = Path( @@ -948,14 +952,14 @@ class ModelManager(object): from . import convert_ckpt_to_diffusers if diffusers_path.exists(): - logger.error( + self.logger.error( f"The path {str(diffusers_path)} already exists. Please move or remove it and try again." ) return model_name = model_name or diffusers_path.name model_description = model_description or f"Converted version of {model_name}" - logger.debug(f"Converting {model_name} to diffusers (30-60s)") + self.logger.debug(f"Converting {model_name} to diffusers (30-60s)") try: # By passing the specified VAE to the conversion function, the autoencoder # will be built into the model rather than tacked on afterward via the config file @@ -972,10 +976,10 @@ class ModelManager(object): vae_path=vae_path, scan_needed=scan_needed, ) - logger.debug( + self.logger.debug( f"Success. Converted model is now located at {str(diffusers_path)}" ) - logger.debug(f"Writing new config file entry for {model_name}") + self.logger.debug(f"Writing new config file entry for {model_name}") new_config = dict( path=str(diffusers_path), description=model_description, @@ -986,17 +990,17 @@ class ModelManager(object): self.add_model(model_name, new_config, True) if commit_to_conf: self.commit(commit_to_conf) - logger.debug("Conversion succeeded") + self.logger.debug("Conversion succeeded") except Exception as e: - logger.warning(f"Conversion failed: {str(e)}") - logger.warning( + self.logger.warning(f"Conversion failed: {str(e)}") + self.logger.warning( "If you are trying to convert an inpainting or 2.X model, please indicate the correct config file (e.g. v1-inpainting-inference.yaml)" ) return model_name def search_models(self, search_folder): - logger.info(f"Finding Models In: {search_folder}") + self.logger.info(f"Finding Models In: {search_folder}") models_folder_ckpt = Path(search_folder).glob("**/*.ckpt") models_folder_safetensors = Path(search_folder).glob("**/*.safetensors") @@ -1020,7 +1024,7 @@ class ModelManager(object): num_loaded_models = len(self.models) if num_loaded_models >= self.max_loaded_models: least_recent_model = self._pop_oldest_model() - logger.info( + self.logger.info( f"Cache limit (max={self.max_loaded_models}) reached. Purging {least_recent_model}" ) if least_recent_model is not None: @@ -1029,7 +1033,7 @@ class ModelManager(object): def print_vram_usage(self) -> None: if self._has_cuda: - logger.info( + self.logger.info( "Current VRAM usage:"+ "%4.2fG" % (torch.cuda.memory_allocated() / 1e9), ) @@ -1119,7 +1123,7 @@ class ModelManager(object): dest = hub / model.stem if dest.exists() and not source.exists(): continue - logger.info(f"{source} => {dest}") + cls.logger.info(f"{source} => {dest}") if source.exists(): if dest.is_symlink(): logger.warning(f"Found symlink at {dest.name}. Not migrating.") @@ -1139,7 +1143,7 @@ class ModelManager(object): ] for d in empty: os.rmdir(d) - logger.info("Migration is done. Continuing...") + cls.logger.info("Migration is done. Continuing...") def _resolve_path( self, source: Union[str, Path], dest_directory: str @@ -1182,14 +1186,14 @@ class ModelManager(object): def _add_embeddings_to_model(self, model: StableDiffusionGeneratorPipeline): if self.embedding_path is not None: - logger.info(f"Loading embeddings from {self.embedding_path}") + self.logger.info(f"Loading embeddings from {self.embedding_path}") for root, _, files in os.walk(self.embedding_path): for name in files: ti_path = os.path.join(root, name) model.textual_inversion_manager.load_textual_inversion( ti_path, defer_injecting_tokens=True ) - logger.info( + self.logger.info( f'Textual inversion triggers: {", ".join(sorted(model.textual_inversion_manager.get_all_trigger_strings()))}' ) @@ -1212,7 +1216,7 @@ class ModelManager(object): with open(hashpath) as f: hash = f.read() return hash - logger.debug("Calculating sha256 hash of model files") + self.logger.debug("Calculating sha256 hash of model files") tic = time.time() sha = hashlib.sha256() count = 0 @@ -1224,7 +1228,7 @@ class ModelManager(object): sha.update(chunk) hash = sha.hexdigest() toc = time.time() - logger.debug(f"sha256 = {hash} ({count} files hashed in", "%4.2fs)" % (toc - tic)) + self.logger.debug(f"sha256 = {hash} ({count} files hashed in", "%4.2fs)" % (toc - tic)) with open(hashpath, "w") as f: f.write(hash) return hash @@ -1242,13 +1246,13 @@ class ModelManager(object): hash = f.read() return hash - logger.debug("Calculating sha256 hash of weights file") + self.logger.debug("Calculating sha256 hash of weights file") tic = time.time() sha = hashlib.sha256() sha.update(data) hash = sha.hexdigest() toc = time.time() - logger.debug(f"sha256 = {hash} "+"(%4.2fs)" % (toc - tic)) + self.logger.debug(f"sha256 = {hash} "+"(%4.2fs)" % (toc - tic)) with open(hashpath, "w") as f: f.write(hash) @@ -1269,12 +1273,12 @@ class ModelManager(object): local_files_only=not Globals.internet_available, ) - logger.debug(f"Loading diffusers VAE from {name_or_path}") + self.logger.debug(f"Loading diffusers VAE from {name_or_path}") if using_fp16: vae_args.update(torch_dtype=torch.float16) fp_args_list = [{"revision": "fp16"}, {}] else: - logger.debug("Using more accurate float32 precision") + self.logger.debug("Using more accurate float32 precision") fp_args_list = [{}] vae = None @@ -1298,12 +1302,12 @@ class ModelManager(object): break if not vae and deferred_error: - logger.warning(f"Could not load VAE {name_or_path}: {str(deferred_error)}") + self.logger.warning(f"Could not load VAE {name_or_path}: {str(deferred_error)}") return vae - @staticmethod - def _delete_model_from_cache(repo_id): + @classmethod + def _delete_model_from_cache(cls,repo_id): cache_info = scan_cache_dir(global_cache_dir("hub")) # I'm sure there is a way to do this with comprehensions @@ -1314,7 +1318,7 @@ class ModelManager(object): for revision in repo.revisions: hashes_to_delete.add(revision.commit_hash) strategy = cache_info.delete_revisions(*hashes_to_delete) - logger.warning( + cls.logger.warning( f"Deletion of this model is expected to free {strategy.expected_freed_size_str}" ) strategy.execute() From 16488e7db881b82f25e42dcc81e8288d5152047d Mon Sep 17 00:00:00 2001 From: Lincoln Stein Date: Sat, 29 Apr 2023 10:59:50 -0400 Subject: [PATCH 38/68] fix tests --- tests/nodes/test_graph_execution_state.py | 1 + tests/nodes/test_invoker.py | 1 + 2 files changed, 2 insertions(+) diff --git a/tests/nodes/test_graph_execution_state.py b/tests/nodes/test_graph_execution_state.py index 2476786e41..3c262cf88e 100644 --- a/tests/nodes/test_graph_execution_state.py +++ b/tests/nodes/test_graph_execution_state.py @@ -25,6 +25,7 @@ def mock_services(): return InvocationServices( model_manager = None, # type: ignore events = None, # type: ignore + logger = None, # type: ignore images = None, # type: ignore latents = None, # type: ignore metadata = None, # type: ignore diff --git a/tests/nodes/test_invoker.py b/tests/nodes/test_invoker.py index d187c1b171..66c6b94d6f 100644 --- a/tests/nodes/test_invoker.py +++ b/tests/nodes/test_invoker.py @@ -23,6 +23,7 @@ def mock_services() -> InvocationServices: return InvocationServices( model_manager = None, # type: ignore events = TestEventService(), + logger = None, # type: ignore images = None, # type: ignore latents = None, # type: ignore metadata = None, # type: ignore From 0cad204e7493e44770a73df865dd3d71de4468f5 Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Sat, 29 Apr 2023 19:10:32 +1000 Subject: [PATCH 39/68] feat(ui): add error handling for linear graph generation --- invokeai/frontend/web/package.json | 1 + .../web/src/services/thunks/session.ts | 37 +++++++++++++------ invokeai/frontend/web/yarn.lock | 12 ++++++ 3 files changed, 38 insertions(+), 12 deletions(-) diff --git a/invokeai/frontend/web/package.json b/invokeai/frontend/web/package.json index 6ee6a9c8f4..684c56451c 100644 --- a/invokeai/frontend/web/package.json +++ b/invokeai/frontend/web/package.json @@ -95,6 +95,7 @@ "redux-dynamic-middlewares": "^2.2.0", "redux-persist": "^6.0.0", "roarr": "^7.15.0", + "serialize-error": "^11.0.0", "socket.io-client": "^4.6.0", "use-image": "^1.1.0", "uuid": "^9.0.0" diff --git a/invokeai/frontend/web/src/services/thunks/session.ts b/invokeai/frontend/web/src/services/thunks/session.ts index 0641437d52..af03045967 100644 --- a/invokeai/frontend/web/src/services/thunks/session.ts +++ b/invokeai/frontend/web/src/services/thunks/session.ts @@ -4,28 +4,41 @@ import { buildLinearGraph as buildGenerateGraph } from 'features/nodes/util/line import { isAnyOf, isFulfilled } from '@reduxjs/toolkit'; import { buildNodesGraph } from 'features/nodes/util/nodesGraphBuilder/buildNodesGraph'; import { log } from 'app/logging/useLogger'; +import { serializeError } from 'serialize-error'; const sessionLog = log.child({ namespace: 'session' }); export const generateGraphBuilt = createAppAsyncThunk( 'api/generateGraphBuilt', - async (_, { dispatch, getState }) => { - const graph = buildGenerateGraph(getState()); - - dispatch(sessionCreated({ graph })); - - return graph; + async (_, { dispatch, getState, rejectWithValue }) => { + try { + const graph = buildGenerateGraph(getState()); + dispatch(sessionCreated({ graph })); + return graph; + } catch (err: any) { + sessionLog.error( + { error: serializeError(err) }, + 'Problem building graph' + ); + return rejectWithValue(err.message); + } } ); export const nodesGraphBuilt = createAppAsyncThunk( 'api/nodesGraphBuilt', - async (_, { dispatch, getState }) => { - const graph = buildNodesGraph(getState()); - - dispatch(sessionCreated({ graph })); - - return graph; + async (_, { dispatch, getState, rejectWithValue }) => { + try { + const graph = buildNodesGraph(getState()); + dispatch(sessionCreated({ graph })); + return graph; + } catch (err: any) { + sessionLog.error( + { error: serializeError(err) }, + 'Problem building graph' + ); + return rejectWithValue(err.message); + } } ); diff --git a/invokeai/frontend/web/yarn.lock b/invokeai/frontend/web/yarn.lock index f117d4f2de..bece7f0829 100644 --- a/invokeai/frontend/web/yarn.lock +++ b/invokeai/frontend/web/yarn.lock @@ -5779,6 +5779,13 @@ semver@~7.3.0: dependencies: lru-cache "^6.0.0" +serialize-error@^11.0.0: + version "11.0.0" + resolved "https://registry.yarnpkg.com/serialize-error/-/serialize-error-11.0.0.tgz#0129f2b07b19b09bc7a5f2d850ffe9cd2d561582" + integrity sha512-YKrURWDqcT3VGX/s/pCwaWtpfJEEaEw5Y4gAnQDku92b/HjVj4r4UhA5QrMVMFotymK2wIWs5xthny5SMFu7Vw== + dependencies: + type-fest "^2.12.2" + shebang-command@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" @@ -6253,6 +6260,11 @@ type-fest@^0.21.3: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== +type-fest@^2.12.2: + version "2.19.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.19.0.tgz#88068015bb33036a598b952e55e9311a60fd3a9b" + integrity sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA== + typed-array-length@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.4.tgz#89d83785e5c4098bec72e08b319651f0eac9c1bb" From 2e4e9434c199484ea5a21e67f6493a1c41980792 Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Sat, 29 Apr 2023 19:11:20 +1000 Subject: [PATCH 40/68] fix(ui): fix initial image for uploads --- .../components/CurrentImageButtons.tsx | 2 +- .../ImageToImage/InitialImagePreview.tsx | 13 +++++-------- .../parameters/store/generationSelectors.ts | 19 +++++++++---------- .../parameters/store/generationSlice.ts | 10 ++++++++-- 4 files changed, 23 insertions(+), 21 deletions(-) diff --git a/invokeai/frontend/web/src/features/gallery/components/CurrentImageButtons.tsx b/invokeai/frontend/web/src/features/gallery/components/CurrentImageButtons.tsx index 3cfe932b75..481e3feb40 100644 --- a/invokeai/frontend/web/src/features/gallery/components/CurrentImageButtons.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/CurrentImageButtons.tsx @@ -166,7 +166,7 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => { const handleClickUseAsInitialImage = useCallback(() => { if (!image) return; if (isLightboxOpen) dispatch(setIsLightboxOpen(false)); - dispatch(initialImageSelected(image.name)); + dispatch(initialImageSelected({ name: image.name, type: image.type })); // dispatch(setInitialImage(currentImage)); // dispatch(setActiveTab('img2img')); diff --git a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/ImageToImage/InitialImagePreview.tsx b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/ImageToImage/InitialImagePreview.tsx index 2082c2a015..8a91602ada 100644 --- a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/ImageToImage/InitialImagePreview.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/ImageToImage/InitialImagePreview.tsx @@ -5,7 +5,6 @@ import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import SelectImagePlaceholder from 'common/components/SelectImagePlaceholder'; import { useGetUrl } from 'common/util/getUrl'; import useGetImageByNameAndType from 'features/gallery/hooks/useGetImageByName'; -import { selectResultsById } from 'features/gallery/store/resultsSlice'; import { clearInitialImage, initialImageSelected, @@ -16,15 +15,13 @@ import { DragEvent, useCallback, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { ImageType } from 'services/api'; import ImageToImageOverlay from 'common/components/ImageToImageOverlay'; +import { initialImageSelector } from 'features/parameters/store/generationSelectors'; const initialImagePreviewSelector = createSelector( - [(state: RootState) => state], - (state) => { - const { initialImage } = state.generation; - const image = selectResultsById(state, initialImage as string); - + [initialImageSelector], + (initialImage) => { return { - initialImage: image, + initialImage, }; }, { memoizeOptions: { resultEqualityCheck: isEqual } } @@ -71,7 +68,7 @@ const InitialImagePreview = () => { return; } - dispatch(initialImageSelected(image.name)); + dispatch(initialImageSelected({ name, type })); }, [getImageByNameAndType, dispatch] ); diff --git a/invokeai/frontend/web/src/features/parameters/store/generationSelectors.ts b/invokeai/frontend/web/src/features/parameters/store/generationSelectors.ts index ce3c9c4e1e..dbf5eec791 100644 --- a/invokeai/frontend/web/src/features/parameters/store/generationSelectors.ts +++ b/invokeai/frontend/web/src/features/parameters/store/generationSelectors.ts @@ -1,10 +1,6 @@ import { createSelector } from '@reduxjs/toolkit'; import { RootState } from 'app/store/store'; -import { gallerySelector } from 'features/gallery/store/gallerySelectors'; -import { - selectResultsById, - selectResultsEntities, -} from 'features/gallery/store/resultsSlice'; +import { selectResultsById } from 'features/gallery/store/resultsSlice'; import { selectUploadsById } from 'features/gallery/store/uploadsSlice'; import { isEqual } from 'lodash-es'; @@ -25,11 +21,14 @@ export const mayGenerateMultipleImagesSelector = createSelector( export const initialImageSelector = createSelector( [(state: RootState) => state, generationSelector], (state, generation) => { - const { initialImage: initialImageName } = generation; + const { initialImage } = generation; - return ( - selectResultsById(state, initialImageName as string) ?? - selectUploadsById(state, initialImageName as string) - ); + if (initialImage?.type === 'results') { + return selectResultsById(state, initialImage.name); + } + + if (initialImage?.type === 'uploads') { + return selectUploadsById(state, initialImage.name); + } } ); diff --git a/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts b/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts index f303491b2b..5dbe6b2c28 100644 --- a/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts +++ b/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts @@ -5,13 +5,19 @@ import { getPromptAndNegative } from 'common/util/getPromptAndNegative'; import promptToString from 'common/util/promptToString'; import { seedWeightsToString } from 'common/util/seedWeightPairs'; import { clamp } from 'lodash-es'; +import { ImageField, ImageType } from 'services/api'; + +export type InitialImage = { + name: string; + type: ImageType; +}; export interface GenerationState { cfgScale: number; height: number; img2imgStrength: number; infillMethod: string; - initialImage?: InvokeAI._Image | string; // can be an Image or url + initialImage?: InitialImage; // can be an Image or url iterations: number; maskPath: string; perlin: number; @@ -345,7 +351,7 @@ export const generationSlice = createSlice({ setVerticalSymmetrySteps: (state, action: PayloadAction) => { state.verticalSymmetrySteps = action.payload; }, - initialImageSelected: (state, action: PayloadAction) => { + initialImageSelected: (state, action: PayloadAction) => { state.initialImage = action.payload; state.isImageToImageEnabled = true; }, From 2eb7c25bae75c75556c896f225949f5dabc680b1 Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Sun, 30 Apr 2023 00:55:14 +1000 Subject: [PATCH 41/68] feat(ui): clean up and simplify socketio middleware --- .../web/src/services/events/middleware.ts | 110 +---------------- .../services/events/util/setEventListeners.ts | 112 ++++++++++++++++-- 2 files changed, 106 insertions(+), 116 deletions(-) diff --git a/invokeai/frontend/web/src/services/events/middleware.ts b/invokeai/frontend/web/src/services/events/middleware.ts index e57851e19c..dab2e756f3 100644 --- a/invokeai/frontend/web/src/services/events/middleware.ts +++ b/invokeai/frontend/web/src/services/events/middleware.ts @@ -7,15 +7,9 @@ import { } from 'services/events/types'; import { invocationComplete, - socketConnected, - socketDisconnected, socketSubscribed, socketUnsubscribed, } from './actions'; -import { - receivedResultImagesPage, - receivedUploadImagesPage, -} from 'services/thunks/gallery'; import { AppDispatch, RootState } from 'app/store/store'; import { getTimestamp } from 'common/util/getTimestamp'; import { @@ -23,14 +17,12 @@ import { isFulfilledSessionCreatedAction, } from 'services/thunks/session'; import { OpenAPI } from 'services/api'; -import { receivedModels } from 'services/thunks/model'; -import { receivedOpenAPISchema } from 'services/thunks/schema'; import { isImageOutput } from 'services/types/guards'; import { imageReceived, thumbnailReceived } from 'services/thunks/image'; import { setEventListeners } from 'services/events/util/setEventListeners'; import { log } from 'app/logging/useLogger'; -const moduleLog = log.child({ namespace: 'socketio' }); +const socketioLog = log.child({ namespace: 'socketio' }); export const socketMiddleware = () => { let areListenersSet = false; @@ -65,106 +57,27 @@ export const socketMiddleware = () => { (store: MiddlewareAPI) => (next) => (action) => { const { dispatch, getState } = store; - // Nothing dispatches `socketReset` actions yet - // if (socketReset.match(action)) { - // const { sessionId } = getState().system; - - // if (sessionId) { - // socket.emit('unsubscribe', { session: sessionId }); - // dispatch( - // socketUnsubscribed({ sessionId, timestamp: getTimestamp() }) - // ); - // } - - // if (socket.connected) { - // socket.disconnect(); - // dispatch(socketDisconnected({ timestamp: getTimestamp() })); - // } - - // socket.removeAllListeners(); - // areListenersSet = false; - // } - // Set listeners for `connect` and `disconnect` events once // Must happen in middleware to get access to `dispatch` if (!areListenersSet) { - socket.on('connect', () => { - moduleLog.debug('Connected'); - - dispatch(socketConnected({ timestamp: getTimestamp() })); - - const { results, uploads, models, nodes, config, system } = - getState(); - - const { disabledTabs } = config; - - // These thunks need to be dispatch in middleware; cannot handle in a reducer - if (!results.ids.length) { - dispatch(receivedResultImagesPage()); - } - - if (!uploads.ids.length) { - dispatch(receivedUploadImagesPage()); - } - - if (!models.ids.length) { - dispatch(receivedModels()); - } - - if (!nodes.schema && !disabledTabs.includes('nodes')) { - dispatch(receivedOpenAPISchema()); - } - - if (system.sessionId) { - const sessionLog = moduleLog.child({ sessionId: system.sessionId }); - - sessionLog.debug( - `Subscribed to existing session (${system.sessionId})` - ); - - socket.emit('subscribe', { session: system.sessionId }); - dispatch( - socketSubscribed({ - sessionId: system.sessionId, - timestamp: getTimestamp(), - }) - ); - setEventListeners({ socket, store, sessionLog }); - } - }); - - socket.on('disconnect', () => { - moduleLog.debug('Disconnected'); - dispatch(socketDisconnected({ timestamp: getTimestamp() })); - }); + setEventListeners({ store, socket, log: socketioLog }); areListenersSet = true; - // must manually connect socket.connect(); } - // Everything else only happens once we have created a session if (isFulfilledSessionCreatedAction(action)) { const sessionId = action.payload.id; - const sessionLog = moduleLog.child({ sessionId }); + const sessionLog = socketioLog.child({ sessionId }); const oldSessionId = getState().system.sessionId; - // const subscribedNodeIds = getState().system.subscribedNodeIds; - // const shouldHandleEvent = (id: string): boolean => { - // if (subscribedNodeIds.length === 1 && subscribedNodeIds[0] === '*') { - // return true; - // } - - // return subscribedNodeIds.includes(id); - // }; - if (oldSessionId) { sessionLog.debug( { oldSessionId }, `Unsubscribed from old session (${oldSessionId})` ); - // Unsubscribe when invocations complete + socket.emit('unsubscribe', { session: oldSessionId, }); @@ -175,28 +88,18 @@ export const socketMiddleware = () => { timestamp: getTimestamp(), }) ); - const listenersToRemove: (keyof ServerToClientEvents)[] = [ - 'invocation_started', - 'generator_progress', - 'invocation_error', - 'invocation_complete', - ]; - - // Remove listeners for these events; we need to set them up fresh whenever we subscribe - listenersToRemove.forEach((event: keyof ServerToClientEvents) => { - socket.removeAllListeners(event); - }); } sessionLog.debug(`Subscribe to new session (${sessionId})`); + socket.emit('subscribe', { session: sessionId }); + dispatch( socketSubscribed({ sessionId: sessionId, timestamp: getTimestamp(), }) ); - setEventListeners({ socket, store, sessionLog }); // Finally we actually invoke the session, starting processing dispatch(sessionInvoked({ sessionId })); @@ -222,7 +125,6 @@ export const socketMiddleware = () => { } } - // Always pass the action on so other middleware and reducers can handle it next(action); }; diff --git a/invokeai/frontend/web/src/services/events/util/setEventListeners.ts b/invokeai/frontend/web/src/services/events/util/setEventListeners.ts index 90a285d238..8454f81508 100644 --- a/invokeai/frontend/web/src/services/events/util/setEventListeners.ts +++ b/invokeai/frontend/web/src/services/events/util/setEventListeners.ts @@ -9,38 +9,124 @@ import { invocationComplete, invocationError, invocationStarted, + socketConnected, + socketDisconnected, + socketSubscribed, } from '../actions'; import { ClientToServerEvents, ServerToClientEvents } from '../types'; import { Logger } from 'roarr'; import { JsonObject } from 'roarr/dist/types'; +import { + receivedResultImagesPage, + receivedUploadImagesPage, +} from 'services/thunks/gallery'; +import { receivedModels } from 'services/thunks/model'; +import { receivedOpenAPISchema } from 'services/thunks/schema'; type SetEventListenersArg = { socket: Socket; store: MiddlewareAPI; - sessionLog: Logger; + log: Logger; }; export const setEventListeners = (arg: SetEventListenersArg) => { - const { socket, store, sessionLog } = arg; + const { socket, store, log } = arg; const { dispatch, getState } = store; - // Set up listeners for the present subscription + + /** + * Connect + */ + socket.on('connect', () => { + log.debug('Connected'); + + dispatch(socketConnected({ timestamp: getTimestamp() })); + + const { results, uploads, models, nodes, config, system } = getState(); + + const { disabledTabs } = config; + + // These thunks need to be dispatch in middleware; cannot handle in a reducer + if (!results.ids.length) { + dispatch(receivedResultImagesPage()); + } + + if (!uploads.ids.length) { + dispatch(receivedUploadImagesPage()); + } + + if (!models.ids.length) { + dispatch(receivedModels()); + } + + if (!nodes.schema && !disabledTabs.includes('nodes')) { + dispatch(receivedOpenAPISchema()); + } + + if (system.sessionId) { + log.debug( + { sessionId: system.sessionId }, + `Subscribed to existing session (${system.sessionId})` + ); + + socket.emit('subscribe', { session: system.sessionId }); + dispatch( + socketSubscribed({ + sessionId: system.sessionId, + timestamp: getTimestamp(), + }) + ); + } + }); + + /** + * Disconnect + */ + socket.on('disconnect', () => { + log.debug('Disconnected'); + dispatch(socketDisconnected({ timestamp: getTimestamp() })); + }); + + /** + * Invocation started + */ socket.on('invocation_started', (data) => { - sessionLog.child({ data }).info(`Invocation started (${data.node.type})`); + log.info( + { data, sessionId: data.graph_execution_state_id }, + `Invocation started (${data.node.type})` + ); dispatch(invocationStarted({ data, timestamp: getTimestamp() })); }); + /** + * Generator progress + */ socket.on('generator_progress', (data) => { - sessionLog.child({ data }).trace(`Generator progress (${data.node.type})`); + log.trace( + { data, sessionId: data.graph_execution_state_id }, + `Generator progress (${data.node.type})` + ); dispatch(generatorProgress({ data, timestamp: getTimestamp() })); }); + /** + * Invocation error + */ socket.on('invocation_error', (data) => { - sessionLog.child({ data }).error(`Invocation error (${data.node.type})`); + log.error( + { data, sessionId: data.graph_execution_state_id }, + `Invocation error (${data.node.type})` + ); dispatch(invocationError({ data, timestamp: getTimestamp() })); }); + /** + * Invocation complete + */ socket.on('invocation_complete', (data) => { - sessionLog.child({ data }).info(`Invocation complete (${data.node.type})`); + log.info( + { data, sessionId: data.graph_execution_state_id }, + `Invocation complete (${data.node.type})` + ); const sessionId = data.graph_execution_state_id; const { cancelType, isCancelScheduled } = getState().system; @@ -60,12 +146,14 @@ export const setEventListeners = (arg: SetEventListenersArg) => { ); }); + /** + * Graph complete + */ socket.on('graph_execution_state_complete', (data) => { - sessionLog - .child({ data }) - .info( - `Graph execution state complete (${data.graph_execution_state_id})` - ); + log.info( + { data, sessionId: data.graph_execution_state_id }, + `Graph execution state complete (${data.graph_execution_state_id})` + ); dispatch(graphExecutionStateComplete({ data, timestamp: getTimestamp() })); }); }; From 258895bcc9e9a932135eee763cecb09c3688a35e Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Sun, 30 Apr 2023 00:57:00 +1000 Subject: [PATCH 42/68] feat(ui): being dismantling old sio stuff, fix recall seed/prompt/init - still need to fix up metadataviewer's recall features --- .../web/src/app/components/InvokeAIUI.tsx | 5 +- invokeai/frontend/web/src/app/constants.ts | 13 +- .../frontend/web/src/app/socketio/actions.ts | 110 +- .../frontend/web/src/app/socketio/emitters.ts | 382 +++---- .../web/src/app/socketio/listeners.ts | 938 +++++++++--------- .../web/src/app/socketio/middleware.ts | 402 ++++---- invokeai/frontend/web/src/app/store/store.ts | 15 +- .../frontend/web/src/app/types/invokeai.ts | 56 +- .../IAICanvasStagingAreaToolbar.tsx | 2 +- .../components/CurrentImageButtons.tsx | 120 +-- .../gallery/components/HoverableImage.tsx | 169 ++-- .../components/ImageGalleryContent.tsx | 2 +- .../ProcessButtons/InvokeButton.tsx | 19 +- .../components/PromptInput/PromptInput.tsx | 8 +- .../parameters/hooks/useParameters.ts | 130 +++ .../components/ClearTempFolderButtonModal.tsx | 2 +- .../ModelManager/AddCheckpointModel.tsx | 2 +- .../ModelManager/AddDiffusersModel.tsx | 2 +- .../ModelManager/CheckpointModelEdit.tsx | 2 +- .../ModelManager/DiffusersModelEdit.tsx | 2 +- .../components/ModelManager/MergeModels.tsx | 2 +- .../components/ModelManager/ModelConvert.tsx | 2 +- .../components/ModelManager/ModelListItem.tsx | 2 +- .../components/ModelManager/SearchModels.tsx | 2 +- .../SettingsModal/SettingsModal.tsx | 58 +- .../system/components/StatusIndicator.tsx | 48 +- .../src/features/system/store/systemSlice.ts | 108 +- .../frontend/web/src/services/types/guards.ts | 17 + 28 files changed, 1231 insertions(+), 1389 deletions(-) create mode 100644 invokeai/frontend/web/src/features/parameters/hooks/useParameters.ts diff --git a/invokeai/frontend/web/src/app/components/InvokeAIUI.tsx b/invokeai/frontend/web/src/app/components/InvokeAIUI.tsx index a66f2ef2a3..97a8be6fc1 100644 --- a/invokeai/frontend/web/src/app/components/InvokeAIUI.tsx +++ b/invokeai/frontend/web/src/app/components/InvokeAIUI.tsx @@ -1,7 +1,7 @@ import React, { lazy, memo, PropsWithChildren, useEffect } from 'react'; import { Provider } from 'react-redux'; import { PersistGate } from 'redux-persist/integration/react'; -import { buildMiddleware, store } from 'app/store/store'; +import { store } from 'app/store/store'; import { persistor } from '../store/persistor'; import { OpenAPI } from 'services/api'; import '@fontsource/inter/100.css'; @@ -19,6 +19,7 @@ import { addMiddleware, resetMiddlewares } from 'redux-dynamic-middlewares'; import { PartialAppConfig } from 'app/types/invokeai'; import '../../i18n'; +import { socketMiddleware } from 'services/events/middleware'; const App = lazy(() => import('./App')); const ThemeLocaleProvider = lazy(() => import('./ThemeLocaleProvider')); @@ -50,7 +51,7 @@ const InvokeAIUI = ({ apiUrl, token, config, children }: Props) => { // the `apiUrl`/`token` dynamically. // rebuild socket middleware with token and apiUrl - addMiddleware(buildMiddleware()); + addMiddleware(socketMiddleware()); }, [apiUrl, token]); return ( diff --git a/invokeai/frontend/web/src/app/constants.ts b/invokeai/frontend/web/src/app/constants.ts index 083f57f26f..534ca9e29a 100644 --- a/invokeai/frontend/web/src/app/constants.ts +++ b/invokeai/frontend/web/src/app/constants.ts @@ -1,7 +1,5 @@ // TODO: use Enums? -import { InProgressImageType } from 'features/system/store/systemSlice'; - export const DIFFUSERS_SCHEDULERS: Array = [ 'ddim', 'plms', @@ -33,17 +31,8 @@ export const UPSCALING_LEVELS: Array<{ key: string; value: number }> = [ export const NUMPY_RAND_MIN = 0; -export const NUMPY_RAND_MAX = 4294967295; +export const NUMPY_RAND_MAX = 2147483647; export const FACETOOL_TYPES = ['gfpgan', 'codeformer'] as const; -export const IN_PROGRESS_IMAGE_TYPES: Array<{ - key: string; - value: InProgressImageType; -}> = [ - { key: 'None', value: 'none' }, - { key: 'Fast', value: 'latents' }, - { key: 'Accurate', value: 'full-res' }, -]; - export const NODE_MIN_WIDTH = 250; diff --git a/invokeai/frontend/web/src/app/socketio/actions.ts b/invokeai/frontend/web/src/app/socketio/actions.ts index 923c1f59b0..bb2a0dd0cb 100644 --- a/invokeai/frontend/web/src/app/socketio/actions.ts +++ b/invokeai/frontend/web/src/app/socketio/actions.ts @@ -1,65 +1,67 @@ -import { createAction } from '@reduxjs/toolkit'; -import * as InvokeAI from 'app/types/invokeai'; -import { GalleryCategory } from 'features/gallery/store/gallerySlice'; -import { InvokeTabName } from 'features/ui/store/tabMap'; +// import { createAction } from '@reduxjs/toolkit'; +// import * as InvokeAI from 'app/types/invokeai'; +// import { GalleryCategory } from 'features/gallery/store/gallerySlice'; +// import { InvokeTabName } from 'features/ui/store/tabMap'; -/** - * We can't use redux-toolkit's createSlice() to make these actions, - * because they have no associated reducer. They only exist to dispatch - * requests to the server via socketio. These actions will be handled - * by the middleware. - */ +// /** +// * We can't use redux-toolkit's createSlice() to make these actions, +// * because they have no associated reducer. They only exist to dispatch +// * requests to the server via socketio. These actions will be handled +// * by the middleware. +// */ -export const generateImage = createAction( - 'socketio/generateImage' -); -export const runESRGAN = createAction('socketio/runESRGAN'); -export const runFacetool = createAction( - 'socketio/runFacetool' -); -export const deleteImage = createAction( - 'socketio/deleteImage' -); -export const requestImages = createAction( - 'socketio/requestImages' -); -export const requestNewImages = createAction( - 'socketio/requestNewImages' -); -export const cancelProcessing = createAction( - 'socketio/cancelProcessing' -); +// export const generateImage = createAction( +// 'socketio/generateImage' +// ); +// export const runESRGAN = createAction('socketio/runESRGAN'); +// export const runFacetool = createAction( +// 'socketio/runFacetool' +// ); +// export const deleteImage = createAction( +// 'socketio/deleteImage' +// ); +// export const requestImages = createAction( +// 'socketio/requestImages' +// ); +// export const requestNewImages = createAction( +// 'socketio/requestNewImages' +// ); +// export const cancelProcessing = createAction( +// 'socketio/cancelProcessing' +// ); -export const requestSystemConfig = createAction( - 'socketio/requestSystemConfig' -); +// export const requestSystemConfig = createAction( +// 'socketio/requestSystemConfig' +// ); -export const searchForModels = createAction('socketio/searchForModels'); +// export const searchForModels = createAction('socketio/searchForModels'); -export const addNewModel = createAction< - InvokeAI.InvokeModelConfigProps | InvokeAI.InvokeDiffusersModelConfigProps ->('socketio/addNewModel'); +// export const addNewModel = createAction< +// InvokeAI.InvokeModelConfigProps | InvokeAI.InvokeDiffusersModelConfigProps +// >('socketio/addNewModel'); -export const deleteModel = createAction('socketio/deleteModel'); +// export const deleteModel = createAction('socketio/deleteModel'); -export const convertToDiffusers = - createAction( - 'socketio/convertToDiffusers' - ); +// export const convertToDiffusers = +// createAction( +// 'socketio/convertToDiffusers' +// ); -export const mergeDiffusersModels = - createAction( - 'socketio/mergeDiffusersModels' - ); +// export const mergeDiffusersModels = +// createAction( +// 'socketio/mergeDiffusersModels' +// ); -export const requestModelChange = createAction( - 'socketio/requestModelChange' -); +// export const requestModelChange = createAction( +// 'socketio/requestModelChange' +// ); -export const saveStagingAreaImageToGallery = createAction( - 'socketio/saveStagingAreaImageToGallery' -); +// export const saveStagingAreaImageToGallery = createAction( +// 'socketio/saveStagingAreaImageToGallery' +// ); -export const emptyTempFolder = createAction( - 'socketio/requestEmptyTempFolder' -); +// export const emptyTempFolder = createAction( +// 'socketio/requestEmptyTempFolder' +// ); + +export default {}; diff --git a/invokeai/frontend/web/src/app/socketio/emitters.ts b/invokeai/frontend/web/src/app/socketio/emitters.ts index 610f05b826..ad7979503f 100644 --- a/invokeai/frontend/web/src/app/socketio/emitters.ts +++ b/invokeai/frontend/web/src/app/socketio/emitters.ts @@ -1,207 +1,209 @@ -import { AnyAction, Dispatch, MiddlewareAPI } from '@reduxjs/toolkit'; -import * as InvokeAI from 'app/types/invokeai'; -import type { RootState } from 'app/store/store'; -import { - frontendToBackendParameters, - FrontendToBackendParametersConfig, -} from 'common/util/parameterTranslation'; -import dateFormat from 'dateformat'; -import { - GalleryCategory, - GalleryState, - removeImage, -} from 'features/gallery/store/gallerySlice'; -import { - generationRequested, - modelChangeRequested, - modelConvertRequested, - modelMergingRequested, - setIsProcessing, -} from 'features/system/store/systemSlice'; -import { InvokeTabName } from 'features/ui/store/tabMap'; -import { Socket } from 'socket.io-client'; +// import { AnyAction, Dispatch, MiddlewareAPI } from '@reduxjs/toolkit'; +// import * as InvokeAI from 'app/types/invokeai'; +// import type { RootState } from 'app/store/store'; +// import { +// frontendToBackendParameters, +// FrontendToBackendParametersConfig, +// } from 'common/util/parameterTranslation'; +// import dateFormat from 'dateformat'; +// import { +// GalleryCategory, +// GalleryState, +// removeImage, +// } from 'features/gallery/store/gallerySlice'; +// import { +// generationRequested, +// modelChangeRequested, +// modelConvertRequested, +// modelMergingRequested, +// setIsProcessing, +// } from 'features/system/store/systemSlice'; +// import { InvokeTabName } from 'features/ui/store/tabMap'; +// import { Socket } from 'socket.io-client'; -/** - * Returns an object containing all functions which use `socketio.emit()`. - * i.e. those which make server requests. - */ -const makeSocketIOEmitters = ( - store: MiddlewareAPI, RootState>, - socketio: Socket -) => { - // We need to dispatch actions to redux and get pieces of state from the store. - const { dispatch, getState } = store; +// /** +// * Returns an object containing all functions which use `socketio.emit()`. +// * i.e. those which make server requests. +// */ +// const makeSocketIOEmitters = ( +// store: MiddlewareAPI, RootState>, +// socketio: Socket +// ) => { +// // We need to dispatch actions to redux and get pieces of state from the store. +// const { dispatch, getState } = store; - return { - emitGenerateImage: (generationMode: InvokeTabName) => { - dispatch(setIsProcessing(true)); +// return { +// emitGenerateImage: (generationMode: InvokeTabName) => { +// dispatch(setIsProcessing(true)); - const state: RootState = getState(); +// const state: RootState = getState(); - const { - generation: generationState, - postprocessing: postprocessingState, - system: systemState, - canvas: canvasState, - } = state; +// const { +// generation: generationState, +// postprocessing: postprocessingState, +// system: systemState, +// canvas: canvasState, +// } = state; - const frontendToBackendParametersConfig: FrontendToBackendParametersConfig = - { - generationMode, - generationState, - postprocessingState, - canvasState, - systemState, - }; +// const frontendToBackendParametersConfig: FrontendToBackendParametersConfig = +// { +// generationMode, +// generationState, +// postprocessingState, +// canvasState, +// systemState, +// }; - dispatch(generationRequested()); +// dispatch(generationRequested()); - const { generationParameters, esrganParameters, facetoolParameters } = - frontendToBackendParameters(frontendToBackendParametersConfig); +// const { generationParameters, esrganParameters, facetoolParameters } = +// frontendToBackendParameters(frontendToBackendParametersConfig); - socketio.emit( - 'generateImage', - generationParameters, - esrganParameters, - facetoolParameters - ); +// socketio.emit( +// 'generateImage', +// generationParameters, +// esrganParameters, +// facetoolParameters +// ); - // we need to truncate the init_mask base64 else it takes up the whole log - // TODO: handle maintaining masks for reproducibility in future - if (generationParameters.init_mask) { - generationParameters.init_mask = generationParameters.init_mask - .substr(0, 64) - .concat('...'); - } - if (generationParameters.init_img) { - generationParameters.init_img = generationParameters.init_img - .substr(0, 64) - .concat('...'); - } +// // we need to truncate the init_mask base64 else it takes up the whole log +// // TODO: handle maintaining masks for reproducibility in future +// if (generationParameters.init_mask) { +// generationParameters.init_mask = generationParameters.init_mask +// .substr(0, 64) +// .concat('...'); +// } +// if (generationParameters.init_img) { +// generationParameters.init_img = generationParameters.init_img +// .substr(0, 64) +// .concat('...'); +// } - dispatch( - addLogEntry({ - timestamp: dateFormat(new Date(), 'isoDateTime'), - message: `Image generation requested: ${JSON.stringify({ - ...generationParameters, - ...esrganParameters, - ...facetoolParameters, - })}`, - }) - ); - }, - emitRunESRGAN: (imageToProcess: InvokeAI._Image) => { - dispatch(setIsProcessing(true)); +// dispatch( +// addLogEntry({ +// timestamp: dateFormat(new Date(), 'isoDateTime'), +// message: `Image generation requested: ${JSON.stringify({ +// ...generationParameters, +// ...esrganParameters, +// ...facetoolParameters, +// })}`, +// }) +// ); +// }, +// emitRunESRGAN: (imageToProcess: InvokeAI._Image) => { +// dispatch(setIsProcessing(true)); - const { - postprocessing: { - upscalingLevel, - upscalingDenoising, - upscalingStrength, - }, - } = getState(); +// const { +// postprocessing: { +// upscalingLevel, +// upscalingDenoising, +// upscalingStrength, +// }, +// } = getState(); - const esrganParameters = { - upscale: [upscalingLevel, upscalingDenoising, upscalingStrength], - }; - socketio.emit('runPostprocessing', imageToProcess, { - type: 'esrgan', - ...esrganParameters, - }); - dispatch( - addLogEntry({ - timestamp: dateFormat(new Date(), 'isoDateTime'), - message: `ESRGAN upscale requested: ${JSON.stringify({ - file: imageToProcess.url, - ...esrganParameters, - })}`, - }) - ); - }, - emitRunFacetool: (imageToProcess: InvokeAI._Image) => { - dispatch(setIsProcessing(true)); +// const esrganParameters = { +// upscale: [upscalingLevel, upscalingDenoising, upscalingStrength], +// }; +// socketio.emit('runPostprocessing', imageToProcess, { +// type: 'esrgan', +// ...esrganParameters, +// }); +// dispatch( +// addLogEntry({ +// timestamp: dateFormat(new Date(), 'isoDateTime'), +// message: `ESRGAN upscale requested: ${JSON.stringify({ +// file: imageToProcess.url, +// ...esrganParameters, +// })}`, +// }) +// ); +// }, +// emitRunFacetool: (imageToProcess: InvokeAI._Image) => { +// dispatch(setIsProcessing(true)); - const { - postprocessing: { facetoolType, facetoolStrength, codeformerFidelity }, - } = getState(); +// const { +// postprocessing: { facetoolType, facetoolStrength, codeformerFidelity }, +// } = getState(); - const facetoolParameters: Record = { - facetool_strength: facetoolStrength, - }; +// const facetoolParameters: Record = { +// facetool_strength: facetoolStrength, +// }; - if (facetoolType === 'codeformer') { - facetoolParameters.codeformer_fidelity = codeformerFidelity; - } +// if (facetoolType === 'codeformer') { +// facetoolParameters.codeformer_fidelity = codeformerFidelity; +// } - socketio.emit('runPostprocessing', imageToProcess, { - type: facetoolType, - ...facetoolParameters, - }); - dispatch( - addLogEntry({ - timestamp: dateFormat(new Date(), 'isoDateTime'), - message: `Face restoration (${facetoolType}) requested: ${JSON.stringify( - { - file: imageToProcess.url, - ...facetoolParameters, - } - )}`, - }) - ); - }, - emitDeleteImage: (imageToDelete: InvokeAI._Image) => { - const { url, uuid, category, thumbnail } = imageToDelete; - dispatch(removeImage(imageToDelete)); - socketio.emit('deleteImage', url, thumbnail, uuid, category); - }, - emitRequestImages: (category: GalleryCategory) => { - const gallery: GalleryState = getState().gallery; - const { earliest_mtime } = gallery.categories[category]; - socketio.emit('requestImages', category, earliest_mtime); - }, - emitRequestNewImages: (category: GalleryCategory) => { - const gallery: GalleryState = getState().gallery; - const { latest_mtime } = gallery.categories[category]; - socketio.emit('requestLatestImages', category, latest_mtime); - }, - emitCancelProcessing: () => { - socketio.emit('cancel'); - }, - emitRequestSystemConfig: () => { - socketio.emit('requestSystemConfig'); - }, - emitSearchForModels: (modelFolder: string) => { - socketio.emit('searchForModels', modelFolder); - }, - emitAddNewModel: (modelConfig: InvokeAI.InvokeModelConfigProps) => { - socketio.emit('addNewModel', modelConfig); - }, - emitDeleteModel: (modelName: string) => { - socketio.emit('deleteModel', modelName); - }, - emitConvertToDiffusers: ( - modelToConvert: InvokeAI.InvokeModelConversionProps - ) => { - dispatch(modelConvertRequested()); - socketio.emit('convertToDiffusers', modelToConvert); - }, - emitMergeDiffusersModels: ( - modelMergeInfo: InvokeAI.InvokeModelMergingProps - ) => { - dispatch(modelMergingRequested()); - socketio.emit('mergeDiffusersModels', modelMergeInfo); - }, - emitRequestModelChange: (modelName: string) => { - dispatch(modelChangeRequested()); - socketio.emit('requestModelChange', modelName); - }, - emitSaveStagingAreaImageToGallery: (url: string) => { - socketio.emit('requestSaveStagingAreaImageToGallery', url); - }, - emitRequestEmptyTempFolder: () => { - socketio.emit('requestEmptyTempFolder'); - }, - }; -}; +// socketio.emit('runPostprocessing', imageToProcess, { +// type: facetoolType, +// ...facetoolParameters, +// }); +// dispatch( +// addLogEntry({ +// timestamp: dateFormat(new Date(), 'isoDateTime'), +// message: `Face restoration (${facetoolType}) requested: ${JSON.stringify( +// { +// file: imageToProcess.url, +// ...facetoolParameters, +// } +// )}`, +// }) +// ); +// }, +// emitDeleteImage: (imageToDelete: InvokeAI._Image) => { +// const { url, uuid, category, thumbnail } = imageToDelete; +// dispatch(removeImage(imageToDelete)); +// socketio.emit('deleteImage', url, thumbnail, uuid, category); +// }, +// emitRequestImages: (category: GalleryCategory) => { +// const gallery: GalleryState = getState().gallery; +// const { earliest_mtime } = gallery.categories[category]; +// socketio.emit('requestImages', category, earliest_mtime); +// }, +// emitRequestNewImages: (category: GalleryCategory) => { +// const gallery: GalleryState = getState().gallery; +// const { latest_mtime } = gallery.categories[category]; +// socketio.emit('requestLatestImages', category, latest_mtime); +// }, +// emitCancelProcessing: () => { +// socketio.emit('cancel'); +// }, +// emitRequestSystemConfig: () => { +// socketio.emit('requestSystemConfig'); +// }, +// emitSearchForModels: (modelFolder: string) => { +// socketio.emit('searchForModels', modelFolder); +// }, +// emitAddNewModel: (modelConfig: InvokeAI.InvokeModelConfigProps) => { +// socketio.emit('addNewModel', modelConfig); +// }, +// emitDeleteModel: (modelName: string) => { +// socketio.emit('deleteModel', modelName); +// }, +// emitConvertToDiffusers: ( +// modelToConvert: InvokeAI.InvokeModelConversionProps +// ) => { +// dispatch(modelConvertRequested()); +// socketio.emit('convertToDiffusers', modelToConvert); +// }, +// emitMergeDiffusersModels: ( +// modelMergeInfo: InvokeAI.InvokeModelMergingProps +// ) => { +// dispatch(modelMergingRequested()); +// socketio.emit('mergeDiffusersModels', modelMergeInfo); +// }, +// emitRequestModelChange: (modelName: string) => { +// dispatch(modelChangeRequested()); +// socketio.emit('requestModelChange', modelName); +// }, +// emitSaveStagingAreaImageToGallery: (url: string) => { +// socketio.emit('requestSaveStagingAreaImageToGallery', url); +// }, +// emitRequestEmptyTempFolder: () => { +// socketio.emit('requestEmptyTempFolder'); +// }, +// }; +// }; -export default makeSocketIOEmitters; +// export default makeSocketIOEmitters; + +export default {}; diff --git a/invokeai/frontend/web/src/app/socketio/listeners.ts b/invokeai/frontend/web/src/app/socketio/listeners.ts index de2f86fd4c..cb6db260fc 100644 --- a/invokeai/frontend/web/src/app/socketio/listeners.ts +++ b/invokeai/frontend/web/src/app/socketio/listeners.ts @@ -1,500 +1,502 @@ -import { AnyAction, Dispatch, MiddlewareAPI } from '@reduxjs/toolkit'; -import dateFormat from 'dateformat'; -import i18n from 'i18n'; -import { v4 as uuidv4 } from 'uuid'; +// import { AnyAction, Dispatch, MiddlewareAPI } from '@reduxjs/toolkit'; +// import dateFormat from 'dateformat'; +// import i18n from 'i18n'; +// import { v4 as uuidv4 } from 'uuid'; -import * as InvokeAI from 'app/types/invokeai'; +// import * as InvokeAI from 'app/types/invokeai'; -import { - addToast, - errorOccurred, - processingCanceled, - setCurrentStatus, - setFoundModels, - setIsCancelable, - setIsConnected, - setIsProcessing, - setModelList, - setSearchFolder, - setSystemConfig, - setSystemStatus, -} from 'features/system/store/systemSlice'; +// import { +// addToast, +// errorOccurred, +// processingCanceled, +// setCurrentStatus, +// setFoundModels, +// setIsCancelable, +// setIsConnected, +// setIsProcessing, +// setModelList, +// setSearchFolder, +// setSystemConfig, +// setSystemStatus, +// } from 'features/system/store/systemSlice'; -import { - addGalleryImages, - addImage, - clearIntermediateImage, - GalleryState, - removeImage, - setIntermediateImage, -} from 'features/gallery/store/gallerySlice'; +// import { +// addGalleryImages, +// addImage, +// clearIntermediateImage, +// GalleryState, +// removeImage, +// setIntermediateImage, +// } from 'features/gallery/store/gallerySlice'; -import type { RootState } from 'app/store/store'; -import { addImageToStagingArea } from 'features/canvas/store/canvasSlice'; -import { - clearInitialImage, - initialImageSelected, - setInfillMethod, - // setInitialImage, - setMaskPath, -} from 'features/parameters/store/generationSlice'; -import { tabMap } from 'features/ui/store/tabMap'; -import { - requestImages, - requestNewImages, - requestSystemConfig, -} from './actions'; +// import type { RootState } from 'app/store/store'; +// import { addImageToStagingArea } from 'features/canvas/store/canvasSlice'; +// import { +// clearInitialImage, +// initialImageSelected, +// setInfillMethod, +// // setInitialImage, +// setMaskPath, +// } from 'features/parameters/store/generationSlice'; +// import { tabMap } from 'features/ui/store/tabMap'; +// import { +// requestImages, +// requestNewImages, +// requestSystemConfig, +// } from './actions'; -/** - * Returns an object containing listener callbacks for socketio events. - * TODO: This file is large, but simple. Should it be split up further? - */ -const makeSocketIOListeners = ( - store: MiddlewareAPI, RootState> -) => { - const { dispatch, getState } = store; +// /** +// * Returns an object containing listener callbacks for socketio events. +// * TODO: This file is large, but simple. Should it be split up further? +// */ +// const makeSocketIOListeners = ( +// store: MiddlewareAPI, RootState> +// ) => { +// const { dispatch, getState } = store; - return { - /** - * Callback to run when we receive a 'connect' event. - */ - onConnect: () => { - try { - dispatch(setIsConnected(true)); - dispatch(setCurrentStatus(i18n.t('common.statusConnected'))); - dispatch(requestSystemConfig()); - const gallery: GalleryState = getState().gallery; +// return { +// /** +// * Callback to run when we receive a 'connect' event. +// */ +// onConnect: () => { +// try { +// dispatch(setIsConnected(true)); +// dispatch(setCurrentStatus(i18n.t('common.statusConnected'))); +// dispatch(requestSystemConfig()); +// const gallery: GalleryState = getState().gallery; - if (gallery.categories.result.latest_mtime) { - dispatch(requestNewImages('result')); - } else { - dispatch(requestImages('result')); - } +// if (gallery.categories.result.latest_mtime) { +// dispatch(requestNewImages('result')); +// } else { +// dispatch(requestImages('result')); +// } - if (gallery.categories.user.latest_mtime) { - dispatch(requestNewImages('user')); - } else { - dispatch(requestImages('user')); - } - } catch (e) { - console.error(e); - } - }, - /** - * Callback to run when we receive a 'disconnect' event. - */ - onDisconnect: () => { - try { - dispatch(setIsConnected(false)); - dispatch(setCurrentStatus(i18n.t('common.statusDisconnected'))); +// if (gallery.categories.user.latest_mtime) { +// dispatch(requestNewImages('user')); +// } else { +// dispatch(requestImages('user')); +// } +// } catch (e) { +// console.error(e); +// } +// }, +// /** +// * Callback to run when we receive a 'disconnect' event. +// */ +// onDisconnect: () => { +// try { +// dispatch(setIsConnected(false)); +// dispatch(setCurrentStatus(i18n.t('common.statusDisconnected'))); - dispatch( - addLogEntry({ - timestamp: dateFormat(new Date(), 'isoDateTime'), - message: `Disconnected from server`, - level: 'warning', - }) - ); - } catch (e) { - console.error(e); - } - }, - /** - * Callback to run when we receive a 'generationResult' event. - */ - onGenerationResult: (data: InvokeAI.ImageResultResponse) => { - try { - const state = getState(); - const { activeTab } = state.ui; - const { shouldLoopback } = state.postprocessing; - const { boundingBox: _, generationMode, ...rest } = data; +// dispatch( +// addLogEntry({ +// timestamp: dateFormat(new Date(), 'isoDateTime'), +// message: `Disconnected from server`, +// level: 'warning', +// }) +// ); +// } catch (e) { +// console.error(e); +// } +// }, +// /** +// * Callback to run when we receive a 'generationResult' event. +// */ +// onGenerationResult: (data: InvokeAI.ImageResultResponse) => { +// try { +// const state = getState(); +// const { activeTab } = state.ui; +// const { shouldLoopback } = state.postprocessing; +// const { boundingBox: _, generationMode, ...rest } = data; - const newImage = { - uuid: uuidv4(), - ...rest, - }; +// const newImage = { +// uuid: uuidv4(), +// ...rest, +// }; - if (['txt2img', 'img2img'].includes(generationMode)) { - dispatch( - addImage({ - category: 'result', - image: { ...newImage, category: 'result' }, - }) - ); - } +// if (['txt2img', 'img2img'].includes(generationMode)) { +// dispatch( +// addImage({ +// category: 'result', +// image: { ...newImage, category: 'result' }, +// }) +// ); +// } - if (generationMode === 'unifiedCanvas' && data.boundingBox) { - const { boundingBox } = data; - dispatch( - addImageToStagingArea({ - image: { ...newImage, category: 'temp' }, - boundingBox, - }) - ); +// if (generationMode === 'unifiedCanvas' && data.boundingBox) { +// const { boundingBox } = data; +// dispatch( +// addImageToStagingArea({ +// image: { ...newImage, category: 'temp' }, +// boundingBox, +// }) +// ); - if (state.canvas.shouldAutoSave) { - dispatch( - addImage({ - image: { ...newImage, category: 'result' }, - category: 'result', - }) - ); - } - } +// if (state.canvas.shouldAutoSave) { +// dispatch( +// addImage({ +// image: { ...newImage, category: 'result' }, +// category: 'result', +// }) +// ); +// } +// } - // TODO: fix - // if (shouldLoopback) { - // const activeTabName = tabMap[activeTab]; - // switch (activeTabName) { - // case 'img2img': { - // dispatch(initialImageSelected(newImage.uuid)); - // // dispatch(setInitialImage(newImage)); - // break; - // } - // } - // } +// // TODO: fix +// // if (shouldLoopback) { +// // const activeTabName = tabMap[activeTab]; +// // switch (activeTabName) { +// // case 'img2img': { +// // dispatch(initialImageSelected(newImage.uuid)); +// // // dispatch(setInitialImage(newImage)); +// // break; +// // } +// // } +// // } - dispatch(clearIntermediateImage()); +// dispatch(clearIntermediateImage()); - dispatch( - addLogEntry({ - timestamp: dateFormat(new Date(), 'isoDateTime'), - message: `Image generated: ${data.url}`, - }) - ); - } catch (e) { - console.error(e); - } - }, - /** - * Callback to run when we receive a 'intermediateResult' event. - */ - onIntermediateResult: (data: InvokeAI.ImageResultResponse) => { - try { - dispatch( - setIntermediateImage({ - uuid: uuidv4(), - ...data, - category: 'result', - }) - ); - if (!data.isBase64) { - dispatch( - addLogEntry({ - timestamp: dateFormat(new Date(), 'isoDateTime'), - message: `Intermediate image generated: ${data.url}`, - }) - ); - } - } catch (e) { - console.error(e); - } - }, - /** - * Callback to run when we receive an 'esrganResult' event. - */ - onPostprocessingResult: (data: InvokeAI.ImageResultResponse) => { - try { - dispatch( - addImage({ - category: 'result', - image: { - uuid: uuidv4(), - ...data, - category: 'result', - }, - }) - ); +// dispatch( +// addLogEntry({ +// timestamp: dateFormat(new Date(), 'isoDateTime'), +// message: `Image generated: ${data.url}`, +// }) +// ); +// } catch (e) { +// console.error(e); +// } +// }, +// /** +// * Callback to run when we receive a 'intermediateResult' event. +// */ +// onIntermediateResult: (data: InvokeAI.ImageResultResponse) => { +// try { +// dispatch( +// setIntermediateImage({ +// uuid: uuidv4(), +// ...data, +// category: 'result', +// }) +// ); +// if (!data.isBase64) { +// dispatch( +// addLogEntry({ +// timestamp: dateFormat(new Date(), 'isoDateTime'), +// message: `Intermediate image generated: ${data.url}`, +// }) +// ); +// } +// } catch (e) { +// console.error(e); +// } +// }, +// /** +// * Callback to run when we receive an 'esrganResult' event. +// */ +// onPostprocessingResult: (data: InvokeAI.ImageResultResponse) => { +// try { +// dispatch( +// addImage({ +// category: 'result', +// image: { +// uuid: uuidv4(), +// ...data, +// category: 'result', +// }, +// }) +// ); - dispatch( - addLogEntry({ - timestamp: dateFormat(new Date(), 'isoDateTime'), - message: `Postprocessed: ${data.url}`, - }) - ); - } catch (e) { - console.error(e); - } - }, - /** - * Callback to run when we receive a 'progressUpdate' event. - * TODO: Add additional progress phases - */ - onProgressUpdate: (data: InvokeAI.SystemStatus) => { - try { - dispatch(setIsProcessing(true)); - dispatch(setSystemStatus(data)); - } catch (e) { - console.error(e); - } - }, - /** - * Callback to run when we receive a 'progressUpdate' event. - */ - onError: (data: InvokeAI.ErrorResponse) => { - const { message, additionalData } = data; +// dispatch( +// addLogEntry({ +// timestamp: dateFormat(new Date(), 'isoDateTime'), +// message: `Postprocessed: ${data.url}`, +// }) +// ); +// } catch (e) { +// console.error(e); +// } +// }, +// /** +// * Callback to run when we receive a 'progressUpdate' event. +// * TODO: Add additional progress phases +// */ +// onProgressUpdate: (data: InvokeAI.SystemStatus) => { +// try { +// dispatch(setIsProcessing(true)); +// dispatch(setSystemStatus(data)); +// } catch (e) { +// console.error(e); +// } +// }, +// /** +// * Callback to run when we receive a 'progressUpdate' event. +// */ +// onError: (data: InvokeAI.ErrorResponse) => { +// const { message, additionalData } = data; - if (additionalData) { - // TODO: handle more data than short message - } +// if (additionalData) { +// // TODO: handle more data than short message +// } - try { - dispatch( - addLogEntry({ - timestamp: dateFormat(new Date(), 'isoDateTime'), - message: `Server error: ${message}`, - level: 'error', - }) - ); - dispatch(errorOccurred()); - dispatch(clearIntermediateImage()); - } catch (e) { - console.error(e); - } - }, - /** - * Callback to run when we receive a 'galleryImages' event. - */ - onGalleryImages: (data: InvokeAI.GalleryImagesResponse) => { - const { images, areMoreImagesAvailable, category } = data; +// try { +// dispatch( +// addLogEntry({ +// timestamp: dateFormat(new Date(), 'isoDateTime'), +// message: `Server error: ${message}`, +// level: 'error', +// }) +// ); +// dispatch(errorOccurred()); +// dispatch(clearIntermediateImage()); +// } catch (e) { +// console.error(e); +// } +// }, +// /** +// * Callback to run when we receive a 'galleryImages' event. +// */ +// onGalleryImages: (data: InvokeAI.GalleryImagesResponse) => { +// const { images, areMoreImagesAvailable, category } = data; - /** - * the logic here ideally would be in the reducer but we have a side effect: - * generating a uuid. so the logic needs to be here, outside redux. - */ +// /** +// * the logic here ideally would be in the reducer but we have a side effect: +// * generating a uuid. so the logic needs to be here, outside redux. +// */ - // Generate a UUID for each image - const preparedImages = images.map((image): InvokeAI._Image => { - return { - uuid: uuidv4(), - ...image, - }; - }); +// // Generate a UUID for each image +// const preparedImages = images.map((image): InvokeAI._Image => { +// return { +// uuid: uuidv4(), +// ...image, +// }; +// }); - dispatch( - addGalleryImages({ - images: preparedImages, - areMoreImagesAvailable, - category, - }) - ); +// dispatch( +// addGalleryImages({ +// images: preparedImages, +// areMoreImagesAvailable, +// category, +// }) +// ); - dispatch( - addLogEntry({ - timestamp: dateFormat(new Date(), 'isoDateTime'), - message: `Loaded ${images.length} images`, - }) - ); - }, - /** - * Callback to run when we receive a 'processingCanceled' event. - */ - onProcessingCanceled: () => { - dispatch(processingCanceled()); +// dispatch( +// addLogEntry({ +// timestamp: dateFormat(new Date(), 'isoDateTime'), +// message: `Loaded ${images.length} images`, +// }) +// ); +// }, +// /** +// * Callback to run when we receive a 'processingCanceled' event. +// */ +// onProcessingCanceled: () => { +// dispatch(processingCanceled()); - const { intermediateImage } = getState().gallery; +// const { intermediateImage } = getState().gallery; - if (intermediateImage) { - if (!intermediateImage.isBase64) { - dispatch( - addImage({ - category: 'result', - image: intermediateImage, - }) - ); - dispatch( - addLogEntry({ - timestamp: dateFormat(new Date(), 'isoDateTime'), - message: `Intermediate image saved: ${intermediateImage.url}`, - }) - ); - } - dispatch(clearIntermediateImage()); - } +// if (intermediateImage) { +// if (!intermediateImage.isBase64) { +// dispatch( +// addImage({ +// category: 'result', +// image: intermediateImage, +// }) +// ); +// dispatch( +// addLogEntry({ +// timestamp: dateFormat(new Date(), 'isoDateTime'), +// message: `Intermediate image saved: ${intermediateImage.url}`, +// }) +// ); +// } +// dispatch(clearIntermediateImage()); +// } - dispatch( - addLogEntry({ - timestamp: dateFormat(new Date(), 'isoDateTime'), - message: `Processing canceled`, - level: 'warning', - }) - ); - }, - /** - * Callback to run when we receive a 'imageDeleted' event. - */ - onImageDeleted: (data: InvokeAI.ImageDeletedResponse) => { - const { url } = data; +// dispatch( +// addLogEntry({ +// timestamp: dateFormat(new Date(), 'isoDateTime'), +// message: `Processing canceled`, +// level: 'warning', +// }) +// ); +// }, +// /** +// * Callback to run when we receive a 'imageDeleted' event. +// */ +// onImageDeleted: (data: InvokeAI.ImageDeletedResponse) => { +// const { url } = data; - // remove image from gallery - dispatch(removeImage(data)); +// // remove image from gallery +// dispatch(removeImage(data)); - // remove references to image in options - const { - generation: { initialImage, maskPath }, - } = getState(); +// // remove references to image in options +// const { +// generation: { initialImage, maskPath }, +// } = getState(); - if ( - initialImage === url || - (initialImage as InvokeAI._Image)?.url === url - ) { - dispatch(clearInitialImage()); - } +// if ( +// initialImage === url || +// (initialImage as InvokeAI._Image)?.url === url +// ) { +// dispatch(clearInitialImage()); +// } - if (maskPath === url) { - dispatch(setMaskPath('')); - } +// if (maskPath === url) { +// dispatch(setMaskPath('')); +// } - dispatch( - addLogEntry({ - timestamp: dateFormat(new Date(), 'isoDateTime'), - message: `Image deleted: ${url}`, - }) - ); - }, - onSystemConfig: (data: InvokeAI.SystemConfig) => { - dispatch(setSystemConfig(data)); - if (!data.infill_methods.includes('patchmatch')) { - dispatch(setInfillMethod(data.infill_methods[0])); - } - }, - onFoundModels: (data: InvokeAI.FoundModelResponse) => { - const { search_folder, found_models } = data; - dispatch(setSearchFolder(search_folder)); - dispatch(setFoundModels(found_models)); - }, - onNewModelAdded: (data: InvokeAI.ModelAddedResponse) => { - const { new_model_name, model_list, update } = data; - dispatch(setModelList(model_list)); - dispatch(setIsProcessing(false)); - dispatch(setCurrentStatus(i18n.t('modelManager.modelAdded'))); - dispatch( - addLogEntry({ - timestamp: dateFormat(new Date(), 'isoDateTime'), - message: `Model Added: ${new_model_name}`, - level: 'info', - }) - ); - dispatch( - addToast({ - title: !update - ? `${i18n.t('modelManager.modelAdded')}: ${new_model_name}` - : `${i18n.t('modelManager.modelUpdated')}: ${new_model_name}`, - status: 'success', - duration: 2500, - isClosable: true, - }) - ); - }, - onModelDeleted: (data: InvokeAI.ModelDeletedResponse) => { - const { deleted_model_name, model_list } = data; - dispatch(setModelList(model_list)); - dispatch(setIsProcessing(false)); - dispatch( - addLogEntry({ - timestamp: dateFormat(new Date(), 'isoDateTime'), - message: `${i18n.t( - 'modelManager.modelAdded' - )}: ${deleted_model_name}`, - level: 'info', - }) - ); - dispatch( - addToast({ - title: `${i18n.t( - 'modelManager.modelEntryDeleted' - )}: ${deleted_model_name}`, - status: 'success', - duration: 2500, - isClosable: true, - }) - ); - }, - onModelConverted: (data: InvokeAI.ModelConvertedResponse) => { - const { converted_model_name, model_list } = data; - dispatch(setModelList(model_list)); - dispatch(setCurrentStatus(i18n.t('common.statusModelConverted'))); - dispatch(setIsProcessing(false)); - dispatch(setIsCancelable(true)); - dispatch( - addLogEntry({ - timestamp: dateFormat(new Date(), 'isoDateTime'), - message: `Model converted: ${converted_model_name}`, - level: 'info', - }) - ); - dispatch( - addToast({ - title: `${i18n.t( - 'modelManager.modelConverted' - )}: ${converted_model_name}`, - status: 'success', - duration: 2500, - isClosable: true, - }) - ); - }, - onModelsMerged: (data: InvokeAI.ModelsMergedResponse) => { - const { merged_models, merged_model_name, model_list } = data; - dispatch(setModelList(model_list)); - dispatch(setCurrentStatus(i18n.t('common.statusMergedModels'))); - dispatch(setIsProcessing(false)); - dispatch(setIsCancelable(true)); - dispatch( - addLogEntry({ - timestamp: dateFormat(new Date(), 'isoDateTime'), - message: `Models merged: ${merged_models}`, - level: 'info', - }) - ); - dispatch( - addToast({ - title: `${i18n.t('modelManager.modelsMerged')}: ${merged_model_name}`, - status: 'success', - duration: 2500, - isClosable: true, - }) - ); - }, - onModelChanged: (data: InvokeAI.ModelChangeResponse) => { - const { model_name, model_list } = data; - dispatch(setModelList(model_list)); - dispatch(setCurrentStatus(i18n.t('common.statusModelChanged'))); - dispatch(setIsProcessing(false)); - dispatch(setIsCancelable(true)); - dispatch( - addLogEntry({ - timestamp: dateFormat(new Date(), 'isoDateTime'), - message: `Model changed: ${model_name}`, - level: 'info', - }) - ); - }, - onModelChangeFailed: (data: InvokeAI.ModelChangeResponse) => { - const { model_name, model_list } = data; - dispatch(setModelList(model_list)); - dispatch(setIsProcessing(false)); - dispatch(setIsCancelable(true)); - dispatch(errorOccurred()); - dispatch( - addLogEntry({ - timestamp: dateFormat(new Date(), 'isoDateTime'), - message: `Model change failed: ${model_name}`, - level: 'error', - }) - ); - }, - onTempFolderEmptied: () => { - dispatch( - addToast({ - title: i18n.t('toast.tempFoldersEmptied'), - status: 'success', - duration: 2500, - isClosable: true, - }) - ); - }, - }; -}; +// dispatch( +// addLogEntry({ +// timestamp: dateFormat(new Date(), 'isoDateTime'), +// message: `Image deleted: ${url}`, +// }) +// ); +// }, +// onSystemConfig: (data: InvokeAI.SystemConfig) => { +// dispatch(setSystemConfig(data)); +// if (!data.infill_methods.includes('patchmatch')) { +// dispatch(setInfillMethod(data.infill_methods[0])); +// } +// }, +// onFoundModels: (data: InvokeAI.FoundModelResponse) => { +// const { search_folder, found_models } = data; +// dispatch(setSearchFolder(search_folder)); +// dispatch(setFoundModels(found_models)); +// }, +// onNewModelAdded: (data: InvokeAI.ModelAddedResponse) => { +// const { new_model_name, model_list, update } = data; +// dispatch(setModelList(model_list)); +// dispatch(setIsProcessing(false)); +// dispatch(setCurrentStatus(i18n.t('modelManager.modelAdded'))); +// dispatch( +// addLogEntry({ +// timestamp: dateFormat(new Date(), 'isoDateTime'), +// message: `Model Added: ${new_model_name}`, +// level: 'info', +// }) +// ); +// dispatch( +// addToast({ +// title: !update +// ? `${i18n.t('modelManager.modelAdded')}: ${new_model_name}` +// : `${i18n.t('modelManager.modelUpdated')}: ${new_model_name}`, +// status: 'success', +// duration: 2500, +// isClosable: true, +// }) +// ); +// }, +// onModelDeleted: (data: InvokeAI.ModelDeletedResponse) => { +// const { deleted_model_name, model_list } = data; +// dispatch(setModelList(model_list)); +// dispatch(setIsProcessing(false)); +// dispatch( +// addLogEntry({ +// timestamp: dateFormat(new Date(), 'isoDateTime'), +// message: `${i18n.t( +// 'modelManager.modelAdded' +// )}: ${deleted_model_name}`, +// level: 'info', +// }) +// ); +// dispatch( +// addToast({ +// title: `${i18n.t( +// 'modelManager.modelEntryDeleted' +// )}: ${deleted_model_name}`, +// status: 'success', +// duration: 2500, +// isClosable: true, +// }) +// ); +// }, +// onModelConverted: (data: InvokeAI.ModelConvertedResponse) => { +// const { converted_model_name, model_list } = data; +// dispatch(setModelList(model_list)); +// dispatch(setCurrentStatus(i18n.t('common.statusModelConverted'))); +// dispatch(setIsProcessing(false)); +// dispatch(setIsCancelable(true)); +// dispatch( +// addLogEntry({ +// timestamp: dateFormat(new Date(), 'isoDateTime'), +// message: `Model converted: ${converted_model_name}`, +// level: 'info', +// }) +// ); +// dispatch( +// addToast({ +// title: `${i18n.t( +// 'modelManager.modelConverted' +// )}: ${converted_model_name}`, +// status: 'success', +// duration: 2500, +// isClosable: true, +// }) +// ); +// }, +// onModelsMerged: (data: InvokeAI.ModelsMergedResponse) => { +// const { merged_models, merged_model_name, model_list } = data; +// dispatch(setModelList(model_list)); +// dispatch(setCurrentStatus(i18n.t('common.statusMergedModels'))); +// dispatch(setIsProcessing(false)); +// dispatch(setIsCancelable(true)); +// dispatch( +// addLogEntry({ +// timestamp: dateFormat(new Date(), 'isoDateTime'), +// message: `Models merged: ${merged_models}`, +// level: 'info', +// }) +// ); +// dispatch( +// addToast({ +// title: `${i18n.t('modelManager.modelsMerged')}: ${merged_model_name}`, +// status: 'success', +// duration: 2500, +// isClosable: true, +// }) +// ); +// }, +// onModelChanged: (data: InvokeAI.ModelChangeResponse) => { +// const { model_name, model_list } = data; +// dispatch(setModelList(model_list)); +// dispatch(setCurrentStatus(i18n.t('common.statusModelChanged'))); +// dispatch(setIsProcessing(false)); +// dispatch(setIsCancelable(true)); +// dispatch( +// addLogEntry({ +// timestamp: dateFormat(new Date(), 'isoDateTime'), +// message: `Model changed: ${model_name}`, +// level: 'info', +// }) +// ); +// }, +// onModelChangeFailed: (data: InvokeAI.ModelChangeResponse) => { +// const { model_name, model_list } = data; +// dispatch(setModelList(model_list)); +// dispatch(setIsProcessing(false)); +// dispatch(setIsCancelable(true)); +// dispatch(errorOccurred()); +// dispatch( +// addLogEntry({ +// timestamp: dateFormat(new Date(), 'isoDateTime'), +// message: `Model change failed: ${model_name}`, +// level: 'error', +// }) +// ); +// }, +// onTempFolderEmptied: () => { +// dispatch( +// addToast({ +// title: i18n.t('toast.tempFoldersEmptied'), +// status: 'success', +// duration: 2500, +// isClosable: true, +// }) +// ); +// }, +// }; +// }; -export default makeSocketIOListeners; +// export default makeSocketIOListeners; + +export default {}; diff --git a/invokeai/frontend/web/src/app/socketio/middleware.ts b/invokeai/frontend/web/src/app/socketio/middleware.ts index 74752dc980..88013ea222 100644 --- a/invokeai/frontend/web/src/app/socketio/middleware.ts +++ b/invokeai/frontend/web/src/app/socketio/middleware.ts @@ -1,246 +1,248 @@ -import { Middleware } from '@reduxjs/toolkit'; -import { io } from 'socket.io-client'; +// import { Middleware } from '@reduxjs/toolkit'; +// import { io } from 'socket.io-client'; -import makeSocketIOEmitters from './emitters'; -import makeSocketIOListeners from './listeners'; +// import makeSocketIOEmitters from './emitters'; +// import makeSocketIOListeners from './listeners'; -import * as InvokeAI from 'app/types/invokeai'; +// import * as InvokeAI from 'app/types/invokeai'; -/** - * Creates a socketio middleware to handle communication with server. - * - * Special `socketio/actionName` actions are created in actions.ts and - * exported for use by the application, which treats them like any old - * action, using `dispatch` to dispatch them. - * - * These actions are intercepted here, where `socketio.emit()` calls are - * made on their behalf - see `emitters.ts`. The emitter functions - * are the outbound communication to the server. - * - * Listeners are also established here - see `listeners.ts`. The listener - * functions receive communication from the server and usually dispatch - * some new action to handle whatever data was sent from the server. - */ -export const socketioMiddleware = () => { - const { origin } = new URL(window.location.href); +// /** +// * Creates a socketio middleware to handle communication with server. +// * +// * Special `socketio/actionName` actions are created in actions.ts and +// * exported for use by the application, which treats them like any old +// * action, using `dispatch` to dispatch them. +// * +// * These actions are intercepted here, where `socketio.emit()` calls are +// * made on their behalf - see `emitters.ts`. The emitter functions +// * are the outbound communication to the server. +// * +// * Listeners are also established here - see `listeners.ts`. The listener +// * functions receive communication from the server and usually dispatch +// * some new action to handle whatever data was sent from the server. +// */ +// export const socketioMiddleware = () => { +// const { origin } = new URL(window.location.href); - const socketio = io(origin, { - timeout: 60000, - path: `${window.location.pathname}socket.io`, - }); +// const socketio = io(origin, { +// timeout: 60000, +// path: `${window.location.pathname}socket.io`, +// }); - socketio.disconnect(); +// socketio.disconnect(); - let areListenersSet = false; +// let areListenersSet = false; - const middleware: Middleware = (store) => (next) => (action) => { - const { - onConnect, - onDisconnect, - onError, - onPostprocessingResult, - onGenerationResult, - onIntermediateResult, - onProgressUpdate, - onGalleryImages, - onProcessingCanceled, - onImageDeleted, - onSystemConfig, - onModelChanged, - onFoundModels, - onNewModelAdded, - onModelDeleted, - onModelConverted, - onModelsMerged, - onModelChangeFailed, - onTempFolderEmptied, - } = makeSocketIOListeners(store); +// const middleware: Middleware = (store) => (next) => (action) => { +// const { +// onConnect, +// onDisconnect, +// onError, +// onPostprocessingResult, +// onGenerationResult, +// onIntermediateResult, +// onProgressUpdate, +// onGalleryImages, +// onProcessingCanceled, +// onImageDeleted, +// onSystemConfig, +// onModelChanged, +// onFoundModels, +// onNewModelAdded, +// onModelDeleted, +// onModelConverted, +// onModelsMerged, +// onModelChangeFailed, +// onTempFolderEmptied, +// } = makeSocketIOListeners(store); - const { - emitGenerateImage, - emitRunESRGAN, - emitRunFacetool, - emitDeleteImage, - emitRequestImages, - emitRequestNewImages, - emitCancelProcessing, - emitRequestSystemConfig, - emitSearchForModels, - emitAddNewModel, - emitDeleteModel, - emitConvertToDiffusers, - emitMergeDiffusersModels, - emitRequestModelChange, - emitSaveStagingAreaImageToGallery, - emitRequestEmptyTempFolder, - } = makeSocketIOEmitters(store, socketio); +// const { +// emitGenerateImage, +// emitRunESRGAN, +// emitRunFacetool, +// emitDeleteImage, +// emitRequestImages, +// emitRequestNewImages, +// emitCancelProcessing, +// emitRequestSystemConfig, +// emitSearchForModels, +// emitAddNewModel, +// emitDeleteModel, +// emitConvertToDiffusers, +// emitMergeDiffusersModels, +// emitRequestModelChange, +// emitSaveStagingAreaImageToGallery, +// emitRequestEmptyTempFolder, +// } = makeSocketIOEmitters(store, socketio); - /** - * If this is the first time the middleware has been called (e.g. during store setup), - * initialize all our socket.io listeners. - */ - if (!areListenersSet) { - socketio.on('connect', () => onConnect()); +// /** +// * If this is the first time the middleware has been called (e.g. during store setup), +// * initialize all our socket.io listeners. +// */ +// if (!areListenersSet) { +// socketio.on('connect', () => onConnect()); - socketio.on('disconnect', () => onDisconnect()); +// socketio.on('disconnect', () => onDisconnect()); - socketio.on('error', (data: InvokeAI.ErrorResponse) => onError(data)); +// socketio.on('error', (data: InvokeAI.ErrorResponse) => onError(data)); - socketio.on('generationResult', (data: InvokeAI.ImageResultResponse) => - onGenerationResult(data) - ); +// socketio.on('generationResult', (data: InvokeAI.ImageResultResponse) => +// onGenerationResult(data) +// ); - socketio.on( - 'postprocessingResult', - (data: InvokeAI.ImageResultResponse) => onPostprocessingResult(data) - ); +// socketio.on( +// 'postprocessingResult', +// (data: InvokeAI.ImageResultResponse) => onPostprocessingResult(data) +// ); - socketio.on('intermediateResult', (data: InvokeAI.ImageResultResponse) => - onIntermediateResult(data) - ); +// socketio.on('intermediateResult', (data: InvokeAI.ImageResultResponse) => +// onIntermediateResult(data) +// ); - socketio.on('progressUpdate', (data: InvokeAI.SystemStatus) => - onProgressUpdate(data) - ); +// socketio.on('progressUpdate', (data: InvokeAI.SystemStatus) => +// onProgressUpdate(data) +// ); - socketio.on('galleryImages', (data: InvokeAI.GalleryImagesResponse) => - onGalleryImages(data) - ); +// socketio.on('galleryImages', (data: InvokeAI.GalleryImagesResponse) => +// onGalleryImages(data) +// ); - socketio.on('processingCanceled', () => { - onProcessingCanceled(); - }); +// socketio.on('processingCanceled', () => { +// onProcessingCanceled(); +// }); - socketio.on('imageDeleted', (data: InvokeAI.ImageDeletedResponse) => { - onImageDeleted(data); - }); +// socketio.on('imageDeleted', (data: InvokeAI.ImageDeletedResponse) => { +// onImageDeleted(data); +// }); - socketio.on('systemConfig', (data: InvokeAI.SystemConfig) => { - onSystemConfig(data); - }); +// socketio.on('systemConfig', (data: InvokeAI.SystemConfig) => { +// onSystemConfig(data); +// }); - socketio.on('foundModels', (data: InvokeAI.FoundModelResponse) => { - onFoundModels(data); - }); +// socketio.on('foundModels', (data: InvokeAI.FoundModelResponse) => { +// onFoundModels(data); +// }); - socketio.on('newModelAdded', (data: InvokeAI.ModelAddedResponse) => { - onNewModelAdded(data); - }); +// socketio.on('newModelAdded', (data: InvokeAI.ModelAddedResponse) => { +// onNewModelAdded(data); +// }); - socketio.on('modelDeleted', (data: InvokeAI.ModelDeletedResponse) => { - onModelDeleted(data); - }); +// socketio.on('modelDeleted', (data: InvokeAI.ModelDeletedResponse) => { +// onModelDeleted(data); +// }); - socketio.on('modelConverted', (data: InvokeAI.ModelConvertedResponse) => { - onModelConverted(data); - }); +// socketio.on('modelConverted', (data: InvokeAI.ModelConvertedResponse) => { +// onModelConverted(data); +// }); - socketio.on('modelsMerged', (data: InvokeAI.ModelsMergedResponse) => { - onModelsMerged(data); - }); +// socketio.on('modelsMerged', (data: InvokeAI.ModelsMergedResponse) => { +// onModelsMerged(data); +// }); - socketio.on('modelChanged', (data: InvokeAI.ModelChangeResponse) => { - onModelChanged(data); - }); +// socketio.on('modelChanged', (data: InvokeAI.ModelChangeResponse) => { +// onModelChanged(data); +// }); - socketio.on('modelChangeFailed', (data: InvokeAI.ModelChangeResponse) => { - onModelChangeFailed(data); - }); +// socketio.on('modelChangeFailed', (data: InvokeAI.ModelChangeResponse) => { +// onModelChangeFailed(data); +// }); - socketio.on('tempFolderEmptied', () => { - onTempFolderEmptied(); - }); +// socketio.on('tempFolderEmptied', () => { +// onTempFolderEmptied(); +// }); - areListenersSet = true; - } +// areListenersSet = true; +// } - /** - * Handle redux actions caught by middleware. - */ - switch (action.type) { - case 'socketio/generateImage': { - emitGenerateImage(action.payload); - break; - } +// /** +// * Handle redux actions caught by middleware. +// */ +// switch (action.type) { +// case 'socketio/generateImage': { +// emitGenerateImage(action.payload); +// break; +// } - case 'socketio/runESRGAN': { - emitRunESRGAN(action.payload); - break; - } +// case 'socketio/runESRGAN': { +// emitRunESRGAN(action.payload); +// break; +// } - case 'socketio/runFacetool': { - emitRunFacetool(action.payload); - break; - } +// case 'socketio/runFacetool': { +// emitRunFacetool(action.payload); +// break; +// } - case 'socketio/deleteImage': { - emitDeleteImage(action.payload); - break; - } +// case 'socketio/deleteImage': { +// emitDeleteImage(action.payload); +// break; +// } - case 'socketio/requestImages': { - emitRequestImages(action.payload); - break; - } +// case 'socketio/requestImages': { +// emitRequestImages(action.payload); +// break; +// } - case 'socketio/requestNewImages': { - emitRequestNewImages(action.payload); - break; - } +// case 'socketio/requestNewImages': { +// emitRequestNewImages(action.payload); +// break; +// } - case 'socketio/cancelProcessing': { - emitCancelProcessing(); - break; - } +// case 'socketio/cancelProcessing': { +// emitCancelProcessing(); +// break; +// } - case 'socketio/requestSystemConfig': { - emitRequestSystemConfig(); - break; - } +// case 'socketio/requestSystemConfig': { +// emitRequestSystemConfig(); +// break; +// } - case 'socketio/searchForModels': { - emitSearchForModels(action.payload); - break; - } +// case 'socketio/searchForModels': { +// emitSearchForModels(action.payload); +// break; +// } - case 'socketio/addNewModel': { - emitAddNewModel(action.payload); - break; - } +// case 'socketio/addNewModel': { +// emitAddNewModel(action.payload); +// break; +// } - case 'socketio/deleteModel': { - emitDeleteModel(action.payload); - break; - } +// case 'socketio/deleteModel': { +// emitDeleteModel(action.payload); +// break; +// } - case 'socketio/convertToDiffusers': { - emitConvertToDiffusers(action.payload); - break; - } +// case 'socketio/convertToDiffusers': { +// emitConvertToDiffusers(action.payload); +// break; +// } - case 'socketio/mergeDiffusersModels': { - emitMergeDiffusersModels(action.payload); - break; - } +// case 'socketio/mergeDiffusersModels': { +// emitMergeDiffusersModels(action.payload); +// break; +// } - case 'socketio/requestModelChange': { - emitRequestModelChange(action.payload); - break; - } +// case 'socketio/requestModelChange': { +// emitRequestModelChange(action.payload); +// break; +// } - case 'socketio/saveStagingAreaImageToGallery': { - emitSaveStagingAreaImageToGallery(action.payload); - break; - } +// case 'socketio/saveStagingAreaImageToGallery': { +// emitSaveStagingAreaImageToGallery(action.payload); +// break; +// } - case 'socketio/requestEmptyTempFolder': { - emitRequestEmptyTempFolder(); - break; - } - } +// case 'socketio/requestEmptyTempFolder': { +// emitRequestEmptyTempFolder(); +// break; +// } +// } - next(action); - }; +// next(action); +// }; - return middleware; -}; +// return middleware; +// }; + +export default {}; diff --git a/invokeai/frontend/web/src/app/store/store.ts b/invokeai/frontend/web/src/app/store/store.ts index 627c4f0063..20c0fa8b2a 100644 --- a/invokeai/frontend/web/src/app/store/store.ts +++ b/invokeai/frontend/web/src/app/store/store.ts @@ -19,7 +19,6 @@ import hotkeysReducer from 'features/ui/store/hotkeysSlice'; import modelsReducer from 'features/system/store/modelSlice'; import nodesReducer from 'features/nodes/store/nodesSlice'; -import { socketioMiddleware } from '../socketio/middleware'; import { socketMiddleware } from 'services/events/middleware'; import { canvasDenylist } from 'features/canvas/store/canvasPersistDenylist'; import { galleryDenylist } from 'features/gallery/store/galleryPersistDenylist'; @@ -87,13 +86,13 @@ const rootPersistConfig = getPersistConfig({ const persistedReducer = persistReducer(rootPersistConfig, rootReducer); // TODO: rip the old middleware out when nodes is complete -export function buildMiddleware() { - if (import.meta.env.MODE === 'nodes' || import.meta.env.MODE === 'package') { - return socketMiddleware(); - } else { - return socketioMiddleware(); - } -} +// export function buildMiddleware() { +// if (import.meta.env.MODE === 'nodes' || import.meta.env.MODE === 'package') { +// return socketMiddleware(); +// } else { +// return socketioMiddleware(); +// } +// } export const store = configureStore({ reducer: persistedReducer, diff --git a/invokeai/frontend/web/src/app/types/invokeai.ts b/invokeai/frontend/web/src/app/types/invokeai.ts index 27ca9dc4a6..bd9642491d 100644 --- a/invokeai/frontend/web/src/app/types/invokeai.ts +++ b/invokeai/frontend/web/src/app/types/invokeai.ts @@ -111,9 +111,9 @@ export type FacetoolMetadata = CommonPostProcessedImageMetadata & { export type PostProcessedImageMetadata = ESRGANMetadata | FacetoolMetadata; // Metadata includes the system config and image metadata. -export type Metadata = SystemGenerationMetadata & { - image: GeneratedImageMetadata | PostProcessedImageMetadata; -}; +// export type Metadata = SystemGenerationMetadata & { +// image: GeneratedImageMetadata | PostProcessedImageMetadata; +// }; // An Image has a UUID, url, modified timestamp, width, height and maybe metadata export type _Image = { @@ -150,31 +150,31 @@ export type GalleryImages = { * Types related to the system status. */ -// This represents the processing status of the backend. -export type SystemStatus = { - isProcessing: boolean; - currentStep: number; - totalSteps: number; - currentIteration: number; - totalIterations: number; - currentStatus: string; - currentStatusHasSteps: boolean; - hasError: boolean; -}; +// // This represents the processing status of the backend. +// export type SystemStatus = { +// isProcessing: boolean; +// currentStep: number; +// totalSteps: number; +// currentIteration: number; +// totalIterations: number; +// currentStatus: string; +// currentStatusHasSteps: boolean; +// hasError: boolean; +// }; -export type SystemGenerationMetadata = { - model: string; - model_weights?: string; - model_id?: string; - model_hash: string; - app_id: string; - app_version: string; -}; +// export type SystemGenerationMetadata = { +// model: string; +// model_weights?: string; +// model_id?: string; +// model_hash: string; +// app_id: string; +// app_version: string; +// }; -export type SystemConfig = SystemGenerationMetadata & { - model_list: ModelList; - infill_methods: string[]; -}; +// export type SystemConfig = SystemGenerationMetadata & { +// model_list: ModelList; +// infill_methods: string[]; +// }; export type ModelStatus = 'active' | 'cached' | 'not loaded'; @@ -286,9 +286,9 @@ export type FoundModelResponse = { found_models: FoundModel[]; }; -export type SystemStatusResponse = SystemStatus; +// export type SystemStatusResponse = SystemStatus; -export type SystemConfigResponse = SystemConfig; +// export type SystemConfigResponse = SystemConfig; export type ImageResultResponse = Omit<_Image, 'uuid'> & { boundingBox?: IRect; diff --git a/invokeai/frontend/web/src/features/canvas/components/IAICanvasStagingAreaToolbar.tsx b/invokeai/frontend/web/src/features/canvas/components/IAICanvasStagingAreaToolbar.tsx index cbcd86d8d6..eeb51d955b 100644 --- a/invokeai/frontend/web/src/features/canvas/components/IAICanvasStagingAreaToolbar.tsx +++ b/invokeai/frontend/web/src/features/canvas/components/IAICanvasStagingAreaToolbar.tsx @@ -1,6 +1,6 @@ import { ButtonGroup, Flex } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; -import { saveStagingAreaImageToGallery } from 'app/socketio/actions'; +// import { saveStagingAreaImageToGallery } from 'app/socketio/actions'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIIconButton from 'common/components/IAIIconButton'; import { canvasSelector } from 'features/canvas/store/canvasSelectors'; diff --git a/invokeai/frontend/web/src/features/gallery/components/CurrentImageButtons.tsx b/invokeai/frontend/web/src/features/gallery/components/CurrentImageButtons.tsx index 481e3feb40..a30d8bcac1 100644 --- a/invokeai/frontend/web/src/features/gallery/components/CurrentImageButtons.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/CurrentImageButtons.tsx @@ -1,5 +1,5 @@ import { createSelector } from '@reduxjs/toolkit'; -import { isEqual } from 'lodash-es'; +import { get, isEqual, isNumber, isString } from 'lodash-es'; import { ButtonGroup, @@ -10,7 +10,7 @@ import { useDisclosure, useToast, } from '@chakra-ui/react'; -import { runESRGAN, runFacetool } from 'app/socketio/actions'; +// import { runESRGAN, runFacetool } from 'app/socketio/actions'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIButton from 'common/components/IAIButton'; import IAIIconButton from 'common/components/IAIIconButton'; @@ -68,6 +68,7 @@ import { requestCanvasRescale } from 'features/canvas/store/thunks/requestCanvas import { useGetUrl } from 'common/util/getUrl'; import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus'; import { imageDeleted } from 'services/thunks/image'; +import { useParameters } from 'features/parameters/hooks/useParameters'; const currentImageButtonsSelector = createSelector( [ @@ -112,6 +113,8 @@ const currentImageButtonsSelector = createSelector( isLightboxOpen, shouldHidePreview, image, + seed: image?.metadata?.invokeai?.node?.seed, + prompt: image?.metadata?.invokeai?.node?.prompt, }; }, { @@ -161,16 +164,8 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => { const toast = useToast(); const { t } = useTranslation(); - const setBothPrompts = useSetBothPrompts(); - const handleClickUseAsInitialImage = useCallback(() => { - if (!image) return; - if (isLightboxOpen) dispatch(setIsLightboxOpen(false)); - dispatch(initialImageSelected({ name: image.name, type: image.type })); - // dispatch(setInitialImage(currentImage)); - - // dispatch(setActiveTab('img2img')); - }, [dispatch, image, isLightboxOpen]); + const { recallPrompt, recallSeed, sendToImageToImage } = useParameters(); const handleCopyImage = useCallback(async () => { if (!image?.url) { @@ -217,30 +212,6 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => { }); }, [toast, shouldTransformUrls, getUrl, t, image]); - useHotkeys( - 'shift+i', - () => { - if (image) { - handleClickUseAsInitialImage(); - toast({ - title: t('toast.sentToImageToImage'), - status: 'success', - duration: 2500, - isClosable: true, - }); - } else { - toast({ - title: t('toast.imageNotLoaded'), - description: t('toast.imageNotLoadedDesc'), - status: 'error', - duration: 2500, - isClosable: true, - }); - } - }, - [image] - ); - const handlePreviewVisibility = useCallback(() => { dispatch(setShouldHidePreview(!shouldHidePreview)); }, [dispatch, shouldHidePreview]); @@ -259,7 +230,8 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => { useHotkeys( 'a', () => { - if (['txt2img', 'img2img'].includes(image?.metadata?.sd_metadata?.type)) { + const type = image?.metadata?.invokeai?.node?.types; + if (isString(type) && ['txt2img', 'img2img'].includes(type)) { handleClickUseAllParameters(); toast({ title: t('toast.parametersSet'), @@ -280,63 +252,23 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => { [image] ); - const handleClickUseSeed = () => { - image?.metadata && dispatch(setSeed(image.metadata.sd_metadata.seed)); - }; + const handleUseSeed = useCallback(() => { + recallSeed(image?.metadata?.invokeai?.node?.seed); + }, [image, recallSeed]); - useHotkeys( - 's', - () => { - if (image?.metadata?.sd_metadata?.seed) { - handleClickUseSeed(); - toast({ - title: t('toast.seedSet'), - status: 'success', - duration: 2500, - isClosable: true, - }); - } else { - toast({ - title: t('toast.seedNotSet'), - description: t('toast.seedNotSetDesc'), - status: 'error', - duration: 2500, - isClosable: true, - }); - } - }, - [image] - ); + useHotkeys('s', handleUseSeed, [image]); - const handleClickUsePrompt = useCallback(() => { - if (image?.metadata?.sd_metadata?.prompt) { - setBothPrompts(image?.metadata?.sd_metadata?.prompt); - } - }, [image?.metadata?.sd_metadata?.prompt, setBothPrompts]); + const handleUsePrompt = useCallback(() => { + recallPrompt(image?.metadata?.invokeai?.node?.prompt); + }, [image, recallPrompt]); - useHotkeys( - 'p', - () => { - if (image?.metadata?.sd_metadata?.prompt) { - handleClickUsePrompt(); - toast({ - title: t('toast.promptSet'), - status: 'success', - duration: 2500, - isClosable: true, - }); - } else { - toast({ - title: t('toast.promptNotSet'), - description: t('toast.promptNotSetDesc'), - status: 'error', - duration: 2500, - isClosable: true, - }); - } - }, - [image] - ); + useHotkeys('p', handleUsePrompt, [image]); + + const handleSendToImageToImage = useCallback(() => { + sendToImageToImage(image); + }, [image, sendToImageToImage]); + + useHotkeys('shift+i', handleSendToImageToImage, [image]); const handleClickUpscale = useCallback(() => { // selectedImage && dispatch(runESRGAN(selectedImage)); @@ -496,7 +428,7 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => { > } > {t('parameters.sendToImg2Img')} @@ -570,8 +502,8 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => { icon={} tooltip={`${t('parameters.usePrompt')} (P)`} aria-label={`${t('parameters.usePrompt')} (P)`} - isDisabled={!image?.metadata?.sd_metadata?.prompt} - onClick={handleClickUsePrompt} + isDisabled={!image?.metadata?.invokeai?.node?.prompt} + onClick={handleUsePrompt} /> { tooltip={`${t('parameters.useSeed')} (S)`} aria-label={`${t('parameters.useSeed')} (S)`} isDisabled={!image?.metadata?.sd_metadata?.seed} - onClick={handleClickUseSeed} + onClick={handleUseSeed} /> { + [gallerySelector, systemSelector, lightboxSelector, activeTabNameSelector], + (gallery, system, lightbox, activeTabName) => { const { galleryImageObjectFit, galleryImageMinimumWidth, @@ -71,7 +43,6 @@ export const selector = createSelector( } = gallery; const { isLightboxOpen } = lightbox; - const { disabledFeatures } = config; const { isConnected, isProcessing, shouldConfirmOnDelete } = system; return { @@ -82,7 +53,6 @@ export const selector = createSelector( shouldUseSingleGalleryColumn, activeTabName, isLightboxOpen, - disabledFeatures, }; }, { @@ -113,14 +83,15 @@ const HoverableImage = memo((props: HoverableImageProps) => { galleryImageMinimumWidth, canDeleteImage, shouldUseSingleGalleryColumn, - disabledFeatures, shouldConfirmOnDelete, } = useAppSelector(selector); + const { isOpen: isDeleteDialogOpen, onOpen: onDeleteDialogOpen, onClose: onDeleteDialogClose, } = useDisclosure(); + const { image, isSelected } = props; const { url, thumbnail, name, metadata } = image; const { getUrl } = useGetUrl(); @@ -130,53 +101,62 @@ const HoverableImage = memo((props: HoverableImageProps) => { const toast = useToast(); const { direction } = useTheme(); const { t } = useTranslation(); - const setBothPrompts = useSetBothPrompts(); + const { isFeatureEnabled: isLightboxEnabled } = useFeatureStatus('lightbox'); + const { recallSeed, recallPrompt, sendToImageToImage, recallInitialImage } = + useParameters(); const handleMouseOver = () => setIsHovered(true); - const handleMouseOut = () => setIsHovered(false); - const handleInitiateDelete = () => { + // Immediately deletes an image + const handleDelete = useCallback(() => { + if (canDeleteImage && image) { + dispatch(imageDeleted({ imageType: image.type, imageName: image.name })); + } + }, [dispatch, image, canDeleteImage]); + + // Opens the alert dialog to check if user is sure they want to delete + const handleInitiateDelete = useCallback(() => { if (shouldConfirmOnDelete) { onDeleteDialogOpen(); } else { handleDelete(); } - }; + }, [handleDelete, onDeleteDialogOpen, shouldConfirmOnDelete]); - const handleDelete = () => { - if (canDeleteImage && image) { - dispatch(imageDeleted({ imageType: image.type, imageName: image.name })); - } - }; + const handleSelectImage = useCallback(() => { + dispatch(imageSelected(image.name)); + }, [image, dispatch]); - const handleUsePrompt = () => { - if (typeof image.metadata?.invokeai?.node?.prompt === 'string') { - setBothPrompts(image.metadata?.invokeai?.node?.prompt); - } - toast({ - title: t('toast.promptSet'), - status: 'success', - duration: 2500, - isClosable: true, - }); - }; + const handleDragStart = useCallback( + (e: DragEvent) => { + e.dataTransfer.setData('invokeai/imageName', image.name); + e.dataTransfer.setData('invokeai/imageType', image.type); + e.dataTransfer.effectAllowed = 'move'; + }, + [image] + ); - const handleUseSeed = () => { - typeof image.metadata.invokeai?.node?.seed === 'number' && - dispatch(setSeed(image.metadata.invokeai?.node?.seed)); - toast({ - title: t('toast.seedSet'), - status: 'success', - duration: 2500, - isClosable: true, - }); - }; + // Recall parameters handlers + const handleRecallPrompt = useCallback(() => { + recallPrompt(image.metadata?.invokeai?.node?.prompt); + }, [image, recallPrompt]); - const handleSendToImageToImage = () => { - dispatch(initialImageSelected(image.name)); - }; + const handleRecallSeed = useCallback(() => { + recallSeed(image.metadata.invokeai?.node?.seed); + }, [image, recallSeed]); + const handleSendToImageToImage = useCallback(() => { + sendToImageToImage(image); + }, [image, sendToImageToImage]); + + const handleRecallInitialImage = useCallback(() => { + recallInitialImage(image.metadata.invokeai?.node?.image); + }, [image, recallInitialImage]); + + /** + * TODO: the rest of these + */ const handleSendToCanvas = () => { // dispatch(setInitialCanvasImage(image)); @@ -205,41 +185,6 @@ const HoverableImage = memo((props: HoverableImageProps) => { // }); }; - const handleUseInitialImage = async () => { - // if (metadata.invokeai?.node?.image?.init_image_path) { - // const response = await fetch( - // metadata.invokeai?.node?.image?.init_image_path - // ); - // if (response.ok) { - // dispatch(setAllImageToImageParameters(metadata?.invokeai?.node)); - // toast({ - // title: t('toast.initialImageSet'), - // status: 'success', - // duration: 2500, - // isClosable: true, - // }); - // return; - // } - // } - // toast({ - // title: t('toast.initialImageNotSet'), - // description: t('toast.initialImageNotSetDesc'), - // status: 'error', - // duration: 2500, - // isClosable: true, - // }); - }; - - const handleSelectImage = () => { - dispatch(imageSelected(image.name)); - }; - - const handleDragStart = (e: DragEvent) => { - e.dataTransfer.setData('invokeai/imageName', image.name); - e.dataTransfer.setData('invokeai/imageType', image.type); - e.dataTransfer.effectAllowed = 'move'; - }; - const handleLightBox = () => { // dispatch(setCurrentImage(image)); // dispatch(setIsLightboxOpen(true)); @@ -254,21 +199,21 @@ const HoverableImage = memo((props: HoverableImageProps) => { menuProps={{ size: 'sm', isLazy: true }} renderMenu={() => ( - + } onClickCapture={handleOpenInNewTab} > {t('common.openInNewTab')} - {!disabledFeatures.includes('lightbox') && ( + {isLightboxEnabled && ( } onClickCapture={handleLightBox}> {t('parameters.openInViewer')} )} } - onClickCapture={handleUsePrompt} + onClickCapture={handleRecallPrompt} isDisabled={image?.metadata?.invokeai?.node?.prompt === undefined} > {t('parameters.usePrompt')} @@ -276,14 +221,14 @@ const HoverableImage = memo((props: HoverableImageProps) => { } - onClickCapture={handleUseSeed} + onClickCapture={handleRecallSeed} isDisabled={image?.metadata?.invokeai?.node?.seed === undefined} > {t('parameters.useSeed')} } - onClickCapture={handleUseInitialImage} + onClickCapture={handleRecallInitialImage} isDisabled={image?.metadata?.invokeai?.node?.type !== 'img2img'} > {t('parameters.useInitImg')} diff --git a/invokeai/frontend/web/src/features/gallery/components/ImageGalleryContent.tsx b/invokeai/frontend/web/src/features/gallery/components/ImageGalleryContent.tsx index 1b57dbea78..e08e934e75 100644 --- a/invokeai/frontend/web/src/features/gallery/components/ImageGalleryContent.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/ImageGalleryContent.tsx @@ -1,5 +1,5 @@ import { ButtonGroup, Flex, Grid, Icon, Image, Text } from '@chakra-ui/react'; -import { requestImages } from 'app/socketio/actions'; +// import { requestImages } from 'app/socketio/actions'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIButton from 'common/components/IAIButton'; import IAICheckbox from 'common/components/IAICheckbox'; diff --git a/invokeai/frontend/web/src/features/parameters/components/ProcessButtons/InvokeButton.tsx b/invokeai/frontend/web/src/features/parameters/components/ProcessButtons/InvokeButton.tsx index e028fe4f8d..d2002eb04f 100644 --- a/invokeai/frontend/web/src/features/parameters/components/ProcessButtons/InvokeButton.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/ProcessButtons/InvokeButton.tsx @@ -1,6 +1,5 @@ import { Box } from '@chakra-ui/react'; import { readinessSelector } from 'app/selectors/readinessSelector'; -import { generateImage } from 'app/socketio/actions'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIButton, { IAIButtonProps } from 'common/components/IAIButton'; import IAIIconButton, { @@ -8,10 +7,11 @@ import IAIIconButton, { } from 'common/components/IAIIconButton'; import { clampSymmetrySteps } from 'features/parameters/store/generationSlice'; import { activeTabNameSelector } from 'features/ui/store/uiSelectors'; +import { useCallback } from 'react'; import { useHotkeys } from 'react-hotkeys-hook'; import { useTranslation } from 'react-i18next'; import { FaPlay } from 'react-icons/fa'; -import { generateGraphBuilt, sessionCreated } from 'services/thunks/session'; +import { generateGraphBuilt } from 'services/thunks/session'; interface InvokeButton extends Omit { @@ -24,19 +24,16 @@ export default function InvokeButton(props: InvokeButton) { const { isReady } = useAppSelector(readinessSelector); const activeTabName = useAppSelector(activeTabNameSelector); - const handleClickGenerate = () => { - // dispatch(generateImage(activeTabName)); + const handleInvoke = useCallback(() => { + dispatch(clampSymmetrySteps()); dispatch(generateGraphBuilt()); - }; + }, [dispatch]); const { t } = useTranslation(); useHotkeys( ['ctrl+enter', 'meta+enter'], - () => { - dispatch(clampSymmetrySteps()); - dispatch(generateImage(activeTabName)); - }, + handleInvoke, { enabled: () => isReady, preventDefault: true, @@ -53,7 +50,7 @@ export default function InvokeButton(props: InvokeButton) { type="submit" icon={} isDisabled={!isReady} - onClick={handleClickGenerate} + onClick={handleInvoke} flexGrow={1} w="100%" tooltip={t('parameters.invoke')} @@ -66,7 +63,7 @@ export default function InvokeButton(props: InvokeButton) { aria-label={t('parameters.invoke')} type="submit" isDisabled={!isReady} - onClick={handleClickGenerate} + onClick={handleInvoke} flexGrow={1} w="100%" colorScheme="accent" diff --git a/invokeai/frontend/web/src/features/parameters/components/PromptInput/PromptInput.tsx b/invokeai/frontend/web/src/features/parameters/components/PromptInput/PromptInput.tsx index 13095ffefa..b54106733c 100644 --- a/invokeai/frontend/web/src/features/parameters/components/PromptInput/PromptInput.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/PromptInput/PromptInput.tsx @@ -1,5 +1,4 @@ import { Box, FormControl, Textarea } from '@chakra-ui/react'; -import { generateImage } from 'app/socketio/actions'; import { RootState } from 'app/store/store'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { ChangeEvent, KeyboardEvent, useRef } from 'react'; @@ -8,6 +7,7 @@ import { createSelector } from '@reduxjs/toolkit'; import { readinessSelector } from 'app/selectors/readinessSelector'; import { GenerationState, + clampSymmetrySteps, setPrompt, } from 'features/parameters/store/generationSlice'; import { activeTabNameSelector } from 'features/ui/store/uiSelectors'; @@ -15,6 +15,7 @@ import { activeTabNameSelector } from 'features/ui/store/uiSelectors'; import { isEqual } from 'lodash-es'; import { useHotkeys } from 'react-hotkeys-hook'; import { useTranslation } from 'react-i18next'; +import { generateGraphBuilt } from 'services/thunks/session'; const promptInputSelector = createSelector( [(state: RootState) => state.generation, activeTabNameSelector], @@ -36,7 +37,7 @@ const promptInputSelector = createSelector( */ const PromptInput = () => { const dispatch = useAppDispatch(); - const { prompt, activeTabName } = useAppSelector(promptInputSelector); + const { prompt } = useAppSelector(promptInputSelector); const { isReady } = useAppSelector(readinessSelector); const promptRef = useRef(null); @@ -58,7 +59,8 @@ const PromptInput = () => { const handleKeyDown = (e: KeyboardEvent) => { if (e.key === 'Enter' && e.shiftKey === false && isReady) { e.preventDefault(); - dispatch(generateImage(activeTabName)); + dispatch(clampSymmetrySteps()); + dispatch(generateGraphBuilt()); } }; diff --git a/invokeai/frontend/web/src/features/parameters/hooks/useParameters.ts b/invokeai/frontend/web/src/features/parameters/hooks/useParameters.ts new file mode 100644 index 0000000000..ac4aa83098 --- /dev/null +++ b/invokeai/frontend/web/src/features/parameters/hooks/useParameters.ts @@ -0,0 +1,130 @@ +import { useToast } from '@chakra-ui/react'; +import { useAppDispatch } from 'app/store/storeHooks'; +import { isFinite, isString } from 'lodash-es'; +import { useCallback } from 'react'; +import { useTranslation } from 'react-i18next'; +import useSetBothPrompts from './usePrompt'; +import { initialImageSelected, setSeed } from '../store/generationSlice'; +import { isImage, isImageField } from 'services/types/guards'; +import { NUMPY_RAND_MAX } from 'app/constants'; + +export const useParameters = () => { + const dispatch = useAppDispatch(); + const toast = useToast(); + const { t } = useTranslation(); + const setBothPrompts = useSetBothPrompts(); + + /** + * Sets prompt with toast + */ + const recallPrompt = useCallback( + (prompt: unknown) => { + if (!isString(prompt)) { + toast({ + title: t('toast.promptNotSet'), + description: t('toast.promptNotSetDesc'), + status: 'warning', + duration: 2500, + isClosable: true, + }); + return; + } + + setBothPrompts(prompt); + toast({ + title: t('toast.promptSet'), + status: 'info', + duration: 2500, + isClosable: true, + }); + }, + [t, toast, setBothPrompts] + ); + + /** + * Sets seed with toast + */ + const recallSeed = useCallback( + (seed: unknown) => { + const s = Number(seed); + if (!isFinite(s) || (isFinite(s) && !(s >= 0 && s <= NUMPY_RAND_MAX))) { + toast({ + title: t('toast.seedNotSet'), + description: t('toast.seedNotSetDesc'), + status: 'error', + duration: 2500, + isClosable: true, + }); + return; + } + + dispatch(setSeed(s)); + toast({ + title: t('toast.seedSet'), + status: 'success', + duration: 2500, + isClosable: true, + }); + }, + [t, toast, dispatch] + ); + + /** + * Sets initial image with toast + */ + const recallInitialImage = useCallback( + async (image: unknown) => { + if (!isImageField(image)) { + toast({ + title: t('toast.initialImageNotSet'), + description: t('toast.initialImageNotSetDesc'), + status: 'error', + duration: 2500, + isClosable: true, + }); + return; + } + + dispatch( + initialImageSelected({ name: image.image_name, type: image.image_type }) + ); + toast({ + title: t('toast.initialImageSet'), + status: 'success', + duration: 2500, + isClosable: true, + }); + }, + [t, toast, dispatch] + ); + + /** + * Sets image as initial image with toast + */ + const sendToImageToImage = useCallback( + (image: unknown) => { + if (!isImage(image)) { + toast({ + title: t('toast.imageNotLoaded'), + description: t('toast.imageNotLoadedDesc'), + status: 'error', + duration: 2500, + isClosable: true, + }); + return; + } + + dispatch(initialImageSelected({ name: image.name, type: image.type })); + + toast({ + title: t('toast.sentToImageToImage'), + status: 'success', + duration: 2500, + isClosable: true, + }); + }, + [t, toast, dispatch] + ); + + return { recallPrompt, recallSeed, recallInitialImage, sendToImageToImage }; +}; diff --git a/invokeai/frontend/web/src/features/system/components/ClearTempFolderButtonModal.tsx b/invokeai/frontend/web/src/features/system/components/ClearTempFolderButtonModal.tsx index 353eddc323..a220c93b3f 100644 --- a/invokeai/frontend/web/src/features/system/components/ClearTempFolderButtonModal.tsx +++ b/invokeai/frontend/web/src/features/system/components/ClearTempFolderButtonModal.tsx @@ -1,4 +1,4 @@ -import { emptyTempFolder } from 'app/socketio/actions'; +// import { emptyTempFolder } from 'app/socketio/actions'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIAlertDialog from 'common/components/IAIAlertDialog'; import IAIButton from 'common/components/IAIButton'; diff --git a/invokeai/frontend/web/src/features/system/components/ModelManager/AddCheckpointModel.tsx b/invokeai/frontend/web/src/features/system/components/ModelManager/AddCheckpointModel.tsx index 71d2b68a86..bb5db0302d 100644 --- a/invokeai/frontend/web/src/features/system/components/ModelManager/AddCheckpointModel.tsx +++ b/invokeai/frontend/web/src/features/system/components/ModelManager/AddCheckpointModel.tsx @@ -17,7 +17,7 @@ import React from 'react'; import SearchModels from './SearchModels'; -import { addNewModel } from 'app/socketio/actions'; +// import { addNewModel } from 'app/socketio/actions'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; diff --git a/invokeai/frontend/web/src/features/system/components/ModelManager/AddDiffusersModel.tsx b/invokeai/frontend/web/src/features/system/components/ModelManager/AddDiffusersModel.tsx index 5a22472fc4..cb3af5f176 100644 --- a/invokeai/frontend/web/src/features/system/components/ModelManager/AddDiffusersModel.tsx +++ b/invokeai/frontend/web/src/features/system/components/ModelManager/AddDiffusersModel.tsx @@ -8,7 +8,7 @@ import { VStack, } from '@chakra-ui/react'; import { InvokeDiffusersModelConfigProps } from 'app/types/invokeai'; -import { addNewModel } from 'app/socketio/actions'; +// import { addNewModel } from 'app/socketio/actions'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIButton from 'common/components/IAIButton'; import IAIInput from 'common/components/IAIInput'; diff --git a/invokeai/frontend/web/src/features/system/components/ModelManager/CheckpointModelEdit.tsx b/invokeai/frontend/web/src/features/system/components/ModelManager/CheckpointModelEdit.tsx index 3523e6fab7..b860a0848c 100644 --- a/invokeai/frontend/web/src/features/system/components/ModelManager/CheckpointModelEdit.tsx +++ b/invokeai/frontend/web/src/features/system/components/ModelManager/CheckpointModelEdit.tsx @@ -17,7 +17,7 @@ import { VStack, } from '@chakra-ui/react'; -import { addNewModel } from 'app/socketio/actions'; +// import { addNewModel } from 'app/socketio/actions'; import { Field, Formik } from 'formik'; import { useTranslation } from 'react-i18next'; diff --git a/invokeai/frontend/web/src/features/system/components/ModelManager/DiffusersModelEdit.tsx b/invokeai/frontend/web/src/features/system/components/ModelManager/DiffusersModelEdit.tsx index f996d5a5d6..81998e4976 100644 --- a/invokeai/frontend/web/src/features/system/components/ModelManager/DiffusersModelEdit.tsx +++ b/invokeai/frontend/web/src/features/system/components/ModelManager/DiffusersModelEdit.tsx @@ -9,7 +9,7 @@ import { systemSelector } from 'features/system/store/systemSelectors'; import { Flex, FormControl, FormLabel, Text, VStack } from '@chakra-ui/react'; -import { addNewModel } from 'app/socketio/actions'; +// import { addNewModel } from 'app/socketio/actions'; import { Field, Formik } from 'formik'; import { useTranslation } from 'react-i18next'; diff --git a/invokeai/frontend/web/src/features/system/components/ModelManager/MergeModels.tsx b/invokeai/frontend/web/src/features/system/components/ModelManager/MergeModels.tsx index 47e9277a59..6ba148cac4 100644 --- a/invokeai/frontend/web/src/features/system/components/ModelManager/MergeModels.tsx +++ b/invokeai/frontend/web/src/features/system/components/ModelManager/MergeModels.tsx @@ -13,7 +13,7 @@ import { Tooltip, useDisclosure, } from '@chakra-ui/react'; -import { mergeDiffusersModels } from 'app/socketio/actions'; +// import { mergeDiffusersModels } from 'app/socketio/actions'; import { RootState } from 'app/store/store'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIButton from 'common/components/IAIButton'; diff --git a/invokeai/frontend/web/src/features/system/components/ModelManager/ModelConvert.tsx b/invokeai/frontend/web/src/features/system/components/ModelManager/ModelConvert.tsx index 3a5aa1264b..820ad546b3 100644 --- a/invokeai/frontend/web/src/features/system/components/ModelManager/ModelConvert.tsx +++ b/invokeai/frontend/web/src/features/system/components/ModelManager/ModelConvert.tsx @@ -7,7 +7,7 @@ import { UnorderedList, Tooltip, } from '@chakra-ui/react'; -import { convertToDiffusers } from 'app/socketio/actions'; +// import { convertToDiffusers } from 'app/socketio/actions'; import { RootState } from 'app/store/store'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIAlertDialog from 'common/components/IAIAlertDialog'; diff --git a/invokeai/frontend/web/src/features/system/components/ModelManager/ModelListItem.tsx b/invokeai/frontend/web/src/features/system/components/ModelManager/ModelListItem.tsx index 47d139cc8f..aa9f87816c 100644 --- a/invokeai/frontend/web/src/features/system/components/ModelManager/ModelListItem.tsx +++ b/invokeai/frontend/web/src/features/system/components/ModelManager/ModelListItem.tsx @@ -1,7 +1,7 @@ import { DeleteIcon, EditIcon } from '@chakra-ui/icons'; import { Box, Button, Flex, Spacer, Text, Tooltip } from '@chakra-ui/react'; import { ModelStatus } from 'app/types/invokeai'; -import { deleteModel, requestModelChange } from 'app/socketio/actions'; +// import { deleteModel, requestModelChange } from 'app/socketio/actions'; import { RootState } from 'app/store/store'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIAlertDialog from 'common/components/IAIAlertDialog'; diff --git a/invokeai/frontend/web/src/features/system/components/ModelManager/SearchModels.tsx b/invokeai/frontend/web/src/features/system/components/ModelManager/SearchModels.tsx index a7867efd5b..3a99997ac8 100644 --- a/invokeai/frontend/web/src/features/system/components/ModelManager/SearchModels.tsx +++ b/invokeai/frontend/web/src/features/system/components/ModelManager/SearchModels.tsx @@ -20,7 +20,7 @@ import { useTranslation } from 'react-i18next'; import { FaSearch, FaTrash } from 'react-icons/fa'; -import { addNewModel, searchForModels } from 'app/socketio/actions'; +// import { addNewModel, searchForModels } from 'app/socketio/actions'; import { setFoundModels, setSearchFolder, diff --git a/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsModal.tsx b/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsModal.tsx index a806ef262b..5cadae68be 100644 --- a/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsModal.tsx +++ b/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsModal.tsx @@ -1,7 +1,6 @@ import { ChakraProps, Flex, - Grid, Heading, Modal, ModalBody, @@ -14,22 +13,16 @@ import { useDisclosure, } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; -import { IN_PROGRESS_IMAGE_TYPES } from 'app/constants'; -import { RootState } from 'app/store/store'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIButton from 'common/components/IAIButton'; -import IAINumberInput from 'common/components/IAINumberInput'; import IAISelect from 'common/components/IAISelect'; import IAISwitch from 'common/components/IAISwitch'; import { systemSelector } from 'features/system/store/systemSelectors'; import { consoleLogLevelChanged, - InProgressImageType, setEnableImageDebugging, - setSaveIntermediatesInterval, setShouldConfirmOnDelete, setShouldDisplayGuides, - setShouldDisplayInProgressType, shouldLogToConsoleChanged, SystemState, } from 'features/system/store/systemSlice'; @@ -39,23 +32,19 @@ import { setShouldUseSliders, } from 'features/ui/store/uiSlice'; import { UIState } from 'features/ui/store/uiTypes'; -import { isEqual, map } from 'lodash-es'; +import { isEqual } from 'lodash-es'; import { persistor } from 'app/store/persistor'; import { ChangeEvent, cloneElement, ReactElement, useCallback } from 'react'; import { useTranslation } from 'react-i18next'; -import { InvokeLogLevel, VALID_LOG_LEVELS } from 'app/logging/useLogger'; +import { VALID_LOG_LEVELS } from 'app/logging/useLogger'; import { LogLevelName } from 'roarr'; -import { F } from 'ts-toolbelt'; const selector = createSelector( [systemSelector, uiSelector], (system: SystemState, ui: UIState) => { const { - shouldDisplayInProgressType, shouldConfirmOnDelete, shouldDisplayGuides, - model_list, - saveIntermediatesInterval, enableImageDebugging, consoleLogLevel, shouldLogToConsole, @@ -64,11 +53,8 @@ const selector = createSelector( const { shouldUseCanvasBetaLayout, shouldUseSliders } = ui; return { - shouldDisplayInProgressType, shouldConfirmOnDelete, shouldDisplayGuides, - models: map(model_list, (_model, key) => key), - saveIntermediatesInterval, enableImageDebugging, shouldUseCanvasBetaLayout, shouldUseSliders, @@ -104,8 +90,6 @@ const SettingsModal = ({ children }: SettingsModalProps) => { const dispatch = useAppDispatch(); const { t } = useTranslation(); - const steps = useAppSelector((state: RootState) => state.generation.steps); - const { isOpen: isSettingsModalOpen, onOpen: onSettingsModalOpen, @@ -119,10 +103,8 @@ const SettingsModal = ({ children }: SettingsModalProps) => { } = useDisclosure(); const { - shouldDisplayInProgressType, shouldConfirmOnDelete, shouldDisplayGuides, - saveIntermediatesInterval, enableImageDebugging, shouldUseCanvasBetaLayout, shouldUseSliders, @@ -134,18 +116,12 @@ const SettingsModal = ({ children }: SettingsModalProps) => { * Resets localstorage, then opens a secondary modal informing user to * refresh their browser. * */ - const handleClickResetWebUI = () => { + const handleClickResetWebUI = useCallback(() => { persistor.purge().then(() => { onSettingsModalClose(); onRefreshModalOpen(); }); - }; - - const handleChangeIntermediateSteps = (value: number) => { - if (value > steps) value = steps; - if (value < 1) value = 1; - dispatch(setSaveIntermediatesInterval(value)); - }; + }, [onSettingsModalClose, onRefreshModalOpen]); const handleLogLevelChanged = useCallback( (e: ChangeEvent) => { @@ -182,32 +158,6 @@ const SettingsModal = ({ children }: SettingsModalProps) => { {t('settings.general')} - ) => - dispatch( - setShouldDisplayInProgressType( - e.target.value as InProgressImageType - ) - ) - } - /> - {shouldDisplayInProgressType === 'full-res' && ( - - )} { + (system) => { return { isConnected: system.isConnected, isProcessing: system.isProcessing, currentIteration: system.currentIteration, totalIterations: system.totalIterations, currentStatus: system.currentStatus, - hasError: system.hasError, - wasErrorSeen: system.wasErrorSeen, }; }, { @@ -31,15 +28,12 @@ const StatusIndicator = () => { currentIteration, totalIterations, currentStatus, - hasError, - wasErrorSeen, } = useAppSelector(statusIndicatorSelector); - const dispatch = useAppDispatch(); const { t } = useTranslation(); let statusIdentifier; - if (isConnected && !hasError) { + if (isConnected) { statusIdentifier = 'ok'; } else { statusIdentifier = 'error'; @@ -60,34 +54,16 @@ const StatusIndicator = () => { } } - const tooltipLabel = - hasError && !wasErrorSeen - ? 'Click to clear, check logs for details' - : undefined; - - const statusIndicatorCursor = - hasError && !wasErrorSeen ? 'pointer' : 'initial'; - - const handleClickStatusIndicator = () => { - if (hasError || !wasErrorSeen) { - dispatch(errorSeen()); - } - }; - return ( - - - {t(statusMessage as keyof typeof t)} - - + + {t(statusMessage as keyof typeof t)} + ); }; diff --git a/invokeai/frontend/web/src/features/system/store/systemSlice.ts b/invokeai/frontend/web/src/features/system/store/systemSlice.ts index 84176bd096..6773314b6a 100644 --- a/invokeai/frontend/web/src/features/system/store/systemSlice.ts +++ b/invokeai/frontend/web/src/features/system/store/systemSlice.ts @@ -23,33 +23,14 @@ import { parsedOpenAPISchema } from 'features/nodes/store/nodesSlice'; import { LogLevelName } from 'roarr'; import { InvokeLogLevel } from 'app/logging/useLogger'; -export type LogLevel = 'info' | 'warning' | 'error'; - -export interface LogEntry { - timestamp: string; - level: LogLevel; - message: string; -} - -export interface Log { - [index: number]: LogEntry; -} - -export type InProgressImageType = 'none' | 'full-res' | 'latents'; - export type CancelType = 'immediate' | 'scheduled'; -export interface SystemState - extends InvokeAI.SystemStatus, - InvokeAI.SystemConfig { - shouldDisplayInProgressType: InProgressImageType; - shouldShowLogViewer: boolean; +export interface SystemState { isGFPGANAvailable: boolean; isESRGANAvailable: boolean; isConnected: boolean; - socketId: string; + isProcessing: boolean; shouldConfirmOnDelete: boolean; - openAccordions: ExpandedIndex; currentStep: number; totalSteps: number; currentIteration: number; @@ -57,18 +38,12 @@ export interface SystemState currentStatus: string; currentStatusHasSteps: boolean; shouldDisplayGuides: boolean; - wasErrorSeen: boolean; isCancelable: boolean; - saveIntermediatesInterval: number; enableImageDebugging: boolean; toastQueue: UseToastOptions[]; searchFolder: string | null; foundModels: InvokeAI.FoundModel[] | null; openModel: string | null; - cancelOptions: { - cancelType: CancelType; - cancelAfter: number | null; - }; /** * The current progress image */ @@ -107,14 +82,10 @@ export interface SystemState const initialSystemState: SystemState = { isConnected: false, isProcessing: false, - shouldShowLogViewer: false, - shouldDisplayInProgressType: 'latents', shouldDisplayGuides: true, isGFPGANAvailable: true, isESRGANAvailable: true, - socketId: '', shouldConfirmOnDelete: true, - openAccordions: [0], currentStep: 0, totalSteps: 0, currentIteration: 0, @@ -123,26 +94,12 @@ const initialSystemState: SystemState = { ? i18n.t('common.statusDisconnected') : 'Disconnected', currentStatusHasSteps: false, - model: '', - model_id: '', - model_hash: '', - app_id: '', - app_version: '', - model_list: {}, - infill_methods: [], - hasError: false, - wasErrorSeen: true, isCancelable: true, - saveIntermediatesInterval: 5, enableImageDebugging: false, toastQueue: [], searchFolder: null, foundModels: null, openModel: null, - cancelOptions: { - cancelType: 'immediate', - cancelAfter: null, - }, progressImage: null, sessionId: null, cancelType: 'immediate', @@ -158,23 +115,13 @@ export const systemSlice = createSlice({ name: 'system', initialState: initialSystemState, reducers: { - setShouldDisplayInProgressType: ( - state, - action: PayloadAction - ) => { - state.shouldDisplayInProgressType = action.payload; - }, setIsProcessing: (state, action: PayloadAction) => { state.isProcessing = action.payload; }, setCurrentStatus: (state, action: PayloadAction) => { state.currentStatus = action.payload; }, - setSystemStatus: (state, action: PayloadAction) => { - return { ...state, ...action.payload }; - }, errorOccurred: (state) => { - state.hasError = true; state.isProcessing = false; state.isCancelable = true; state.currentStep = 0; @@ -183,17 +130,6 @@ export const systemSlice = createSlice({ state.totalIterations = 0; state.currentStatusHasSteps = false; state.currentStatus = i18n.t('common.statusError'); - state.wasErrorSeen = false; - }, - errorSeen: (state) => { - state.hasError = false; - state.wasErrorSeen = true; - state.currentStatus = state.isConnected - ? i18n.t('common.statusConnected') - : i18n.t('common.statusDisconnected'); - }, - setShouldShowLogViewer: (state, action: PayloadAction) => { - state.shouldShowLogViewer = action.payload; }, setIsConnected: (state, action: PayloadAction) => { state.isConnected = action.payload; @@ -204,23 +140,10 @@ export const systemSlice = createSlice({ state.currentIteration = 0; state.totalIterations = 0; state.currentStatusHasSteps = false; - state.hasError = false; - }, - setSocketId: (state, action: PayloadAction) => { - state.socketId = action.payload; }, setShouldConfirmOnDelete: (state, action: PayloadAction) => { state.shouldConfirmOnDelete = action.payload; }, - setOpenAccordions: (state, action: PayloadAction) => { - state.openAccordions = action.payload; - }, - setSystemConfig: (state, action: PayloadAction) => { - return { - ...state, - ...action.payload, - }; - }, setShouldDisplayGuides: (state, action: PayloadAction) => { state.shouldDisplayGuides = action.payload; }, @@ -244,12 +167,6 @@ export const systemSlice = createSlice({ state.currentStatusHasSteps = false; state.currentStatus = i18n.t('common.statusPreparing'); }, - setModelList: ( - state, - action: PayloadAction> - ) => { - state.model_list = action.payload; - }, setIsCancelable: (state, action: PayloadAction) => { state.isCancelable = action.payload; }, @@ -271,9 +188,6 @@ export const systemSlice = createSlice({ state.isProcessing = true; state.currentStatusHasSteps = false; }, - setSaveIntermediatesInterval: (state, action: PayloadAction) => { - state.saveIntermediatesInterval = action.payload; - }, setEnableImageDebugging: (state, action: PayloadAction) => { state.enableImageDebugging = action.payload; }, @@ -300,12 +214,6 @@ export const systemSlice = createSlice({ setOpenModel: (state, action: PayloadAction) => { state.openModel = action.payload; }, - setCancelType: (state, action: PayloadAction) => { - state.cancelOptions.cancelType = action.payload; - }, - setCancelAfter: (state, action: PayloadAction) => { - state.cancelOptions.cancelAfter = action.payload; - }, /** * A cancel was scheduled */ @@ -420,7 +328,6 @@ export const systemSlice = createSlice({ builder.addCase(invocationError, (state, action) => { const { data, timestamp } = action.payload; - state.wasErrorSeen = true; state.progressImage = null; state.isProcessing = false; @@ -479,26 +386,17 @@ export const systemSlice = createSlice({ }); export const { - setShouldDisplayInProgressType, setIsProcessing, - setShouldShowLogViewer, setIsConnected, - setSocketId, setShouldConfirmOnDelete, - setOpenAccordions, - setSystemStatus, setCurrentStatus, - setSystemConfig, setShouldDisplayGuides, processingCanceled, errorOccurred, - errorSeen, - setModelList, setIsCancelable, modelChangeRequested, modelConvertRequested, modelMergingRequested, - setSaveIntermediatesInterval, setEnableImageDebugging, generationRequested, addToast, @@ -507,8 +405,6 @@ export const { setSearchFolder, setFoundModels, setOpenModel, - setCancelType, - setCancelAfter, cancelScheduled, scheduledCancelAborted, cancelTypeChanged, diff --git a/invokeai/frontend/web/src/services/types/guards.ts b/invokeai/frontend/web/src/services/types/guards.ts index 5a9d891395..72cf1108fb 100644 --- a/invokeai/frontend/web/src/services/types/guards.ts +++ b/invokeai/frontend/web/src/services/types/guards.ts @@ -1,3 +1,5 @@ +import { Image } from 'app/types/invokeai'; +import { get, isObject, isString } from 'lodash-es'; import { GraphExecutionState, GraphInvocationOutput, @@ -6,6 +8,8 @@ import { PromptOutput, IterateInvocationOutput, CollectInvocationOutput, + ImageType, + ImageField, } from 'services/api'; export const isImageOutput = ( @@ -31,3 +35,16 @@ export const isIterateOutput = ( export const isCollectOutput = ( output: GraphExecutionState['results'][string] ): output is CollectInvocationOutput => output.type === 'collect_output'; + +export const isImageType = (t: unknown): t is ImageType => + isString(t) && ['results', 'uploads', 'intermediates'].includes(t); + +export const isImage = (image: unknown): image is Image => + isObject(image) && + isString(get(image, 'name')) && + isImageType(get(image, 'type')); + +export const isImageField = (imageField: unknown): imageField is ImageField => + isObject(imageField) && + isString(get(imageField, 'image_name')) && + isImageType(get(imageField, 'image_type')); From adaecada20bb8960730ab34b2e23f4b3e99cd3c1 Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Sun, 30 Apr 2023 01:11:54 +1000 Subject: [PATCH 43/68] fix(ui): fix current image seed button --- .../gallery/components/CurrentImageButtons.tsx | 2 +- .../features/parameters/hooks/useParameters.ts | 15 +++++++-------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/invokeai/frontend/web/src/features/gallery/components/CurrentImageButtons.tsx b/invokeai/frontend/web/src/features/gallery/components/CurrentImageButtons.tsx index a30d8bcac1..51de6bea2e 100644 --- a/invokeai/frontend/web/src/features/gallery/components/CurrentImageButtons.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/CurrentImageButtons.tsx @@ -510,7 +510,7 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => { icon={} tooltip={`${t('parameters.useSeed')} (S)`} aria-label={`${t('parameters.useSeed')} (S)`} - isDisabled={!image?.metadata?.sd_metadata?.seed} + isDisabled={!image?.metadata?.invokeai?.node?.seed} onClick={handleUseSeed} /> diff --git a/invokeai/frontend/web/src/features/parameters/hooks/useParameters.ts b/invokeai/frontend/web/src/features/parameters/hooks/useParameters.ts index ac4aa83098..7c45f159b2 100644 --- a/invokeai/frontend/web/src/features/parameters/hooks/useParameters.ts +++ b/invokeai/frontend/web/src/features/parameters/hooks/useParameters.ts @@ -1,4 +1,4 @@ -import { useToast } from '@chakra-ui/react'; +import { UseToastOptions, useToast } from '@chakra-ui/react'; import { useAppDispatch } from 'app/store/storeHooks'; import { isFinite, isString } from 'lodash-es'; import { useCallback } from 'react'; @@ -51,7 +51,7 @@ export const useParameters = () => { toast({ title: t('toast.seedNotSet'), description: t('toast.seedNotSetDesc'), - status: 'error', + status: 'warning', duration: 2500, isClosable: true, }); @@ -61,7 +61,7 @@ export const useParameters = () => { dispatch(setSeed(s)); toast({ title: t('toast.seedSet'), - status: 'success', + status: 'info', duration: 2500, isClosable: true, }); @@ -78,7 +78,7 @@ export const useParameters = () => { toast({ title: t('toast.initialImageNotSet'), description: t('toast.initialImageNotSetDesc'), - status: 'error', + status: 'warning', duration: 2500, isClosable: true, }); @@ -90,7 +90,7 @@ export const useParameters = () => { ); toast({ title: t('toast.initialImageSet'), - status: 'success', + status: 'info', duration: 2500, isClosable: true, }); @@ -107,7 +107,7 @@ export const useParameters = () => { toast({ title: t('toast.imageNotLoaded'), description: t('toast.imageNotLoadedDesc'), - status: 'error', + status: 'warning', duration: 2500, isClosable: true, }); @@ -115,10 +115,9 @@ export const useParameters = () => { } dispatch(initialImageSelected({ name: image.name, type: image.type })); - toast({ title: t('toast.sentToImageToImage'), - status: 'success', + status: 'info', duration: 2500, isClosable: true, }); From 8c2e4700f9152e730462f1ac4d20f9e25ebd128b Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Sun, 30 Apr 2023 13:56:33 +1000 Subject: [PATCH 44/68] feat(ui): persist gallery state --- invokeai/frontend/web/src/app/store/store.ts | 9 ++++----- .../src/features/gallery/store/resultsPersistDenylist.ts | 2 +- .../web/src/features/gallery/store/resultsSlice.ts | 4 ++-- .../src/features/gallery/store/uploadsPersistDenylist.ts | 2 +- .../web/src/features/gallery/store/uploadsSlice.ts | 4 ++-- 5 files changed, 10 insertions(+), 11 deletions(-) diff --git a/invokeai/frontend/web/src/app/store/store.ts b/invokeai/frontend/web/src/app/store/store.ts index 20c0fa8b2a..e9e104dac2 100644 --- a/invokeai/frontend/web/src/app/store/store.ts +++ b/invokeai/frontend/web/src/app/store/store.ts @@ -19,7 +19,6 @@ import hotkeysReducer from 'features/ui/store/hotkeysSlice'; import modelsReducer from 'features/system/store/modelSlice'; import nodesReducer from 'features/nodes/store/nodesSlice'; -import { socketMiddleware } from 'services/events/middleware'; import { canvasDenylist } from 'features/canvas/store/canvasPersistDenylist'; import { galleryDenylist } from 'features/gallery/store/galleryPersistDenylist'; import { generationDenylist } from 'features/parameters/store/generationPersistDenylist'; @@ -29,6 +28,8 @@ import { nodesDenylist } from 'features/nodes/store/nodesPersistDenylist'; import { postprocessingDenylist } from 'features/parameters/store/postprocessingPersistDenylist'; import { systemDenylist } from 'features/system/store/systemPersistDenylist'; import { uiDenylist } from 'features/ui/store/uiPersistDenylist'; +import { resultsDenylist } from 'features/gallery/store/resultsPersistDenylist'; +import { uploadsDenylist } from 'features/gallery/store/uploadsPersistDenylist'; /** * redux-persist provides an easy and reliable way to persist state across reloads. @@ -72,12 +73,10 @@ const rootPersistConfig = getPersistConfig({ ...modelsDenylist, ...nodesDenylist, ...postprocessingDenylist, - // ...resultsDenylist, - 'results', + ...resultsDenylist, ...systemDenylist, ...uiDenylist, - // ...uploadsDenylist, - 'uploads', + ...uploadsDenylist, 'hotkeys', 'config', ], diff --git a/invokeai/frontend/web/src/features/gallery/store/resultsPersistDenylist.ts b/invokeai/frontend/web/src/features/gallery/store/resultsPersistDenylist.ts index ef21f4b7b2..b62a199b33 100644 --- a/invokeai/frontend/web/src/features/gallery/store/resultsPersistDenylist.ts +++ b/invokeai/frontend/web/src/features/gallery/store/resultsPersistDenylist.ts @@ -5,7 +5,7 @@ import { ResultsState } from './resultsSlice'; * * Currently denylisting results slice entirely, see persist config in store.ts */ -const itemsToDenylist: (keyof ResultsState)[] = []; +const itemsToDenylist: (keyof ResultsState)[] = ['isLoading']; export const resultsDenylist = itemsToDenylist.map( (denylistItem) => `results.${denylistItem}` diff --git a/invokeai/frontend/web/src/features/gallery/store/resultsSlice.ts b/invokeai/frontend/web/src/features/gallery/store/resultsSlice.ts index 73da68c031..26af366e03 100644 --- a/invokeai/frontend/web/src/features/gallery/store/resultsSlice.ts +++ b/invokeai/frontend/web/src/features/gallery/store/resultsSlice.ts @@ -65,7 +65,7 @@ const resultsSlice = createSlice({ deserializeImageResponse(image) ); - resultsAdapter.addMany(state, resultImages); + resultsAdapter.setMany(state, resultImages); state.page = page; state.pages = pages; @@ -107,7 +107,7 @@ const resultsSlice = createSlice({ }, }; - resultsAdapter.addOne(state, image); + resultsAdapter.setOne(state, image); } }); diff --git a/invokeai/frontend/web/src/features/gallery/store/uploadsPersistDenylist.ts b/invokeai/frontend/web/src/features/gallery/store/uploadsPersistDenylist.ts index ec4248e99c..6e2ac1c3aa 100644 --- a/invokeai/frontend/web/src/features/gallery/store/uploadsPersistDenylist.ts +++ b/invokeai/frontend/web/src/features/gallery/store/uploadsPersistDenylist.ts @@ -5,7 +5,7 @@ import { UploadsState } from './uploadsSlice'; * * Currently denylisting uploads slice entirely, see persist config in store.ts */ -const itemsToDenylist: (keyof UploadsState)[] = []; +const itemsToDenylist: (keyof UploadsState)[] = ['isLoading']; export const uploadsDenylist = itemsToDenylist.map( (denylistItem) => `uploads.${denylistItem}` diff --git a/invokeai/frontend/web/src/features/gallery/store/uploadsSlice.ts b/invokeai/frontend/web/src/features/gallery/store/uploadsSlice.ts index 04d321d7d9..bb77844f42 100644 --- a/invokeai/frontend/web/src/features/gallery/store/uploadsSlice.ts +++ b/invokeai/frontend/web/src/features/gallery/store/uploadsSlice.ts @@ -53,7 +53,7 @@ const uploadsSlice = createSlice({ const images = items.map((image) => deserializeImageResponse(image)); - uploadsAdapter.addMany(state, images); + uploadsAdapter.setMany(state, images); state.page = page; state.pages = pages; @@ -69,7 +69,7 @@ const uploadsSlice = createSlice({ const uploadedImage = deserializeImageResponse(response); - uploadsAdapter.addOne(state, uploadedImage); + uploadsAdapter.setOne(state, uploadedImage); }); /** From 4150d5306f5f0bcac9e580cef123be28764b7ff9 Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Sun, 30 Apr 2023 13:56:56 +1000 Subject: [PATCH 45/68] chore(ui): regen api client --- .../services/api/core/CancelablePromise.ts | 76 ++++++++++--------- .../frontend/web/src/services/api/index.ts | 4 + .../web/src/services/api/models/Graph.ts | 4 +- .../api/models/LatentsToLatentsInvocation.ts | 12 --- .../api/models/ResizeLatentsInvocation.ts | 37 +++++++++ .../api/models/ScaleLatentsInvocation.ts | 33 ++++++++ .../api/models/TextToLatentsInvocation.ts | 12 --- .../web/src/services/api/schemas/$Graph.ts | 4 + .../schemas/$LatentsToLatentsInvocation.ts | 16 ---- .../api/schemas/$ResizeLatentsInvocation.ts | 44 +++++++++++ .../api/schemas/$ScaleLatentsInvocation.ts | 35 +++++++++ .../api/schemas/$TextToLatentsInvocation.ts | 16 ---- .../services/api/services/SessionsService.ts | 6 +- 13 files changed, 203 insertions(+), 96 deletions(-) create mode 100644 invokeai/frontend/web/src/services/api/models/ResizeLatentsInvocation.ts create mode 100644 invokeai/frontend/web/src/services/api/models/ScaleLatentsInvocation.ts create mode 100644 invokeai/frontend/web/src/services/api/schemas/$ResizeLatentsInvocation.ts create mode 100644 invokeai/frontend/web/src/services/api/schemas/$ScaleLatentsInvocation.ts diff --git a/invokeai/frontend/web/src/services/api/core/CancelablePromise.ts b/invokeai/frontend/web/src/services/api/core/CancelablePromise.ts index b923479fea..a0f92e01b7 100644 --- a/invokeai/frontend/web/src/services/api/core/CancelablePromise.ts +++ b/invokeai/frontend/web/src/services/api/core/CancelablePromise.ts @@ -22,15 +22,13 @@ export interface OnCancel { } export class CancelablePromise implements Promise { - readonly [Symbol.toStringTag]!: string; - - private _isResolved: boolean; - private _isRejected: boolean; - private _isCancelled: boolean; - private readonly _cancelHandlers: (() => void)[]; - private readonly _promise: Promise; - private _resolve?: (value: T | PromiseLike) => void; - private _reject?: (reason?: any) => void; + #isResolved: boolean; + #isRejected: boolean; + #isCancelled: boolean; + readonly #cancelHandlers: (() => void)[]; + readonly #promise: Promise; + #resolve?: (value: T | PromiseLike) => void; + #reject?: (reason?: any) => void; constructor( executor: ( @@ -39,78 +37,82 @@ export class CancelablePromise implements Promise { onCancel: OnCancel ) => void ) { - this._isResolved = false; - this._isRejected = false; - this._isCancelled = false; - this._cancelHandlers = []; - this._promise = new Promise((resolve, reject) => { - this._resolve = resolve; - this._reject = reject; + this.#isResolved = false; + this.#isRejected = false; + this.#isCancelled = false; + this.#cancelHandlers = []; + this.#promise = new Promise((resolve, reject) => { + this.#resolve = resolve; + this.#reject = reject; const onResolve = (value: T | PromiseLike): void => { - if (this._isResolved || this._isRejected || this._isCancelled) { + if (this.#isResolved || this.#isRejected || this.#isCancelled) { return; } - this._isResolved = true; - this._resolve?.(value); + this.#isResolved = true; + this.#resolve?.(value); }; const onReject = (reason?: any): void => { - if (this._isResolved || this._isRejected || this._isCancelled) { + if (this.#isResolved || this.#isRejected || this.#isCancelled) { return; } - this._isRejected = true; - this._reject?.(reason); + this.#isRejected = true; + this.#reject?.(reason); }; const onCancel = (cancelHandler: () => void): void => { - if (this._isResolved || this._isRejected || this._isCancelled) { + if (this.#isResolved || this.#isRejected || this.#isCancelled) { return; } - this._cancelHandlers.push(cancelHandler); + this.#cancelHandlers.push(cancelHandler); }; Object.defineProperty(onCancel, 'isResolved', { - get: (): boolean => this._isResolved, + get: (): boolean => this.#isResolved, }); Object.defineProperty(onCancel, 'isRejected', { - get: (): boolean => this._isRejected, + get: (): boolean => this.#isRejected, }); Object.defineProperty(onCancel, 'isCancelled', { - get: (): boolean => this._isCancelled, + get: (): boolean => this.#isCancelled, }); return executor(onResolve, onReject, onCancel as OnCancel); }); } + get [Symbol.toStringTag]() { + return "Cancellable Promise"; + } + public then( onFulfilled?: ((value: T) => TResult1 | PromiseLike) | null, onRejected?: ((reason: any) => TResult2 | PromiseLike) | null ): Promise { - return this._promise.then(onFulfilled, onRejected); + return this.#promise.then(onFulfilled, onRejected); } public catch( onRejected?: ((reason: any) => TResult | PromiseLike) | null ): Promise { - return this._promise.catch(onRejected); + return this.#promise.catch(onRejected); } public finally(onFinally?: (() => void) | null): Promise { - return this._promise.finally(onFinally); + return this.#promise.finally(onFinally); } public cancel(): void { - if (this._isResolved || this._isRejected || this._isCancelled) { + if (this.#isResolved || this.#isRejected || this.#isCancelled) { return; } - this._isCancelled = true; - if (this._cancelHandlers.length) { + this.#isCancelled = true; + if (this.#cancelHandlers.length) { try { - for (const cancelHandler of this._cancelHandlers) { + for (const cancelHandler of this.#cancelHandlers) { cancelHandler(); } } catch (error) { @@ -118,11 +120,11 @@ export class CancelablePromise implements Promise { return; } } - this._cancelHandlers.length = 0; - this._reject?.(new CancelError('Request aborted')); + this.#cancelHandlers.length = 0; + this.#reject?.(new CancelError('Request aborted')); } public get isCancelled(): boolean { - return this._isCancelled; + return this.#isCancelled; } } diff --git a/invokeai/frontend/web/src/services/api/index.ts b/invokeai/frontend/web/src/services/api/index.ts index f1b84f8465..2a34837715 100644 --- a/invokeai/frontend/web/src/services/api/index.ts +++ b/invokeai/frontend/web/src/services/api/index.ts @@ -58,7 +58,9 @@ export type { PasteImageInvocation } from './models/PasteImageInvocation'; export type { PromptOutput } from './models/PromptOutput'; export type { RandomRangeInvocation } from './models/RandomRangeInvocation'; export type { RangeInvocation } from './models/RangeInvocation'; +export type { ResizeLatentsInvocation } from './models/ResizeLatentsInvocation'; export type { RestoreFaceInvocation } from './models/RestoreFaceInvocation'; +export type { ScaleLatentsInvocation } from './models/ScaleLatentsInvocation'; export type { ShowImageInvocation } from './models/ShowImageInvocation'; export type { SubtractInvocation } from './models/SubtractInvocation'; export type { TextToImageInvocation } from './models/TextToImageInvocation'; @@ -119,7 +121,9 @@ export { $PasteImageInvocation } from './schemas/$PasteImageInvocation'; export { $PromptOutput } from './schemas/$PromptOutput'; export { $RandomRangeInvocation } from './schemas/$RandomRangeInvocation'; export { $RangeInvocation } from './schemas/$RangeInvocation'; +export { $ResizeLatentsInvocation } from './schemas/$ResizeLatentsInvocation'; export { $RestoreFaceInvocation } from './schemas/$RestoreFaceInvocation'; +export { $ScaleLatentsInvocation } from './schemas/$ScaleLatentsInvocation'; export { $ShowImageInvocation } from './schemas/$ShowImageInvocation'; export { $SubtractInvocation } from './schemas/$SubtractInvocation'; export { $TextToImageInvocation } from './schemas/$TextToImageInvocation'; diff --git a/invokeai/frontend/web/src/services/api/models/Graph.ts b/invokeai/frontend/web/src/services/api/models/Graph.ts index 1e590e4ba9..57a9178290 100644 --- a/invokeai/frontend/web/src/services/api/models/Graph.ts +++ b/invokeai/frontend/web/src/services/api/models/Graph.ts @@ -25,7 +25,9 @@ import type { ParamIntInvocation } from './ParamIntInvocation'; import type { PasteImageInvocation } from './PasteImageInvocation'; import type { RandomRangeInvocation } from './RandomRangeInvocation'; import type { RangeInvocation } from './RangeInvocation'; +import type { ResizeLatentsInvocation } from './ResizeLatentsInvocation'; import type { RestoreFaceInvocation } from './RestoreFaceInvocation'; +import type { ScaleLatentsInvocation } from './ScaleLatentsInvocation'; import type { ShowImageInvocation } from './ShowImageInvocation'; import type { SubtractInvocation } from './SubtractInvocation'; import type { TextToImageInvocation } from './TextToImageInvocation'; @@ -40,7 +42,7 @@ export type Graph = { /** * The nodes in this graph */ - nodes?: Record; + nodes?: Record; /** * The connections between nodes and their fields in this graph */ diff --git a/invokeai/frontend/web/src/services/api/models/LatentsToLatentsInvocation.ts b/invokeai/frontend/web/src/services/api/models/LatentsToLatentsInvocation.ts index 8210f01bb6..d04885bf85 100644 --- a/invokeai/frontend/web/src/services/api/models/LatentsToLatentsInvocation.ts +++ b/invokeai/frontend/web/src/services/api/models/LatentsToLatentsInvocation.ts @@ -17,10 +17,6 @@ export type LatentsToLatentsInvocation = { * The prompt to generate an image from */ prompt?: string; - /** - * The seed to use (-1 for a random seed) - */ - seed?: number; /** * The noise to use */ @@ -29,14 +25,6 @@ export type LatentsToLatentsInvocation = { * The number of steps to use to generate the image */ steps?: number; - /** - * The width of the resulting image - */ - width?: number; - /** - * The height of the resulting image - */ - height?: number; /** * The Classifier-Free Guidance, higher values may result in a result closer to the prompt */ diff --git a/invokeai/frontend/web/src/services/api/models/ResizeLatentsInvocation.ts b/invokeai/frontend/web/src/services/api/models/ResizeLatentsInvocation.ts new file mode 100644 index 0000000000..c0fabb4984 --- /dev/null +++ b/invokeai/frontend/web/src/services/api/models/ResizeLatentsInvocation.ts @@ -0,0 +1,37 @@ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ + +import type { LatentsField } from './LatentsField'; + +/** + * Resizes latents to explicit width/height (in pixels). Provided dimensions are floor-divided by 8. + */ +export type ResizeLatentsInvocation = { + /** + * The id of this node. Must be unique among all nodes. + */ + id: string; + type?: 'lresize'; + /** + * The latents to resize + */ + latents?: LatentsField; + /** + * The width to resize to (px) + */ + width: number; + /** + * The height to resize to (px) + */ + height: number; + /** + * The interpolation mode + */ + mode?: 'nearest' | 'linear' | 'bilinear' | 'bicubic' | 'trilinear' | 'area' | 'nearest-exact'; + /** + * Whether or not to antialias (applied in bilinear and bicubic modes only) + */ + antialias?: boolean; +}; + diff --git a/invokeai/frontend/web/src/services/api/models/ScaleLatentsInvocation.ts b/invokeai/frontend/web/src/services/api/models/ScaleLatentsInvocation.ts new file mode 100644 index 0000000000..f398eaf408 --- /dev/null +++ b/invokeai/frontend/web/src/services/api/models/ScaleLatentsInvocation.ts @@ -0,0 +1,33 @@ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ + +import type { LatentsField } from './LatentsField'; + +/** + * Scales latents by a given factor. + */ +export type ScaleLatentsInvocation = { + /** + * The id of this node. Must be unique among all nodes. + */ + id: string; + type?: 'lscale'; + /** + * The latents to scale + */ + latents?: LatentsField; + /** + * The factor by which to scale the latents + */ + scale_factor: number; + /** + * The interpolation mode + */ + mode?: 'nearest' | 'linear' | 'bilinear' | 'bicubic' | 'trilinear' | 'area' | 'nearest-exact'; + /** + * Whether or not to antialias (applied in bilinear and bicubic modes only) + */ + antialias?: boolean; +}; + diff --git a/invokeai/frontend/web/src/services/api/models/TextToLatentsInvocation.ts b/invokeai/frontend/web/src/services/api/models/TextToLatentsInvocation.ts index 63754db163..217b917f18 100644 --- a/invokeai/frontend/web/src/services/api/models/TextToLatentsInvocation.ts +++ b/invokeai/frontend/web/src/services/api/models/TextToLatentsInvocation.ts @@ -17,10 +17,6 @@ export type TextToLatentsInvocation = { * The prompt to generate an image from */ prompt?: string; - /** - * The seed to use (-1 for a random seed) - */ - seed?: number; /** * The noise to use */ @@ -29,14 +25,6 @@ export type TextToLatentsInvocation = { * The number of steps to use to generate the image */ steps?: number; - /** - * The width of the resulting image - */ - width?: number; - /** - * The height of the resulting image - */ - height?: number; /** * The Classifier-Free Guidance, higher values may result in a result closer to the prompt */ diff --git a/invokeai/frontend/web/src/services/api/schemas/$Graph.ts b/invokeai/frontend/web/src/services/api/schemas/$Graph.ts index b431011ba6..6fd8117db8 100644 --- a/invokeai/frontend/web/src/services/api/schemas/$Graph.ts +++ b/invokeai/frontend/web/src/services/api/schemas/$Graph.ts @@ -33,6 +33,10 @@ export const $Graph = { type: 'TextToLatentsInvocation', }, { type: 'LatentsToImageInvocation', + }, { + type: 'ResizeLatentsInvocation', + }, { + type: 'ScaleLatentsInvocation', }, { type: 'AddInvocation', }, { diff --git a/invokeai/frontend/web/src/services/api/schemas/$LatentsToLatentsInvocation.ts b/invokeai/frontend/web/src/services/api/schemas/$LatentsToLatentsInvocation.ts index d27fdc7c1f..b20ee88a52 100644 --- a/invokeai/frontend/web/src/services/api/schemas/$LatentsToLatentsInvocation.ts +++ b/invokeai/frontend/web/src/services/api/schemas/$LatentsToLatentsInvocation.ts @@ -16,12 +16,6 @@ export const $LatentsToLatentsInvocation = { type: 'string', description: `The prompt to generate an image from`, }, - seed: { - type: 'number', - description: `The seed to use (-1 for a random seed)`, - maximum: 4294967295, - minimum: -1, - }, noise: { type: 'all-of', description: `The noise to use`, @@ -33,16 +27,6 @@ export const $LatentsToLatentsInvocation = { type: 'number', description: `The number of steps to use to generate the image`, }, - width: { - type: 'number', - description: `The width of the resulting image`, - multipleOf: 64, - }, - height: { - type: 'number', - description: `The height of the resulting image`, - multipleOf: 64, - }, cfg_scale: { type: 'number', description: `The Classifier-Free Guidance, higher values may result in a result closer to the prompt`, diff --git a/invokeai/frontend/web/src/services/api/schemas/$ResizeLatentsInvocation.ts b/invokeai/frontend/web/src/services/api/schemas/$ResizeLatentsInvocation.ts new file mode 100644 index 0000000000..2609b1a681 --- /dev/null +++ b/invokeai/frontend/web/src/services/api/schemas/$ResizeLatentsInvocation.ts @@ -0,0 +1,44 @@ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +export const $ResizeLatentsInvocation = { + description: `Resizes latents to explicit width/height (in pixels). Provided dimensions are floor-divided by 8.`, + properties: { + id: { + type: 'string', + description: `The id of this node. Must be unique among all nodes.`, + isRequired: true, + }, + type: { + type: 'Enum', + }, + latents: { + type: 'all-of', + description: `The latents to resize`, + contains: [{ + type: 'LatentsField', + }], + }, + width: { + type: 'number', + description: `The width to resize to (px)`, + isRequired: true, + minimum: 64, + multipleOf: 8, + }, + height: { + type: 'number', + description: `The height to resize to (px)`, + isRequired: true, + minimum: 64, + multipleOf: 8, + }, + mode: { + type: 'Enum', + }, + antialias: { + type: 'boolean', + description: `Whether or not to antialias (applied in bilinear and bicubic modes only)`, + }, + }, +} as const; diff --git a/invokeai/frontend/web/src/services/api/schemas/$ScaleLatentsInvocation.ts b/invokeai/frontend/web/src/services/api/schemas/$ScaleLatentsInvocation.ts new file mode 100644 index 0000000000..8d4d15e2e8 --- /dev/null +++ b/invokeai/frontend/web/src/services/api/schemas/$ScaleLatentsInvocation.ts @@ -0,0 +1,35 @@ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +export const $ScaleLatentsInvocation = { + description: `Scales latents by a given factor.`, + properties: { + id: { + type: 'string', + description: `The id of this node. Must be unique among all nodes.`, + isRequired: true, + }, + type: { + type: 'Enum', + }, + latents: { + type: 'all-of', + description: `The latents to scale`, + contains: [{ + type: 'LatentsField', + }], + }, + scale_factor: { + type: 'number', + description: `The factor by which to scale the latents`, + isRequired: true, + }, + mode: { + type: 'Enum', + }, + antialias: { + type: 'boolean', + description: `Whether or not to antialias (applied in bilinear and bicubic modes only)`, + }, + }, +} as const; diff --git a/invokeai/frontend/web/src/services/api/schemas/$TextToLatentsInvocation.ts b/invokeai/frontend/web/src/services/api/schemas/$TextToLatentsInvocation.ts index 7b6dd155ca..06376824c6 100644 --- a/invokeai/frontend/web/src/services/api/schemas/$TextToLatentsInvocation.ts +++ b/invokeai/frontend/web/src/services/api/schemas/$TextToLatentsInvocation.ts @@ -16,12 +16,6 @@ export const $TextToLatentsInvocation = { type: 'string', description: `The prompt to generate an image from`, }, - seed: { - type: 'number', - description: `The seed to use (-1 for a random seed)`, - maximum: 4294967295, - minimum: -1, - }, noise: { type: 'all-of', description: `The noise to use`, @@ -33,16 +27,6 @@ export const $TextToLatentsInvocation = { type: 'number', description: `The number of steps to use to generate the image`, }, - width: { - type: 'number', - description: `The width of the resulting image`, - multipleOf: 64, - }, - height: { - type: 'number', - description: `The height of the resulting image`, - multipleOf: 64, - }, cfg_scale: { type: 'number', description: `The Classifier-Free Guidance, higher values may result in a result closer to the prompt`, diff --git a/invokeai/frontend/web/src/services/api/services/SessionsService.ts b/invokeai/frontend/web/src/services/api/services/SessionsService.ts index 269092c6d9..dad455fc80 100644 --- a/invokeai/frontend/web/src/services/api/services/SessionsService.ts +++ b/invokeai/frontend/web/src/services/api/services/SessionsService.ts @@ -27,7 +27,9 @@ import type { ParamIntInvocation } from '../models/ParamIntInvocation'; import type { PasteImageInvocation } from '../models/PasteImageInvocation'; import type { RandomRangeInvocation } from '../models/RandomRangeInvocation'; import type { RangeInvocation } from '../models/RangeInvocation'; +import type { ResizeLatentsInvocation } from '../models/ResizeLatentsInvocation'; import type { RestoreFaceInvocation } from '../models/RestoreFaceInvocation'; +import type { ScaleLatentsInvocation } from '../models/ScaleLatentsInvocation'; import type { ShowImageInvocation } from '../models/ShowImageInvocation'; import type { SubtractInvocation } from '../models/SubtractInvocation'; import type { TextToImageInvocation } from '../models/TextToImageInvocation'; @@ -142,7 +144,7 @@ export class SessionsService { * The id of the session */ sessionId: string, - requestBody: (LoadImageInvocation | ShowImageInvocation | CropImageInvocation | PasteImageInvocation | MaskFromAlphaInvocation | BlurInvocation | LerpInvocation | InverseLerpInvocation | NoiseInvocation | TextToLatentsInvocation | LatentsToImageInvocation | AddInvocation | SubtractInvocation | MultiplyInvocation | DivideInvocation | ParamIntInvocation | CvInpaintInvocation | RangeInvocation | RandomRangeInvocation | UpscaleInvocation | RestoreFaceInvocation | TextToImageInvocation | GraphInvocation | IterateInvocation | CollectInvocation | LatentsToLatentsInvocation | ImageToImageInvocation | InpaintInvocation), + requestBody: (LoadImageInvocation | ShowImageInvocation | CropImageInvocation | PasteImageInvocation | MaskFromAlphaInvocation | BlurInvocation | LerpInvocation | InverseLerpInvocation | NoiseInvocation | TextToLatentsInvocation | LatentsToImageInvocation | ResizeLatentsInvocation | ScaleLatentsInvocation | AddInvocation | SubtractInvocation | MultiplyInvocation | DivideInvocation | ParamIntInvocation | CvInpaintInvocation | RangeInvocation | RandomRangeInvocation | UpscaleInvocation | RestoreFaceInvocation | TextToImageInvocation | GraphInvocation | IterateInvocation | CollectInvocation | LatentsToLatentsInvocation | ImageToImageInvocation | InpaintInvocation), }): CancelablePromise { return __request(OpenAPI, { method: 'POST', @@ -179,7 +181,7 @@ export class SessionsService { * The path to the node in the graph */ nodePath: string, - requestBody: (LoadImageInvocation | ShowImageInvocation | CropImageInvocation | PasteImageInvocation | MaskFromAlphaInvocation | BlurInvocation | LerpInvocation | InverseLerpInvocation | NoiseInvocation | TextToLatentsInvocation | LatentsToImageInvocation | AddInvocation | SubtractInvocation | MultiplyInvocation | DivideInvocation | ParamIntInvocation | CvInpaintInvocation | RangeInvocation | RandomRangeInvocation | UpscaleInvocation | RestoreFaceInvocation | TextToImageInvocation | GraphInvocation | IterateInvocation | CollectInvocation | LatentsToLatentsInvocation | ImageToImageInvocation | InpaintInvocation), + requestBody: (LoadImageInvocation | ShowImageInvocation | CropImageInvocation | PasteImageInvocation | MaskFromAlphaInvocation | BlurInvocation | LerpInvocation | InverseLerpInvocation | NoiseInvocation | TextToLatentsInvocation | LatentsToImageInvocation | ResizeLatentsInvocation | ScaleLatentsInvocation | AddInvocation | SubtractInvocation | MultiplyInvocation | DivideInvocation | ParamIntInvocation | CvInpaintInvocation | RangeInvocation | RandomRangeInvocation | UpscaleInvocation | RestoreFaceInvocation | TextToImageInvocation | GraphInvocation | IterateInvocation | CollectInvocation | LatentsToLatentsInvocation | ImageToImageInvocation | InpaintInvocation), }): CancelablePromise { return __request(OpenAPI, { method: 'PUT', From 5b558af2b3ba39b0195848905a4ba3f6567ee634 Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Sun, 30 Apr 2023 13:57:33 +1000 Subject: [PATCH 46/68] fix(ui): fix metadata viewer scroll --- .../components/ImageMetaDataViewer/ImageMetadataViewer.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/invokeai/frontend/web/src/features/gallery/components/ImageMetaDataViewer/ImageMetadataViewer.tsx b/invokeai/frontend/web/src/features/gallery/components/ImageMetaDataViewer/ImageMetadataViewer.tsx index 073521344d..eedbf63081 100644 --- a/invokeai/frontend/web/src/features/gallery/components/ImageMetaDataViewer/ImageMetadataViewer.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/ImageMetaDataViewer/ImageMetadataViewer.tsx @@ -159,6 +159,7 @@ const ImageMetadataViewer = memo(({ image }: ImageMetadataViewerProps) => { _dark: { bg: 'blackAlpha.600', }, + overflow: 'scroll', }} > From deae5fbaec7f18b38ca81180e144828fa54c79da Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Sun, 30 Apr 2023 13:58:19 +1000 Subject: [PATCH 47/68] fix(ui): socket event types --- .../frontend/web/src/services/events/types.ts | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/invokeai/frontend/web/src/services/events/types.ts b/invokeai/frontend/web/src/services/events/types.ts index 573dc0ac3a..2577b7fe92 100644 --- a/invokeai/frontend/web/src/services/events/types.ts +++ b/invokeai/frontend/web/src/services/events/types.ts @@ -1,4 +1,4 @@ -import { Graph, GraphExecutionState } from '../api'; +import { Graph, GraphExecutionState, InvokeAIMetadata } from '../api'; /** * A progress image, we get one for each step in the generation @@ -17,6 +17,12 @@ export type AnyInvocation = NonNullable[string]; export type AnyResult = GraphExecutionState['results'][string]; +export type BaseNode = { + id: string; + type: string; + [key: string]: NonNullable[string]; +}; + /** * A `generator_progress` socket.io event. * @@ -24,7 +30,7 @@ export type AnyResult = GraphExecutionState['results'][string]; */ export type GeneratorProgressEvent = { graph_execution_state_id: string; - node: AnyInvocation; + node: BaseNode; source_node_id: string; progress_image?: ProgressImage; step: number; @@ -40,7 +46,7 @@ export type GeneratorProgressEvent = { */ export type InvocationCompleteEvent = { graph_execution_state_id: string; - node: AnyInvocation; + node: BaseNode; source_node_id: string; result: AnyResult; }; @@ -52,7 +58,7 @@ export type InvocationCompleteEvent = { */ export type InvocationErrorEvent = { graph_execution_state_id: string; - node: AnyInvocation; + node: BaseNode; source_node_id: string; error: string; }; @@ -64,7 +70,7 @@ export type InvocationErrorEvent = { */ export type InvocationStartedEvent = { graph_execution_state_id: string; - node: AnyInvocation; + node: BaseNode; source_node_id: string; }; From c8fe12cd91de76a2c91039710711c589fa04a180 Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Sun, 30 Apr 2023 15:40:47 +1000 Subject: [PATCH 48/68] feat(ui): init image tweaks --- .../common/components/ImageToImageOverlay.tsx | 25 ++----------------- .../components/ImageToImageSettingsHeader.tsx | 25 ++----------------- .../ImageToImage/InitialImagePreview.tsx | 11 +++----- .../components/AnimatedImageToImagePanel.tsx | 6 ++--- 4 files changed, 10 insertions(+), 57 deletions(-) diff --git a/invokeai/frontend/web/src/common/components/ImageToImageOverlay.tsx b/invokeai/frontend/web/src/common/components/ImageToImageOverlay.tsx index a78ced06ea..45a45e37d3 100644 --- a/invokeai/frontend/web/src/common/components/ImageToImageOverlay.tsx +++ b/invokeai/frontend/web/src/common/components/ImageToImageOverlay.tsx @@ -1,32 +1,11 @@ -import { Badge, Box, ButtonGroup, Flex } from '@chakra-ui/react'; -import { RootState } from 'app/store/store'; -import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; -import { clearInitialImage } from 'features/parameters/store/generationSlice'; -import { useCallback } from 'react'; -import IAIIconButton from 'common/components/IAIIconButton'; -import { FaUndo, FaUpload } from 'react-icons/fa'; -import { useTranslation } from 'react-i18next'; +import { Badge, Box, Flex } from '@chakra-ui/react'; import { Image } from 'app/types/invokeai'; type ImageToImageOverlayProps = { - setIsLoaded: (isLoaded: boolean) => void; image: Image; }; -const ImageToImageOverlay = ({ - setIsLoaded, - image, -}: ImageToImageOverlayProps) => { - const isImageToImageEnabled = useAppSelector( - (state: RootState) => state.generation.isImageToImageEnabled - ); - const dispatch = useAppDispatch(); - const { t } = useTranslation(); - const handleResetInitialImage = useCallback(() => { - dispatch(clearInitialImage()); - setIsLoaded(false); - }, [dispatch, setIsLoaded]); - +const ImageToImageOverlay = ({ image }: ImageToImageOverlayProps) => { return ( { - const isImageToImageEnabled = useAppSelector( - (state: RootState) => state.generation.isImageToImageEnabled - ); const dispatch = useAppDispatch(); const { t } = useTranslation(); diff --git a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/ImageToImage/InitialImagePreview.tsx b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/ImageToImage/InitialImagePreview.tsx index 8a91602ada..9682d2eb0b 100644 --- a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/ImageToImage/InitialImagePreview.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/ImageToImage/InitialImagePreview.tsx @@ -17,7 +17,7 @@ import { ImageType } from 'services/api'; import ImageToImageOverlay from 'common/components/ImageToImageOverlay'; import { initialImageSelector } from 'features/parameters/store/generationSelectors'; -const initialImagePreviewSelector = createSelector( +const selector = createSelector( [initialImageSelector], (initialImage) => { return { @@ -31,7 +31,7 @@ const InitialImagePreview = () => { const isImageToImageEnabled = useAppSelector( (state: RootState) => state.generation.isImageToImageEnabled ); - const { initialImage } = useAppSelector(initialImagePreviewSelector); + const { initialImage } = useAppSelector(selector); const { getUrl } = useGetUrl(); const dispatch = useAppDispatch(); const { t } = useTranslation(); @@ -113,12 +113,7 @@ const InitialImagePreview = () => { } /> - {isLoaded && ( - - )} + {isLoaded && } )} {!initialImage?.url && } diff --git a/invokeai/frontend/web/src/features/parameters/components/AnimatedImageToImagePanel.tsx b/invokeai/frontend/web/src/features/parameters/components/AnimatedImageToImagePanel.tsx index a15759cd1f..da9262ac0f 100644 --- a/invokeai/frontend/web/src/features/parameters/components/AnimatedImageToImagePanel.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/AnimatedImageToImagePanel.tsx @@ -15,9 +15,9 @@ const AnimatedImageToImagePanel = () => { {isImageToImageEnabled && ( From 3601b9c860f521214b8c9d3bde6071c80898a2dc Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Sun, 30 Apr 2023 15:46:07 +1000 Subject: [PATCH 49/68] feat(ui): revamp status indicator --- invokeai/frontend/web/package.json | 1 + .../frontend/web/src/app/types/invokeai.ts | 37 ---- .../components/CurrentImageButtons.tsx | 1 - .../ProcessButtons/CancelButton.tsx | 4 +- .../system/components/StatusIndicator.tsx | 115 +++++++---- .../src/features/system/store/systemSlice.ts | 114 ++++++++--- invokeai/frontend/web/yarn.lock | 193 +++++++++++++++++- 7 files changed, 354 insertions(+), 111 deletions(-) diff --git a/invokeai/frontend/web/package.json b/invokeai/frontend/web/package.json index 684c56451c..326213c4f2 100644 --- a/invokeai/frontend/web/package.json +++ b/invokeai/frontend/web/package.json @@ -89,6 +89,7 @@ "react-konva-utils": "^1.0.4", "react-redux": "^8.0.5", "react-transition-group": "^4.4.5", + "react-use": "^17.4.0", "react-zoom-pan-pinch": "^3.0.7", "reactflow": "^11.7.0", "redux-deep-persist": "^1.0.7", diff --git a/invokeai/frontend/web/src/app/types/invokeai.ts b/invokeai/frontend/web/src/app/types/invokeai.ts index bd9642491d..05e6e088d6 100644 --- a/invokeai/frontend/web/src/app/types/invokeai.ts +++ b/invokeai/frontend/web/src/app/types/invokeai.ts @@ -115,21 +115,6 @@ export type PostProcessedImageMetadata = ESRGANMetadata | FacetoolMetadata; // image: GeneratedImageMetadata | PostProcessedImageMetadata; // }; -// An Image has a UUID, url, modified timestamp, width, height and maybe metadata -export type _Image = { - uuid: string; - url: string; - thumbnail: string; - mtime: number; - metadata?: Metadata; - width: number; - height: number; - category: GalleryCategory; - isBase64?: boolean; - dreamPrompt?: 'string'; - name?: string; -}; - /** * ResultImage */ @@ -141,11 +126,6 @@ export type Image = { metadata: ImageResponseMetadata; }; -// GalleryImages is an array of Image. -export type GalleryImages = { - images: Array<_Image>; -}; - /** * Types related to the system status. */ @@ -310,27 +290,10 @@ export type ErrorResponse = { additionalData?: string; }; -export type GalleryImagesResponse = { - images: Array>; - areMoreImagesAvailable: boolean; - category: GalleryCategory; -}; - -export type ImageDeletedResponse = { - uuid: string; - url: string; - category: GalleryCategory; -}; - export type ImageUrlResponse = { url: string; }; -// export type UploadImagePayload = { -// file: File; -// destination?: ImageUploadDestination; -// }; - export type UploadOutpaintingMergeImagePayload = { dataURL: string; name: string; diff --git a/invokeai/frontend/web/src/features/gallery/components/CurrentImageButtons.tsx b/invokeai/frontend/web/src/features/gallery/components/CurrentImageButtons.tsx index 51de6bea2e..4fef811d46 100644 --- a/invokeai/frontend/web/src/features/gallery/components/CurrentImageButtons.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/CurrentImageButtons.tsx @@ -63,7 +63,6 @@ import { } from '../store/gallerySelectors'; import DeleteImageModal from './DeleteImageModal'; import { useCallback } from 'react'; -import useSetBothPrompts from 'features/parameters/hooks/usePrompt'; import { requestCanvasRescale } from 'features/canvas/store/thunks/requestCanvasScale'; import { useGetUrl } from 'common/util/getUrl'; import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus'; diff --git a/invokeai/frontend/web/src/features/parameters/components/ProcessButtons/CancelButton.tsx b/invokeai/frontend/web/src/features/parameters/components/ProcessButtons/CancelButton.tsx index a71e8a3638..4f6c2ecc1c 100644 --- a/invokeai/frontend/web/src/features/parameters/components/ProcessButtons/CancelButton.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/ProcessButtons/CancelButton.tsx @@ -8,7 +8,7 @@ import { SystemState, cancelScheduled, cancelTypeChanged, - CancelType, + CancelStrategy, } from 'features/system/store/systemSlice'; import { isEqual } from 'lodash-es'; import { useCallback, memo } from 'react'; @@ -87,7 +87,7 @@ const CancelButton = ( const handleCancelTypeChanged = useCallback( (value: string | string[]) => { const newCancelType = Array.isArray(value) ? value[0] : value; - dispatch(cancelTypeChanged(newCancelType as CancelType)); + dispatch(cancelTypeChanged(newCancelType as CancelStrategy)); }, [dispatch] ); diff --git a/invokeai/frontend/web/src/features/system/components/StatusIndicator.tsx b/invokeai/frontend/web/src/features/system/components/StatusIndicator.tsx index 04adcdbe36..48418c9f19 100644 --- a/invokeai/frontend/web/src/features/system/components/StatusIndicator.tsx +++ b/invokeai/frontend/web/src/features/system/components/StatusIndicator.tsx @@ -1,19 +1,34 @@ -import { Text } from '@chakra-ui/react'; +import { Flex, Icon, Text } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; -import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; +import { useAppSelector } from 'app/store/storeHooks'; import { isEqual } from 'lodash-es'; import { useTranslation } from 'react-i18next'; import { systemSelector } from '../store/systemSelectors'; +import { ResourceKey } from 'i18next'; +import { AnimatePresence, motion } from 'framer-motion'; +import { useMemo, useRef } from 'react'; +import { FaCircle } from 'react-icons/fa'; +import { useHoverDirty } from 'react-use'; const statusIndicatorSelector = createSelector( systemSelector, (system) => { + const { + isConnected, + isProcessing, + statusTranslationKey, + currentIteration, + totalIterations, + currentStatusHasSteps, + } = system; + return { - isConnected: system.isConnected, - isProcessing: system.isProcessing, - currentIteration: system.currentIteration, - totalIterations: system.totalIterations, - currentStatus: system.currentStatus, + isConnected, + isProcessing, + currentIteration, + totalIterations, + statusTranslationKey, + currentStatusHasSteps, }; }, { @@ -27,43 +42,69 @@ const StatusIndicator = () => { isProcessing, currentIteration, totalIterations, - currentStatus, + statusTranslationKey, + currentStatusHasSteps, } = useAppSelector(statusIndicatorSelector); const { t } = useTranslation(); + const ref = useRef(null); - let statusIdentifier; - - if (isConnected) { - statusIdentifier = 'ok'; - } else { - statusIdentifier = 'error'; - } - - let statusMessage = currentStatus; - - if (isProcessing) { - statusIdentifier = 'working'; - } - - if (statusMessage) + const statusColorScheme = useMemo(() => { if (isProcessing) { - if (totalIterations > 1) { - statusMessage = `${t( - statusMessage as keyof typeof t - )} (${currentIteration}/${totalIterations})`; - } + return 'working'; } + if (isConnected) { + return 'ok'; + } + + return 'error'; + }, [isProcessing, isConnected]); + + const iterationsText = useMemo(() => { + if (!(currentIteration && totalIterations)) { + return; + } + + return ` (${currentIteration}/${totalIterations})`; + }, [currentIteration, totalIterations]); + + const isHovered = useHoverDirty(ref); + return ( - - {t(statusMessage as keyof typeof t)} - + + + {isHovered && ( + + + {t(statusTranslationKey as ResourceKey)} + {iterationsText} + + + )} + + + ); }; diff --git a/invokeai/frontend/web/src/features/system/store/systemSlice.ts b/invokeai/frontend/web/src/features/system/store/systemSlice.ts index 6773314b6a..cfaffdb65c 100644 --- a/invokeai/frontend/web/src/features/system/store/systemSlice.ts +++ b/invokeai/frontend/web/src/features/system/store/systemSlice.ts @@ -1,9 +1,10 @@ -import { ExpandedIndex, UseToastOptions } from '@chakra-ui/react'; +import { UseToastOptions } from '@chakra-ui/react'; import type { PayloadAction } from '@reduxjs/toolkit'; import { createSlice } from '@reduxjs/toolkit'; import * as InvokeAI from 'app/types/invokeai'; import { generatorProgress, + graphExecutionStateComplete, invocationComplete, invocationError, invocationStarted, @@ -13,7 +14,6 @@ import { socketUnsubscribed, } from 'services/events/actions'; -import i18n from 'i18n'; import { ProgressImage } from 'services/events/types'; import { initialImageSelected } from 'features/parameters/store/generationSlice'; import { makeToast } from '../hooks/useToastWatcher'; @@ -22,8 +22,10 @@ import { receivedModels } from 'services/thunks/model'; import { parsedOpenAPISchema } from 'features/nodes/store/nodesSlice'; import { LogLevelName } from 'roarr'; import { InvokeLogLevel } from 'app/logging/useLogger'; +import { TFuncKey } from 'i18next'; +import { t } from 'i18next'; -export type CancelType = 'immediate' | 'scheduled'; +export type CancelStrategy = 'immediate' | 'scheduled'; export interface SystemState { isGFPGANAvailable: boolean; @@ -35,7 +37,6 @@ export interface SystemState { totalSteps: number; currentIteration: number; totalIterations: number; - currentStatus: string; currentStatusHasSteps: boolean; shouldDisplayGuides: boolean; isCancelable: boolean; @@ -55,7 +56,7 @@ export interface SystemState { /** * Cancel strategy */ - cancelType: CancelType; + cancelType: CancelStrategy; /** * Whether or not a scheduled cancelation is pending */ @@ -77,6 +78,7 @@ export interface SystemState { */ consoleLogLevel: InvokeLogLevel; shouldLogToConsole: boolean; + statusTranslationKey: TFuncKey; } const initialSystemState: SystemState = { @@ -90,9 +92,6 @@ const initialSystemState: SystemState = { totalSteps: 0, currentIteration: 0, totalIterations: 0, - currentStatus: i18n.isInitialized - ? i18n.t('common.statusDisconnected') - : 'Disconnected', currentStatusHasSteps: false, isCancelable: true, enableImageDebugging: false, @@ -109,6 +108,7 @@ const initialSystemState: SystemState = { wasSchemaParsed: false, consoleLogLevel: 'error', shouldLogToConsole: true, + statusTranslationKey: 'common.statusDisconnected', }; export const systemSlice = createSlice({ @@ -118,8 +118,8 @@ export const systemSlice = createSlice({ setIsProcessing: (state, action: PayloadAction) => { state.isProcessing = action.payload; }, - setCurrentStatus: (state, action: PayloadAction) => { - state.currentStatus = action.payload; + setCurrentStatus: (state, action: PayloadAction) => { + state.statusTranslationKey = action.payload; }, errorOccurred: (state) => { state.isProcessing = false; @@ -129,7 +129,7 @@ export const systemSlice = createSlice({ state.currentIteration = 0; state.totalIterations = 0; state.currentStatusHasSteps = false; - state.currentStatus = i18n.t('common.statusError'); + state.statusTranslationKey = 'common.statusError'; }, setIsConnected: (state, action: PayloadAction) => { state.isConnected = action.payload; @@ -155,7 +155,7 @@ export const systemSlice = createSlice({ state.currentIteration = 0; state.totalIterations = 0; state.currentStatusHasSteps = false; - state.currentStatus = i18n.t('common.statusProcessingCanceled'); + state.statusTranslationKey = 'common.statusProcessingCanceled'; }, generationRequested: (state) => { state.isProcessing = true; @@ -165,25 +165,25 @@ export const systemSlice = createSlice({ state.currentIteration = 0; state.totalIterations = 0; state.currentStatusHasSteps = false; - state.currentStatus = i18n.t('common.statusPreparing'); + state.statusTranslationKey = 'common.statusPreparing'; }, setIsCancelable: (state, action: PayloadAction) => { state.isCancelable = action.payload; }, modelChangeRequested: (state) => { - state.currentStatus = i18n.t('common.statusLoadingModel'); + state.statusTranslationKey = 'common.statusLoadingModel'; state.isCancelable = false; state.isProcessing = true; state.currentStatusHasSteps = false; }, modelConvertRequested: (state) => { - state.currentStatus = i18n.t('common.statusConvertingModel'); + state.statusTranslationKey = 'common.statusConvertingModel'; state.isCancelable = false; state.isProcessing = true; state.currentStatusHasSteps = false; }, modelMergingRequested: (state) => { - state.currentStatus = i18n.t('common.statusMergingModels'); + state.statusTranslationKey = 'common.statusMergingModels'; state.isCancelable = false; state.isProcessing = true; state.currentStatusHasSteps = false; @@ -197,9 +197,12 @@ export const systemSlice = createSlice({ clearToastQueue: (state) => { state.toastQueue = []; }, - setProcessingIndeterminateTask: (state, action: PayloadAction) => { + setProcessingIndeterminateTask: ( + state, + action: PayloadAction + ) => { state.isProcessing = true; - state.currentStatus = action.payload; + state.statusTranslationKey = action.payload; state.currentStatusHasSteps = false; }, setSearchFolder: (state, action: PayloadAction) => { @@ -229,7 +232,7 @@ export const systemSlice = createSlice({ /** * The cancel type was changed */ - cancelTypeChanged: (state, action: PayloadAction) => { + cancelTypeChanged: (state, action: PayloadAction) => { state.cancelType = action.payload; }, /** @@ -265,9 +268,15 @@ export const systemSlice = createSlice({ */ builder.addCase(socketConnected, (state, action) => { const { timestamp } = action.payload; - state.isConnected = true; - state.currentStatus = i18n.t('common.statusConnected'); + state.isCancelable = true; + state.isProcessing = false; + state.currentStatusHasSteps = false; + state.currentStep = 0; + state.totalSteps = 0; + state.currentIteration = 0; + state.totalIterations = 0; + state.statusTranslationKey = 'common.statusConnected'; }); /** @@ -277,17 +286,28 @@ export const systemSlice = createSlice({ const { timestamp } = action.payload; state.isConnected = false; - state.currentStatus = i18n.t('common.statusDisconnected'); + state.isProcessing = false; + state.isCancelable = true; + state.currentStatusHasSteps = false; + state.currentStep = 0; + state.totalSteps = 0; + // state.currentIteration = 0; + // state.totalIterations = 0; + state.statusTranslationKey = 'common.statusDisconnected'; }); /** * Invocation Started */ builder.addCase(invocationStarted, (state) => { - state.isProcessing = true; state.isCancelable = true; + state.isProcessing = true; state.currentStatusHasSteps = false; - state.currentStatus = i18n.t('common.statusGenerating'); + state.currentStep = 0; + state.totalSteps = 0; + // state.currentIteration = 0; + // state.totalIterations = 0; + state.statusTranslationKey = 'common.statusPreparing'; }); /** @@ -303,10 +323,15 @@ export const systemSlice = createSlice({ graph_execution_state_id, } = action.payload.data; + state.isProcessing = true; + state.isCancelable = true; + // state.currentIteration = 0; + // state.totalIterations = 0; state.currentStatusHasSteps = true; state.currentStep = step + 1; // TODO: step starts at -1, think this is a bug state.totalSteps = total_steps; state.progressImage = progress_image ?? null; + state.statusTranslationKey = 'common.statusGenerating'; }); /** @@ -315,11 +340,15 @@ export const systemSlice = createSlice({ builder.addCase(invocationComplete, (state, action) => { const { data, timestamp } = action.payload; - state.isProcessing = false; + state.isProcessing = true; + state.isCancelable = true; + // state.currentIteration = 0; + // state.totalIterations = 0; + state.currentStatusHasSteps = false; state.currentStep = 0; state.totalSteps = 0; state.progressImage = null; - state.currentStatus = i18n.t('common.statusProcessingComplete'); + state.statusTranslationKey = 'common.statusProcessingComplete'; }); /** @@ -328,11 +357,18 @@ export const systemSlice = createSlice({ builder.addCase(invocationError, (state, action) => { const { data, timestamp } = action.payload; - state.progressImage = null; state.isProcessing = false; + state.isCancelable = true; + // state.currentIteration = 0; + // state.totalIterations = 0; + state.currentStatusHasSteps = false; + state.currentStep = 0; + state.totalSteps = 0; + state.progressImage = null; + state.statusTranslationKey = 'common.statusError'; state.toastQueue.push( - makeToast({ title: i18n.t('toast.serverError'), status: 'error' }) + makeToast({ title: t('toast.serverError'), status: 'error' }) ); }); @@ -341,7 +377,7 @@ export const systemSlice = createSlice({ */ builder.addCase(sessionInvoked.pending, (state) => { - state.currentStatus = i18n.t('common.statusPreparing'); + state.statusTranslationKey = 'common.statusPreparing'; }); /** @@ -356,17 +392,33 @@ export const systemSlice = createSlice({ state.currentStep = 0; state.totalSteps = 0; state.progressImage = null; + state.statusTranslationKey = 'common.statusConnected'; state.toastQueue.push( - makeToast({ title: i18n.t('toast.canceled'), status: 'warning' }) + makeToast({ title: t('toast.canceled'), status: 'warning' }) ); }); + /** + * Session Canceled + */ + builder.addCase(graphExecutionStateComplete, (state, action) => { + const { timestamp } = action.payload; + + state.isProcessing = false; + state.isCancelable = false; + state.isCancelScheduled = false; + state.currentStep = 0; + state.totalSteps = 0; + state.progressImage = null; + state.statusTranslationKey = 'common.statusConnected'; + }); + /** * Initial Image Selected */ builder.addCase(initialImageSelected, (state) => { - state.toastQueue.push(makeToast(i18n.t('toast.sentToImageToImage'))); + state.toastQueue.push(makeToast(t('toast.sentToImageToImage'))); }); /** diff --git a/invokeai/frontend/web/yarn.lock b/invokeai/frontend/web/yarn.lock index bece7f0829..88fec64725 100644 --- a/invokeai/frontend/web/yarn.lock +++ b/invokeai/frontend/web/yarn.lock @@ -57,6 +57,13 @@ dependencies: regenerator-runtime "^0.13.11" +"@babel/runtime@^7.1.2": + version "7.21.5" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.21.5.tgz#8492dddda9644ae3bda3b45eabe87382caee7200" + integrity sha512-8jI69toZqqcsnqGGqwGS4Qb1VwLOEp4hz+CXPywcvjs60u3B4Pom/U/7rm4W8tMOYEB+E9wgD0mW1l3r8qlI9Q== + dependencies: + regenerator-runtime "^0.13.11" + "@babel/types@^7.21.4", "@babel/types@^7.4": version "7.21.4" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.21.4.tgz#2d5d6bb7908699b3b416409ffd3b5daa25b030d4" @@ -1837,6 +1844,11 @@ "@types/react" "*" hoist-non-react-statics "^3.3.0" +"@types/js-cookie@^2.2.6": + version "2.2.7" + resolved "https://registry.yarnpkg.com/@types/js-cookie/-/js-cookie-2.2.7.tgz#226a9e31680835a6188e887f3988e60c04d3f6a3" + integrity sha512-aLkWa0C0vO5b4Sr798E26QgOkss68Un0bLjs7u9qxzPT5CG+8DuNTffWES58YzJs3hrVAOs1wonycqEBqNJubA== + "@types/json-schema@*", "@types/json-schema@^7.0.6", "@types/json-schema@^7.0.9": version "7.0.11" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" @@ -2048,6 +2060,11 @@ dependencies: "@swc/core" "^1.3.42" +"@xobotyi/scrollbar-width@^1.9.5": + version "1.9.5" + resolved "https://registry.yarnpkg.com/@xobotyi/scrollbar-width/-/scrollbar-width-1.9.5.tgz#80224a6919272f405b87913ca13b92929bdf3c4d" + integrity sha512-N8tkAACJx2ww8vFMneJmaAgmjAG1tnVBZJRLRcx061tmsLRZHSEZSLuGWnwPtunsSLvSqXQ2wfp7Mgqg1I+2dQ== + "@yarnpkg/lockfile@^1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz#e77a97fbd345b76d83245edcd17d393b1b41fb31" @@ -2685,7 +2702,7 @@ convert-source-map@^1.5.0: resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== -copy-to-clipboard@3.3.3: +copy-to-clipboard@3.3.3, copy-to-clipboard@^3.3.1: version "3.3.3" resolved "https://registry.yarnpkg.com/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz#55ac43a1db8ae639a4bd99511c148cdd1b83a1b0" integrity sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA== @@ -2736,7 +2753,22 @@ css-box-model@1.2.1: dependencies: tiny-invariant "^1.0.6" -csstype@^3.0.11, csstype@^3.0.2: +css-in-js-utils@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/css-in-js-utils/-/css-in-js-utils-3.1.0.tgz#640ae6a33646d401fc720c54fc61c42cd76ae2bb" + integrity sha512-fJAcud6B3rRu+KHYk+Bwf+WFL2MDCJJ1XG9x137tJQ0xYxor7XziQtuGFbWNdqrvF4Tk26O3H73nfVqXt/fW1A== + dependencies: + hyphenate-style-name "^1.0.3" + +css-tree@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.1.3.tgz#eb4870fb6fd7707327ec95c2ff2ab09b5e8db91d" + integrity sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q== + dependencies: + mdn-data "2.0.14" + source-map "^0.6.1" + +csstype@^3.0.11, csstype@^3.0.2, csstype@^3.0.6: version "3.1.2" resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.2.tgz#1d4bf9d572f11c14031f0436e1c10bc1f571f50b" integrity sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ== @@ -3142,6 +3174,13 @@ error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" +error-stack-parser@^2.0.6: + version "2.1.4" + resolved "https://registry.yarnpkg.com/error-stack-parser/-/error-stack-parser-2.1.4.tgz#229cb01cdbfa84440bfa91876285b94680188286" + integrity sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ== + dependencies: + stackframe "^1.3.4" + es-abstract@^1.19.0, es-abstract@^1.20.4: version "1.21.2" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.21.2.tgz#a56b9695322c8a185dc25975aa3b8ec31d0e7eff" @@ -3481,6 +3520,11 @@ fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== +fast-loops@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/fast-loops/-/fast-loops-1.1.3.tgz#ce96adb86d07e7bf9b4822ab9c6fac9964981f75" + integrity sha512-8EZzEP0eKkEEVX+drtd9mtuQ+/QrlfW/5MlwcwK5Nds6EkZ/tRzEexkzUY2mIssnAyVLT+TKHuRXmFNNXYUd6g== + fast-printf@^1.6.9: version "1.6.9" resolved "https://registry.yarnpkg.com/fast-printf/-/fast-printf-1.6.9.tgz#212f56570d2dc8ccdd057ee93d50dd414d07d676" @@ -3488,6 +3532,16 @@ fast-printf@^1.6.9: dependencies: boolean "^3.1.4" +fast-shallow-equal@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fast-shallow-equal/-/fast-shallow-equal-1.0.0.tgz#d4dcaf6472440dcefa6f88b98e3251e27f25628b" + integrity sha512-HPtaa38cPgWvaCFmRNhlc6NG7pv6NUHqjPgVAkWGoB9mQMwYB27/K0CvOM5Czy+qpT3e8XJ6Q4aPAnzpNpzNaw== + +fastest-stable-stringify@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/fastest-stable-stringify/-/fastest-stable-stringify-2.0.2.tgz#3757a6774f6ec8de40c4e86ec28ea02417214c76" + integrity sha512-bijHueCGd0LqqNK9b5oCMHc0MluJAx0cwqASgbWMvkO01lCYgIhacVRLcaDz3QnyYIRNJRDwMb41VuT6pHJ91Q== + fastq@^1.6.0: version "1.15.0" resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a" @@ -3966,6 +4020,11 @@ husky@^8.0.3: resolved "https://registry.yarnpkg.com/husky/-/husky-8.0.3.tgz#4936d7212e46d1dea28fef29bb3a108872cd9184" integrity sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg== +hyphenate-style-name@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz#691879af8e220aea5750e8827db4ef62a54e361d" + integrity sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ== + i18next-browser-languagedetector@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/i18next-browser-languagedetector/-/i18next-browser-languagedetector-7.0.1.tgz#ead34592edc96c6c3a618a51cb57ad027c5b5d87" @@ -4058,6 +4117,14 @@ ini@~1.3.0: resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== +inline-style-prefixer@^6.0.0: + version "6.0.4" + resolved "https://registry.yarnpkg.com/inline-style-prefixer/-/inline-style-prefixer-6.0.4.tgz#4290ed453ab0e4441583284ad86e41ad88384f44" + integrity sha512-FwXmZC2zbeeS7NzGjJ6pAiqRhXR0ugUShSNb6GApMl6da0/XGc4MOJsoWAywia52EEWbXNSy0pzkwz/+Y+swSg== + dependencies: + css-in-js-utils "^3.1.0" + fast-loops "^1.1.3" + internal-slot@^1.0.3, internal-slot@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.5.tgz#f2a2ee21f668f8627a4667f309dc0f4fb6674986" @@ -4350,6 +4417,11 @@ jju@~1.4.0: resolved "https://registry.yarnpkg.com/jju/-/jju-1.4.0.tgz#a3abe2718af241a2b2904f84a625970f389ae32a" integrity sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA== +js-cookie@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/js-cookie/-/js-cookie-2.2.1.tgz#69e106dc5d5806894562902aa5baec3744e9b2b8" + integrity sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ== + js-sdsl@^4.1.4: version "4.4.0" resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.4.0.tgz#8b437dbe642daa95760400b602378ed8ffea8430" @@ -4667,6 +4739,11 @@ make-error@^1.1.1: resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== +mdn-data@2.0.14: + version "2.0.14" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50" + integrity sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow== + merge-stream@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" @@ -4773,6 +4850,20 @@ ms@2.1.2: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== +nano-css@^5.3.1: + version "5.3.5" + resolved "https://registry.yarnpkg.com/nano-css/-/nano-css-5.3.5.tgz#3075ea29ffdeb0c7cb6d25edb21d8f7fa8e8fe8e" + integrity sha512-vSB9X12bbNu4ALBu7nigJgRViZ6ja3OU7CeuiV1zMIbXOdmkLahgtPmh3GBOlDxbKY0CitqlPdOReGlBLSp+yg== + dependencies: + css-tree "^1.1.2" + csstype "^3.0.6" + fastest-stable-stringify "^2.0.2" + inline-style-prefixer "^6.0.0" + rtl-css-js "^1.14.0" + sourcemap-codec "^1.4.8" + stacktrace-js "^2.0.2" + stylis "^4.0.6" + nanoid@^3.3.6: version "3.3.6" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.6.tgz#443380c856d6e9f9824267d960b4236ad583ea4c" @@ -5462,6 +5553,31 @@ react-transition-group@^4.4.5: loose-envify "^1.4.0" prop-types "^15.6.2" +react-universal-interface@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/react-universal-interface/-/react-universal-interface-0.6.2.tgz#5e8d438a01729a4dbbcbeeceb0b86be146fe2b3b" + integrity sha512-dg8yXdcQmvgR13RIlZbTRQOoUrDciFVoSBZILwjE2LFISxZZ8loVJKAkuzswl5js8BHda79bIb2b84ehU8IjXw== + +react-use@^17.4.0: + version "17.4.0" + resolved "https://registry.yarnpkg.com/react-use/-/react-use-17.4.0.tgz#cefef258b0a6c534a5c8021c2528ac6e1a4cdc6d" + integrity sha512-TgbNTCA33Wl7xzIJegn1HndB4qTS9u03QUwyNycUnXaweZkE4Kq2SB+Yoxx8qbshkZGYBDvUXbXWRUmQDcZZ/Q== + dependencies: + "@types/js-cookie" "^2.2.6" + "@xobotyi/scrollbar-width" "^1.9.5" + copy-to-clipboard "^3.3.1" + fast-deep-equal "^3.1.3" + fast-shallow-equal "^1.0.0" + js-cookie "^2.2.1" + nano-css "^5.3.1" + react-universal-interface "^0.6.2" + resize-observer-polyfill "^1.5.1" + screenfull "^5.1.0" + set-harmonic-interval "^1.0.1" + throttle-debounce "^3.0.1" + ts-easing "^0.2.0" + tslib "^2.1.0" + react-zoom-pan-pinch@^3.0.7: version "3.0.7" resolved "https://registry.yarnpkg.com/react-zoom-pan-pinch/-/react-zoom-pan-pinch-3.0.7.tgz#def52f6886bc11e1b160dedf4250aae95470b94d" @@ -5580,6 +5696,11 @@ reselect@^4.1.8: resolved "https://registry.yarnpkg.com/reselect/-/reselect-4.1.8.tgz#3f5dc671ea168dccdeb3e141236f69f02eaec524" integrity sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ== +resize-observer-polyfill@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz#0e9020dd3d21024458d4ebd27e23e40269810464" + integrity sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg== + resolve-dependency-path@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/resolve-dependency-path/-/resolve-dependency-path-2.0.0.tgz#11700e340717b865d216c66cabeb4a2a3c696736" @@ -5696,6 +5817,13 @@ rollup@^3.21.0: optionalDependencies: fsevents "~2.3.2" +rtl-css-js@^1.14.0: + version "1.16.1" + resolved "https://registry.yarnpkg.com/rtl-css-js/-/rtl-css-js-1.16.1.tgz#4b48b4354b0ff917a30488d95100fbf7219a3e80" + integrity sha512-lRQgou1mu19e+Ya0LsTvKrVJ5TYUbqCVPAiImX3UfLTenarvPUl1QFdvu5Z3PYmHT9RCcwIfbjRQBntExyj3Zg== + dependencies: + "@babel/runtime" "^7.1.2" + run-parallel@^1.1.9: version "1.2.0" resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" @@ -5743,6 +5871,11 @@ scheduler@^0.23.0: dependencies: loose-envify "^1.1.0" +screenfull@^5.1.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/screenfull/-/screenfull-5.2.0.tgz#6533d524d30621fc1283b9692146f3f13a93d1ba" + integrity sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA== + semver-compare@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc" @@ -5786,6 +5919,11 @@ serialize-error@^11.0.0: dependencies: type-fest "^2.12.2" +set-harmonic-interval@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/set-harmonic-interval/-/set-harmonic-interval-1.0.1.tgz#e1773705539cdfb80ce1c3d99e7f298bb3995249" + integrity sha512-AhICkFV84tBP1aWqPwLZqFvAwqEoVA9kxNMniGEUvzOlm4vLmOFLiTT3UZ6bziJTy4bOVpzWGTfSCbmaayGx8g== + shebang-command@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" @@ -5884,6 +6022,11 @@ source-map-support@~0.5.20: buffer-from "^1.0.0" source-map "^0.6.0" +source-map@0.5.6: + version "0.5.6" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" + integrity sha512-MjZkVp0NHr5+TPihLcadqnlVoGIoWo4IBHptutGh9wI3ttUYvCG26HkSuDi+K6lsZ25syXJXcctwgyVCt//xqA== + source-map@^0.5.7: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" @@ -5899,6 +6042,11 @@ source-map@^0.7.4: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.4.tgz#a9bbe705c9d8846f4e08ff6765acf0f1b0898656" integrity sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA== +sourcemap-codec@^1.4.8: + version "1.4.8" + resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" + integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== + spawn-command@0.0.2-1: version "0.0.2-1" resolved "https://registry.yarnpkg.com/spawn-command/-/spawn-command-0.0.2-1.tgz#62f5e9466981c1b796dc5929937e11c9c6921bd0" @@ -5909,6 +6057,35 @@ sprintf-js@~1.0.2: resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== +stack-generator@^2.0.5: + version "2.0.10" + resolved "https://registry.yarnpkg.com/stack-generator/-/stack-generator-2.0.10.tgz#8ae171e985ed62287d4f1ed55a1633b3fb53bb4d" + integrity sha512-mwnua/hkqM6pF4k8SnmZ2zfETsRUpWXREfA/goT8SLCV4iOFa4bzOX2nDipWAZFPTjLvQB82f5yaodMVhK0yJQ== + dependencies: + stackframe "^1.3.4" + +stackframe@^1.3.4: + version "1.3.4" + resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.3.4.tgz#b881a004c8c149a5e8efef37d51b16e412943310" + integrity sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw== + +stacktrace-gps@^3.0.4: + version "3.1.2" + resolved "https://registry.yarnpkg.com/stacktrace-gps/-/stacktrace-gps-3.1.2.tgz#0c40b24a9b119b20da4525c398795338966a2fb0" + integrity sha512-GcUgbO4Jsqqg6RxfyTHFiPxdPqF+3LFmQhm7MgCuYQOYuWyqxo5pwRPz5d/u6/WYJdEnWfK4r+jGbyD8TSggXQ== + dependencies: + source-map "0.5.6" + stackframe "^1.3.4" + +stacktrace-js@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/stacktrace-js/-/stacktrace-js-2.0.2.tgz#4ca93ea9f494752d55709a081d400fdaebee897b" + integrity sha512-Je5vBeY4S1r/RnLydLl0TBTi3F2qdfWmYsGvtfZgEI+SCprPppaIhQf5nGcal4gI4cGpCV/duLcAzT1np6sQqg== + dependencies: + error-stack-parser "^2.0.6" + stack-generator "^2.0.5" + stacktrace-gps "^3.0.4" + stream-to-array@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/stream-to-array/-/stream-to-array-2.3.0.tgz#bbf6b39f5f43ec30bc71babcb37557acecf34353" @@ -6035,7 +6212,7 @@ strip-json-comments@~2.0.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== -stylis@4.1.4: +stylis@4.1.4, stylis@^4.0.6: version "4.1.4" resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.1.4.tgz#9cb60e7153d8ac6d02d773552bf51c7a0344535b" integrity sha512-USf5pszRYwuE6hg9by0OkKChkQYEXfkeTtm0xKw+jqQhwyjCVLdYyMBK7R+n7dhzsblAWJnGxju4vxq5eH20GQ== @@ -6094,6 +6271,11 @@ text-table@^0.2.0: resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== +throttle-debounce@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/throttle-debounce/-/throttle-debounce-3.0.1.tgz#32f94d84dfa894f786c9a1f290e7a645b6a19abb" + integrity sha512-dTEWWNu6JmeVXY0ZYoPuH5cRIwc0MeGbJwah9KUNYSJwommQpCzTySTpEe8Gs1J23aeWEuAobe4Ag7EHVt/LOg== + through@^2.3.8: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" @@ -6148,6 +6330,11 @@ tree-kill@^1.2.2: resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc" integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== +ts-easing@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/ts-easing/-/ts-easing-0.2.0.tgz#c8a8a35025105566588d87dbda05dd7fbfa5a4ec" + integrity sha512-Z86EW+fFFh/IFB1fqQ3/+7Zpf9t2ebOAxNI/V6Wo7r5gqiqtxmgTlQ1qbqQcjLKYeSHPTsEmvlJUDg/EuL0uHQ== + ts-error@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/ts-error/-/ts-error-1.0.6.tgz#277496f2a28de6c184cfce8dfd5cdd03a4e6b0fc" From 270657a62c9337cad011d4973adaee126dfee7af Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Sun, 30 Apr 2023 22:01:34 +1000 Subject: [PATCH 50/68] feat(ui): gallery & progress image refactor --- invokeai/frontend/web/package.json | 2 + invokeai/frontend/web/public/locales/en.json | 4 + .../frontend/web/src/app/components/App.tsx | 145 +++++---- .../web/src/app/components/InvokeAIUI.tsx | 9 +- .../web/src/common/components/IAISlider.tsx | 2 +- .../store/thunks/mergeAndUploadCanvas.ts | 2 +- .../components/CurrentImagePreview.tsx | 79 ++--- .../gallery/components/HoverableImage.tsx | 2 +- .../components/ImageGalleryContent.tsx | 26 +- .../gallery/components/ImageGalleryPanel.tsx | 4 +- .../components/NextPrevImageButtons.tsx | 36 ++- .../gallery/store/gallerySelectors.ts | 33 +- .../features/gallery/store/gallerySlice.ts | 287 ++++-------------- .../components/ProgressImagePreview.tsx | 168 ++++++++++ .../parameters/store/generationSlice.ts | 6 +- .../src/features/system/store/systemSlice.ts | 6 +- .../tabs/Generate/GenerateContent.tsx | 2 + .../web/src/features/ui/store/uiSlice.ts | 14 + .../web/src/features/ui/store/uiTypes.ts | 4 +- .../frontend/web/src/services/thunks/image.ts | 14 +- invokeai/frontend/web/yarn.lock | 31 ++ 21 files changed, 466 insertions(+), 410 deletions(-) create mode 100644 invokeai/frontend/web/src/features/parameters/components/ProgressImagePreview.tsx diff --git a/invokeai/frontend/web/package.json b/invokeai/frontend/web/package.json index 326213c4f2..0d41e06897 100644 --- a/invokeai/frontend/web/package.json +++ b/invokeai/frontend/web/package.json @@ -61,6 +61,8 @@ "@chakra-ui/styled-system": "^2.9.0", "@chakra-ui/theme-tools": "^2.0.16", "@dagrejs/graphlib": "^2.1.12", + "@dnd-kit/core": "^6.0.8", + "@dnd-kit/modifiers": "^6.0.1", "@emotion/react": "^11.10.6", "@emotion/styled": "^11.10.6", "@fontsource/inter": "^4.5.15", diff --git a/invokeai/frontend/web/public/locales/en.json b/invokeai/frontend/web/public/locales/en.json index d3ccbcb395..e4e49138dc 100644 --- a/invokeai/frontend/web/public/locales/en.json +++ b/invokeai/frontend/web/public/locales/en.json @@ -645,5 +645,9 @@ "betaDarkenOutside": "Darken Outside", "betaLimitToBox": "Limit To Box", "betaPreserveMasked": "Preserve Masked" + }, + "ui": { + "showProgressImages": "Show Progress Images", + "hideProgressImages": "Hide Progress Images" } } diff --git a/invokeai/frontend/web/src/app/components/App.tsx b/invokeai/frontend/web/src/app/components/App.tsx index 37d0c7ba72..dff59efdb1 100644 --- a/invokeai/frontend/web/src/app/components/App.tsx +++ b/invokeai/frontend/web/src/app/components/App.tsx @@ -27,6 +27,16 @@ import { useGlobalHotkeys } from 'common/hooks/useGlobalHotkeys'; import { configChanged } from 'features/system/store/configSlice'; import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus'; import { useLogger } from 'app/logging/useLogger'; +import ProgressImagePreview from 'features/parameters/components/ProgressImagePreview'; +import { + DndContext, + DragEndEvent, + PointerSensor, + useSensor, + useSensors, +} from '@dnd-kit/core'; +import { floatingProgressImageMoved } from 'features/ui/store/uiSlice'; +import { restrictToWindowEdges } from '@dnd-kit/modifiers'; const DEFAULT_CONFIG = {}; @@ -40,6 +50,9 @@ const App = ({ config = DEFAULT_CONFIG, children }: Props) => { const log = useLogger(); const currentTheme = useAppSelector((state) => state.ui.currentTheme); + const shouldShowProgressImage = useAppSelector( + (state) => state.ui.shouldShowProgressImage + ); const isLightboxEnabled = useFeatureStatus('lightbox').isFeatureEnabled; @@ -63,64 +76,90 @@ const App = ({ config = DEFAULT_CONFIG, children }: Props) => { setLoadingOverridden(true); }, []); + const handleDragEnd = useCallback( + (event: DragEndEvent) => { + dispatch( + floatingProgressImageMoved({ x: event.delta.x, y: event.delta.y }) + ); + }, + [dispatch] + ); + + const pointer = useSensor(PointerSensor, { + // Delay the drag events (allow clicks on elements) + activationConstraint: { + delay: 100, + tolerance: 5, + }, + }); + + const sensors = useSensors(pointer); + return ( - - {isLightboxEnabled && } - - - - {children || } - + + {isLightboxEnabled && } + + + - - - - - + {children || } + + + + + + - - {!isApplicationReady && !loadingOverridden && ( - - - - - - - )} - + + {!isApplicationReady && !loadingOverridden && ( + + + + + + + )} + - - - - - - - + + + + + + + + + ); }; diff --git a/invokeai/frontend/web/src/app/components/InvokeAIUI.tsx b/invokeai/frontend/web/src/app/components/InvokeAIUI.tsx index 97a8be6fc1..ca48770119 100644 --- a/invokeai/frontend/web/src/app/components/InvokeAIUI.tsx +++ b/invokeai/frontend/web/src/app/components/InvokeAIUI.tsx @@ -1,4 +1,11 @@ -import React, { lazy, memo, PropsWithChildren, useEffect } from 'react'; +import React, { + lazy, + memo, + PropsWithChildren, + useCallback, + useEffect, + useState, +} from 'react'; import { Provider } from 'react-redux'; import { PersistGate } from 'redux-persist/integration/react'; import { store } from 'app/store/store'; diff --git a/invokeai/frontend/web/src/common/components/IAISlider.tsx b/invokeai/frontend/web/src/common/components/IAISlider.tsx index 44f039c433..48080e8970 100644 --- a/invokeai/frontend/web/src/common/components/IAISlider.tsx +++ b/invokeai/frontend/web/src/common/components/IAISlider.tsx @@ -233,7 +233,7 @@ const IAISlider = (props: IAIFullSliderProps) => { hidden={hideTooltip} {...sliderTooltipProps} > - + diff --git a/invokeai/frontend/web/src/features/canvas/store/thunks/mergeAndUploadCanvas.ts b/invokeai/frontend/web/src/features/canvas/store/thunks/mergeAndUploadCanvas.ts index d9feba63d3..e14871e11b 100644 --- a/invokeai/frontend/web/src/features/canvas/store/thunks/mergeAndUploadCanvas.ts +++ b/invokeai/frontend/web/src/features/canvas/store/thunks/mergeAndUploadCanvas.ts @@ -1,7 +1,7 @@ import { AnyAction, ThunkAction } from '@reduxjs/toolkit'; import * as InvokeAI from 'app/types/invokeai'; import { RootState } from 'app/store/store'; -import { addImage } from 'features/gallery/store/gallerySlice'; +// import { addImage } from 'features/gallery/store/gallerySlice'; import { addToast, setCurrentStatus, diff --git a/invokeai/frontend/web/src/features/gallery/components/CurrentImagePreview.tsx b/invokeai/frontend/web/src/features/gallery/components/CurrentImagePreview.tsx index 8855bf11d3..cb666dd128 100644 --- a/invokeai/frontend/web/src/features/gallery/components/CurrentImagePreview.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/CurrentImagePreview.tsx @@ -17,31 +17,11 @@ export const imagesSelector = createSelector( [uiSelector, selectedImageSelector, systemSelector], (ui, selectedImage, system) => { const { shouldShowImageDetails, shouldHidePreview } = ui; - const { progressImage } = system; - - // TODO: Clean this up, this is really gross - const imageToDisplay = progressImage - ? { - url: progressImage.dataURL, - width: progressImage.width, - height: progressImage.height, - isProgressImage: true, - image: progressImage, - } - : selectedImage - ? { - url: selectedImage.url, - width: selectedImage.metadata.width, - height: selectedImage.metadata.height, - isProgressImage: false, - image: selectedImage, - } - : null; return { shouldShowImageDetails, shouldHidePreview, - imageToDisplay, + image: selectedImage, }; }, { @@ -52,7 +32,7 @@ export const imagesSelector = createSelector( ); const CurrentImagePreview = () => { - const { shouldShowImageDetails, imageToDisplay, shouldHidePreview } = + const { shouldShowImageDetails, image, shouldHidePreview } = useAppSelector(imagesSelector); const { getUrl } = useGetUrl(); @@ -66,54 +46,37 @@ const CurrentImagePreview = () => { height: '100%', }} > - {imageToDisplay && ( + {image && ( - ) : !imageToDisplay.isProgressImage ? ( - - ) : undefined - } + src={shouldHidePreview ? undefined : getUrl(image.url)} + width={image.metadata.width} + height={image.metadata.height} + fallback={shouldHidePreview ? : undefined} sx={{ objectFit: 'contain', maxWidth: '100%', maxHeight: '100%', height: 'auto', position: 'absolute', - imageRendering: imageToDisplay.isProgressImage - ? 'pixelated' - : 'initial', borderRadius: 'base', }} /> )} {!shouldShowImageDetails && } - {shouldShowImageDetails && - imageToDisplay && - 'metadata' in imageToDisplay.image && ( - - - - )} + {shouldShowImageDetails && image && 'metadata' in image && ( + + + + )} ); }; diff --git a/invokeai/frontend/web/src/features/gallery/components/HoverableImage.tsx b/invokeai/frontend/web/src/features/gallery/components/HoverableImage.tsx index bd9ff92082..d0ff9aee40 100644 --- a/invokeai/frontend/web/src/features/gallery/components/HoverableImage.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/HoverableImage.tsx @@ -125,7 +125,7 @@ const HoverableImage = memo((props: HoverableImageProps) => { }, [handleDelete, onDeleteDialogOpen, shouldConfirmOnDelete]); const handleSelectImage = useCallback(() => { - dispatch(imageSelected(image.name)); + dispatch(imageSelected(image)); }, [image, dispatch]); const handleDragStart = useCallback( diff --git a/invokeai/frontend/web/src/features/gallery/components/ImageGalleryContent.tsx b/invokeai/frontend/web/src/features/gallery/components/ImageGalleryContent.tsx index e08e934e75..6524452e90 100644 --- a/invokeai/frontend/web/src/features/gallery/components/ImageGalleryContent.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/ImageGalleryContent.tsx @@ -49,7 +49,7 @@ const gallerySelector = createSelector( (uploads, results, gallery) => { const { currentCategory } = gallery; - return currentCategory === 'result' + return currentCategory === 'results' ? { images: resultsAdapter.getSelectors().selectAll(results), isLoading: results.isLoading, @@ -72,7 +72,6 @@ const ImageGalleryContent = () => { const { // images, currentCategory, - currentImageUuid, shouldPinGallery, galleryImageMinimumWidth, galleryGridTemplateColumns, @@ -80,6 +79,7 @@ const ImageGalleryContent = () => { shouldAutoSwitchToNewImages, // areMoreImagesAvailable, shouldUseSingleGalleryColumn, + selectedImage, } = useAppSelector(imageGallerySelector); const { images, areMoreImagesAvailable, isLoading } = @@ -89,11 +89,11 @@ const ImageGalleryContent = () => { // dispatch(requestImages(currentCategory)); // }; const handleClickLoadMore = () => { - if (currentCategory === 'result') { + if (currentCategory === 'results') { dispatch(receivedResultImagesPage()); } - if (currentCategory === 'user') { + if (currentCategory === 'uploads') { dispatch(receivedUploadImagesPage()); } }; @@ -147,34 +147,34 @@ const ImageGalleryContent = () => { } - onClick={() => dispatch(setCurrentCategory('result'))} + onClick={() => dispatch(setCurrentCategory('results'))} /> } - onClick={() => dispatch(setCurrentCategory('user'))} + onClick={() => dispatch(setCurrentCategory('uploads'))} /> ) : ( <> dispatch(setCurrentCategory('result'))} + isChecked={currentCategory === 'results'} + onClick={() => dispatch(setCurrentCategory('results'))} flexGrow={1} > {t('gallery.generations')} dispatch(setCurrentCategory('user'))} + isChecked={currentCategory === 'uploads'} + onClick={() => dispatch(setCurrentCategory('uploads'))} flexGrow={1} > {t('gallery.uploads')} @@ -251,7 +251,7 @@ const ImageGalleryContent = () => { > {images.map((image) => { const { name } = image; - const isSelected = currentImageUuid === name; + const isSelected = selectedImage?.name === name; return ( { - const { currentImage } = gallery; + [(state: RootState) => state, gallerySelector], + (state, gallery) => { + const { selectedImage, currentCategory } = gallery; - const tempImages = - gallery.categories[ - currentImage ? (currentImage.category as GalleryCategory) : 'result' - ].images; + if (!selectedImage) { + return { + isOnFirstImage: true, + isOnLastImage: true, + }; + } - const currentImageIndex = tempImages.findIndex( - (i) => i.uuid === gallery?.currentImage?.uuid + const currentImageIndex = state[currentCategory].ids.findIndex( + (i) => i === selectedImage.name ); - const imagesLength = tempImages.length; + + const imagesLength = state[currentCategory].ids.length; return { isOnFirstImage: currentImageIndex === 0, @@ -81,7 +86,6 @@ const NextPrevImageButtons = () => { state.gallery; export const imageGallerySelector = createSelector( - [gallerySelector, uiSelector, lightboxSelector, activeTabNameSelector], - (gallery, ui, lightbox, activeTabName) => { + [ + (state: RootState) => state, + gallerySelector, + uiSelector, + lightboxSelector, + activeTabNameSelector, + ], + (state, gallery, ui, lightbox, activeTabName) => { const { - categories, currentCategory, - currentImageUuid, galleryImageMinimumWidth, galleryImageObjectFit, shouldAutoSwitchToNewImages, galleryWidth, shouldUseSingleGalleryColumn, + selectedImage, } = gallery; const { shouldPinGallery } = ui; @@ -40,7 +45,6 @@ export const imageGallerySelector = createSelector( const { isLightboxOpen } = lightbox; return { - currentImageUuid, shouldPinGallery, galleryImageMinimumWidth, galleryImageObjectFit, @@ -49,9 +53,7 @@ export const imageGallerySelector = createSelector( : `repeat(auto-fill, minmax(${galleryImageMinimumWidth}px, auto))`, shouldAutoSwitchToNewImages, currentCategory, - images: categories[currentCategory].images, - areMoreImagesAvailable: - categories[currentCategory].areMoreImagesAvailable, + images: state[currentCategory].entities, galleryWidth, shouldEnableResize: isLightboxOpen || @@ -59,6 +61,7 @@ export const imageGallerySelector = createSelector( ? false : true, shouldUseSingleGalleryColumn, + selectedImage, }; }, { @@ -69,16 +72,16 @@ export const imageGallerySelector = createSelector( ); export const selectedImageSelector = createSelector( - [gallerySelector, selectResultsEntities, selectUploadsEntities], - (gallery, allResults, allUploads) => { - const selectedImageName = gallery.selectedImageName; + [(state: RootState) => state, gallerySelector], + (state, gallery) => { + const selectedImage = gallery.selectedImage; - if (selectedImageName in allResults) { - return allResults[selectedImageName]; + if (selectedImage?.type === 'results') { + return selectResultsById(state, selectedImage.name); } - if (selectedImageName in allUploads) { - return allUploads[selectedImageName]; + if (selectedImage?.type === 'uploads') { + return selectUploadsById(state, selectedImage.name); } } ); diff --git a/invokeai/frontend/web/src/features/gallery/store/gallerySlice.ts b/invokeai/frontend/web/src/features/gallery/store/gallerySlice.ts index 4d752a151b..4a7aa8a7e7 100644 --- a/invokeai/frontend/web/src/features/gallery/store/gallerySlice.ts +++ b/invokeai/frontend/web/src/features/gallery/store/gallerySlice.ts @@ -1,260 +1,80 @@ import type { PayloadAction } from '@reduxjs/toolkit'; import { createSlice } from '@reduxjs/toolkit'; -import * as InvokeAI from 'app/types/invokeai'; import { invocationComplete } from 'services/events/actions'; -import { InvokeTabName } from 'features/ui/store/tabMap'; -import { IRect } from 'konva/lib/types'; -import { clamp } from 'lodash-es'; import { isImageOutput } from 'services/types/guards'; import { deserializeImageResponse } from 'services/util/deserializeImageResponse'; import { imageUploaded } from 'services/thunks/image'; - -export type GalleryCategory = 'user' | 'result'; - -export type AddImagesPayload = { - images: Array; - areMoreImagesAvailable: boolean; - category: GalleryCategory; -}; +import { SelectedImage } from 'features/parameters/store/generationSlice'; type GalleryImageObjectFitType = 'contain' | 'cover'; -export type Gallery = { - images: InvokeAI._Image[]; - latest_mtime?: number; - earliest_mtime?: number; - areMoreImagesAvailable: boolean; -}; - export interface GalleryState { /** - * The selected image's unique name - * Use `selectedImageSelector` to access the image + * The selected image */ - selectedImageName: string; - /** - * The currently selected image - * @deprecated See `state.gallery.selectedImageName` - */ - currentImage?: InvokeAI._Image; - /** - * The currently selected image's uuid. - * @deprecated See `state.gallery.selectedImageName`, use `selectedImageSelector` to access the image - */ - currentImageUuid: string; - /** - * The current progress image - * @deprecated See `state.system.progressImage` - */ - intermediateImage?: InvokeAI._Image & { - boundingBox?: IRect; - generationMode?: InvokeTabName; - }; + selectedImage?: SelectedImage; galleryImageMinimumWidth: number; galleryImageObjectFit: GalleryImageObjectFitType; shouldAutoSwitchToNewImages: boolean; - categories: { - user: Gallery; - result: Gallery; - }; - currentCategory: GalleryCategory; galleryWidth: number; shouldUseSingleGalleryColumn: boolean; + currentCategory: 'results' | 'uploads'; } const initialState: GalleryState = { - selectedImageName: '', - currentImageUuid: '', + selectedImage: undefined, galleryImageMinimumWidth: 64, galleryImageObjectFit: 'cover', shouldAutoSwitchToNewImages: true, - currentCategory: 'result', - categories: { - user: { - images: [], - latest_mtime: undefined, - earliest_mtime: undefined, - areMoreImagesAvailable: true, - }, - result: { - images: [], - latest_mtime: undefined, - earliest_mtime: undefined, - areMoreImagesAvailable: true, - }, - }, galleryWidth: 300, shouldUseSingleGalleryColumn: false, + currentCategory: 'results', }; export const gallerySlice = createSlice({ name: 'gallery', initialState, reducers: { - imageSelected: (state, action: PayloadAction) => { - state.selectedImageName = action.payload; - }, - setCurrentImage: (state, action: PayloadAction) => { - state.currentImage = action.payload; - state.currentImageUuid = action.payload.uuid; - }, - removeImage: ( + imageSelected: ( state, - action: PayloadAction + action: PayloadAction ) => { - const { uuid, category } = action.payload; - - const tempImages = state.categories[category as GalleryCategory].images; - - const newImages = tempImages.filter((image) => image.uuid !== uuid); - - if (uuid === state.currentImageUuid) { - /** - * We are deleting the currently selected image. - * - * We want the new currentl selected image to be under the cursor in the - * gallery, so we need to do some fanagling. The currently selected image - * is set by its UUID, not its index in the image list. - * - * Get the currently selected image's index. - */ - const imageToDeleteIndex = tempImages.findIndex( - (image) => image.uuid === uuid - ); - - /** - * New current image needs to be in the same spot, but because the gallery - * is sorted in reverse order, the new current image's index will actuall be - * one less than the deleted image's index. - * - * Clamp the new index to ensure it is valid.. - */ - const newCurrentImageIndex = clamp( - imageToDeleteIndex, - 0, - newImages.length - 1 - ); - - state.currentImage = newImages.length - ? newImages[newCurrentImageIndex] - : undefined; - - state.currentImageUuid = newImages.length - ? newImages[newCurrentImageIndex].uuid - : ''; - } - - state.categories[category as GalleryCategory].images = newImages; + state.selectedImage = action.payload; }, - addImage: ( - state, - action: PayloadAction<{ - image: InvokeAI._Image; - category: GalleryCategory; - }> - ) => { - const { image: newImage, category } = action.payload; - const { uuid, url, mtime } = newImage; + // selectNextImage: (state) => { + // const { currentImage } = state; + // if (!currentImage) return; + // const tempImages = + // state.categories[currentImage.category as GalleryCategory].images; - const tempCategory = state.categories[category as GalleryCategory]; + // if (currentImage) { + // const currentImageIndex = tempImages.findIndex( + // (i) => i.uuid === currentImage.uuid + // ); + // if (currentImageIndex < tempImages.length - 1) { + // const newCurrentImage = tempImages[currentImageIndex + 1]; + // state.currentImage = newCurrentImage; + // state.currentImageUuid = newCurrentImage.uuid; + // } + // } + // }, + // selectPrevImage: (state) => { + // const { currentImage } = state; + // if (!currentImage) return; + // const tempImages = + // state.categories[currentImage.category as GalleryCategory].images; - // Do not add duplicate images - if (tempCategory.images.find((i) => i.url === url && i.mtime === mtime)) { - return; - } - - tempCategory.images.unshift(newImage); - if (state.shouldAutoSwitchToNewImages) { - state.currentImageUuid = uuid; - state.currentImage = newImage; - state.currentCategory = category; - } - state.intermediateImage = undefined; - tempCategory.latest_mtime = mtime; - }, - setIntermediateImage: ( - state, - action: PayloadAction< - InvokeAI._Image & { - boundingBox?: IRect; - generationMode?: InvokeTabName; - } - > - ) => { - state.intermediateImage = action.payload; - }, - clearIntermediateImage: (state) => { - state.intermediateImage = undefined; - }, - selectNextImage: (state) => { - const { currentImage } = state; - if (!currentImage) return; - const tempImages = - state.categories[currentImage.category as GalleryCategory].images; - - if (currentImage) { - const currentImageIndex = tempImages.findIndex( - (i) => i.uuid === currentImage.uuid - ); - if (currentImageIndex < tempImages.length - 1) { - const newCurrentImage = tempImages[currentImageIndex + 1]; - state.currentImage = newCurrentImage; - state.currentImageUuid = newCurrentImage.uuid; - } - } - }, - selectPrevImage: (state) => { - const { currentImage } = state; - if (!currentImage) return; - const tempImages = - state.categories[currentImage.category as GalleryCategory].images; - - if (currentImage) { - const currentImageIndex = tempImages.findIndex( - (i) => i.uuid === currentImage.uuid - ); - if (currentImageIndex > 0) { - const newCurrentImage = tempImages[currentImageIndex - 1]; - state.currentImage = newCurrentImage; - state.currentImageUuid = newCurrentImage.uuid; - } - } - }, - addGalleryImages: (state, action: PayloadAction) => { - const { images, areMoreImagesAvailable, category } = action.payload; - const tempImages = state.categories[category].images; - - // const prevImages = category === 'user' ? state.userImages : state.resultImages - - if (images.length > 0) { - // Filter images that already exist in the gallery - const newImages = images.filter( - (newImage) => - !tempImages.find( - (i) => i.url === newImage.url && i.mtime === newImage.mtime - ) - ); - state.categories[category].images = tempImages - .concat(newImages) - .sort((a, b) => b.mtime - a.mtime); - - if (!state.currentImage) { - const newCurrentImage = images[0]; - state.currentImage = newCurrentImage; - state.currentImageUuid = newCurrentImage.uuid; - } - - // keep track of the timestamps of latest and earliest images received - state.categories[category].latest_mtime = images[0].mtime; - state.categories[category].earliest_mtime = - images[images.length - 1].mtime; - } - - if (areMoreImagesAvailable !== undefined) { - state.categories[category].areMoreImagesAvailable = - areMoreImagesAvailable; - } - }, + // if (currentImage) { + // const currentImageIndex = tempImages.findIndex( + // (i) => i.uuid === currentImage.uuid + // ); + // if (currentImageIndex > 0) { + // const newCurrentImage = tempImages[currentImageIndex - 1]; + // state.currentImage = newCurrentImage; + // state.currentImageUuid = newCurrentImage.uuid; + // } + // } + // }, setGalleryImageMinimumWidth: (state, action: PayloadAction) => { state.galleryImageMinimumWidth = action.payload; }, @@ -267,7 +87,10 @@ export const gallerySlice = createSlice({ setShouldAutoSwitchToNewImages: (state, action: PayloadAction) => { state.shouldAutoSwitchToNewImages = action.payload; }, - setCurrentCategory: (state, action: PayloadAction) => { + setCurrentCategory: ( + state, + action: PayloadAction<'results' | 'uploads'> + ) => { state.currentCategory = action.payload; }, setGalleryWidth: (state, action: PayloadAction) => { @@ -286,9 +109,11 @@ export const gallerySlice = createSlice({ */ builder.addCase(invocationComplete, (state, action) => { const { data } = action.payload; - if (isImageOutput(data.result)) { - state.selectedImageName = data.result.image.image_name; - state.intermediateImage = undefined; + if (isImageOutput(data.result) && state.shouldAutoSwitchToNewImages) { + state.selectedImage = { + name: data.result.image.image_name, + type: 'results', + }; } }); @@ -299,27 +124,19 @@ export const gallerySlice = createSlice({ const { response } = action.payload; const uploadedImage = deserializeImageResponse(response); - state.selectedImageName = uploadedImage.name; + state.selectedImage = { name: uploadedImage.name, type: 'uploads' }; }); }, }); export const { imageSelected, - addImage, - clearIntermediateImage, - removeImage, - setCurrentImage, - addGalleryImages, - setIntermediateImage, - selectNextImage, - selectPrevImage, setGalleryImageMinimumWidth, setGalleryImageObjectFit, setShouldAutoSwitchToNewImages, - setCurrentCategory, setGalleryWidth, setShouldUseSingleGalleryColumn, + setCurrentCategory, } = gallerySlice.actions; export default gallerySlice.reducer; diff --git a/invokeai/frontend/web/src/features/parameters/components/ProgressImagePreview.tsx b/invokeai/frontend/web/src/features/parameters/components/ProgressImagePreview.tsx new file mode 100644 index 0000000000..63771c3ecd --- /dev/null +++ b/invokeai/frontend/web/src/features/parameters/components/ProgressImagePreview.tsx @@ -0,0 +1,168 @@ +import { + Accordion, + AccordionButton, + AccordionIcon, + AccordionItem, + AccordionPanel, + Box, + Flex, + Icon, + Image, + Text, +} from '@chakra-ui/react'; +import { useDraggable } from '@dnd-kit/core'; +import { createSelector } from '@reduxjs/toolkit'; +import { useAppSelector } from 'app/store/storeHooks'; +import { systemSelector } from 'features/system/store/systemSelectors'; +import { memo, useCallback, useRef, MouseEvent } from 'react'; +import { CSS } from '@dnd-kit/utilities'; +import { FaEye, FaImage } from 'react-icons/fa'; +import { uiSelector } from 'features/ui/store/uiSelectors'; +import { Resizable } from 're-resizable'; +import { useBoolean, useHoverDirty } from 'react-use'; +import IAIIconButton from 'common/components/IAIIconButton'; +import { CloseIcon } from '@chakra-ui/icons'; +import { useTranslation } from 'react-i18next'; + +const selector = createSelector([systemSelector, uiSelector], (system, ui) => { + const { progressImage } = system; + const { floatingProgressImageCoordinates, shouldShowProgressImage } = ui; + + return { + progressImage, + coords: floatingProgressImageCoordinates, + shouldShowProgressImage, + }; +}); + +const ProgressImagePreview = () => { + const { progressImage, coords, shouldShowProgressImage } = + useAppSelector(selector); + + const [shouldShowProgressImages, toggleShouldShowProgressImages] = + useBoolean(false); + + const { t } = useTranslation(); + const { attributes, listeners, setNodeRef, transform } = useDraggable({ + id: 'progress-image', + }); + + const transformStyles = transform + ? { + transform: CSS.Translate.toString(transform), + } + : {}; + + return shouldShowProgressImages ? ( + + + + + + + {progressImage ? ( + + + + ) : ( + + + + )} + + } + sx={{ + position: 'absolute', + top: 2, + insetInlineEnd: 2, + }} + variant="ghost" + /> + + + + + + ) : ( + } + /> + ); +}; + +export default memo(ProgressImagePreview); diff --git a/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts b/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts index 5dbe6b2c28..9d9d689cb0 100644 --- a/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts +++ b/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts @@ -7,7 +7,7 @@ import { seedWeightsToString } from 'common/util/seedWeightPairs'; import { clamp } from 'lodash-es'; import { ImageField, ImageType } from 'services/api'; -export type InitialImage = { +export type SelectedImage = { name: string; type: ImageType; }; @@ -17,7 +17,7 @@ export interface GenerationState { height: number; img2imgStrength: number; infillMethod: string; - initialImage?: InitialImage; // can be an Image or url + initialImage?: SelectedImage; // can be an Image or url iterations: number; maskPath: string; perlin: number; @@ -351,7 +351,7 @@ export const generationSlice = createSlice({ setVerticalSymmetrySteps: (state, action: PayloadAction) => { state.verticalSymmetrySteps = action.payload; }, - initialImageSelected: (state, action: PayloadAction) => { + initialImageSelected: (state, action: PayloadAction) => { state.initialImage = action.payload; state.isImageToImageEnabled = true; }, diff --git a/invokeai/frontend/web/src/features/system/store/systemSlice.ts b/invokeai/frontend/web/src/features/system/store/systemSlice.ts index cfaffdb65c..e7f58d2f4b 100644 --- a/invokeai/frontend/web/src/features/system/store/systemSlice.ts +++ b/invokeai/frontend/web/src/features/system/store/systemSlice.ts @@ -307,7 +307,7 @@ export const systemSlice = createSlice({ state.totalSteps = 0; // state.currentIteration = 0; // state.totalIterations = 0; - state.statusTranslationKey = 'common.statusPreparing'; + state.statusTranslationKey = 'common.statusGenerating'; }); /** @@ -347,7 +347,6 @@ export const systemSlice = createSlice({ state.currentStatusHasSteps = false; state.currentStep = 0; state.totalSteps = 0; - state.progressImage = null; state.statusTranslationKey = 'common.statusProcessingComplete'; }); @@ -364,7 +363,6 @@ export const systemSlice = createSlice({ state.currentStatusHasSteps = false; state.currentStep = 0; state.totalSteps = 0; - state.progressImage = null; state.statusTranslationKey = 'common.statusError'; state.toastQueue.push( @@ -391,7 +389,6 @@ export const systemSlice = createSlice({ state.isCancelScheduled = false; state.currentStep = 0; state.totalSteps = 0; - state.progressImage = null; state.statusTranslationKey = 'common.statusConnected'; state.toastQueue.push( @@ -410,7 +407,6 @@ export const systemSlice = createSlice({ state.isCancelScheduled = false; state.currentStep = 0; state.totalSteps = 0; - state.progressImage = null; state.statusTranslationKey = 'common.statusConnected'; }); diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/Generate/GenerateContent.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/Generate/GenerateContent.tsx index 53fdcb4a49..de7b738956 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/Generate/GenerateContent.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/Generate/GenerateContent.tsx @@ -1,10 +1,12 @@ import { Box, Flex } from '@chakra-ui/react'; import CurrentImageDisplay from 'features/gallery/components/CurrentImageDisplay'; +import ProgressImagePreview from 'features/parameters/components/ProgressImagePreview'; const GenerateContent = () => { return ( ) => { + const { x, y } = state.floatingProgressImageCoordinates; + const { x: _x, y: _y } = action.payload; + + state.floatingProgressImageCoordinates = { x: x + _x, y: y + _y }; + }, + shouldShowProgressImageChanged: (state, action: PayloadAction) => { + state.shouldShowProgressImage = action.payload; + }, }, }); @@ -128,6 +140,8 @@ export const { toggleParametersPanel, toggleGalleryPanel, openAccordionItemsChanged, + floatingProgressImageMoved, + shouldShowProgressImageChanged, } = uiSlice.actions; export default uiSlice.reducer; diff --git a/invokeai/frontend/web/src/features/ui/store/uiTypes.ts b/invokeai/frontend/web/src/features/ui/store/uiTypes.ts index 66e85ce71b..309b110d4d 100644 --- a/invokeai/frontend/web/src/features/ui/store/uiTypes.ts +++ b/invokeai/frontend/web/src/features/ui/store/uiTypes.ts @@ -1,4 +1,4 @@ -import { InvokeTabName } from './tabMap'; +import { Coordinates } from '@dnd-kit/core/dist/types'; export type AddNewModelType = 'ckpt' | 'diffusers' | null; @@ -19,4 +19,6 @@ export interface UIState { openLinearAccordionItems: number[]; openGenerateAccordionItems: number[]; openUnifiedCanvasAccordionItems: number[]; + floatingProgressImageCoordinates: Coordinates; + shouldShowProgressImage: boolean; } diff --git a/invokeai/frontend/web/src/services/thunks/image.ts b/invokeai/frontend/web/src/services/thunks/image.ts index c4da9d9f16..a0d8f504b7 100644 --- a/invokeai/frontend/web/src/services/thunks/image.ts +++ b/invokeai/frontend/web/src/services/thunks/image.ts @@ -2,7 +2,7 @@ import { isFulfilled, isRejected } from '@reduxjs/toolkit'; import { log } from 'app/logging/useLogger'; import { createAppAsyncThunk } from 'app/store/storeUtils'; import { imageSelected } from 'features/gallery/store/gallerySlice'; -import { clamp } from 'lodash-es'; +import { clamp, isString } from 'lodash-es'; import { ImagesService } from 'services/api'; import { getHeaders } from 'services/util/getHeaders'; @@ -85,7 +85,7 @@ export const imageDeleted = createAppAsyncThunk( // Determine which image should replace the deleted image, if the deleted image is the selected image. // Unfortunately, we have to do this here, because the resultsSlice and uploadsSlice cannot change // the selected image. - const selectedImageName = getState().gallery.selectedImageName; + const selectedImageName = getState().gallery.selectedImage?.name; if (selectedImageName === imageName) { const allIds = getState()[imageType].ids; @@ -104,9 +104,13 @@ export const imageDeleted = createAppAsyncThunk( const newSelectedImageId = filteredIds[newSelectedImageIndex]; - dispatch( - imageSelected(newSelectedImageId ? newSelectedImageId.toString() : '') - ); + if (newSelectedImageId) { + dispatch( + imageSelected({ name: newSelectedImageId as string, type: imageType }) + ); + } else { + dispatch(imageSelected()); + } } const response = await ImagesService.deleteImage(arg); diff --git a/invokeai/frontend/web/yarn.lock b/invokeai/frontend/web/yarn.lock index 88fec64725..f7f9af51ef 100644 --- a/invokeai/frontend/web/yarn.lock +++ b/invokeai/frontend/web/yarn.lock @@ -937,6 +937,37 @@ gonzales-pe "^4.3.0" node-source-walk "^5.0.1" +"@dnd-kit/accessibility@^3.0.0": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@dnd-kit/accessibility/-/accessibility-3.0.1.tgz#3ccbefdfca595b0a23a5dc57d3de96bc6935641c" + integrity sha512-HXRrwS9YUYQO9lFRc/49uO/VICbM+O+ZRpFDe9Pd1rwVv2PCNkRiTZRdxrDgng/UkvdC3Re9r2vwPpXXrWeFzg== + dependencies: + tslib "^2.0.0" + +"@dnd-kit/core@^6.0.8": + version "6.0.8" + resolved "https://registry.yarnpkg.com/@dnd-kit/core/-/core-6.0.8.tgz#040ae13fea9787ee078e5f0361f3b49b07f3f005" + integrity sha512-lYaoP8yHTQSLlZe6Rr9qogouGUz9oRUj4AHhDQGQzq/hqaJRpFo65X+JKsdHf8oUFBzx5A+SJPUvxAwTF2OabA== + dependencies: + "@dnd-kit/accessibility" "^3.0.0" + "@dnd-kit/utilities" "^3.2.1" + tslib "^2.0.0" + +"@dnd-kit/modifiers@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/@dnd-kit/modifiers/-/modifiers-6.0.1.tgz#9e39b25fd6e323659604cc74488fe044d33188c8" + integrity sha512-rbxcsg3HhzlcMHVHWDuh9LCjpOVAgqbV78wLGI8tziXY3+qcMQ61qVXIvNKQFuhj75dSfD+o+PYZQ/NUk2A23A== + dependencies: + "@dnd-kit/utilities" "^3.2.1" + tslib "^2.0.0" + +"@dnd-kit/utilities@^3.2.1": + version "3.2.1" + resolved "https://registry.yarnpkg.com/@dnd-kit/utilities/-/utilities-3.2.1.tgz#53f9e2016fd2506ec49e404c289392cfff30332a" + integrity sha512-OOXqISfvBw/1REtkSK2N3Fi2EQiLMlWUlqnOK/UpOISqBZPWpE6TqL+jcPtMOkE8TqYGiURvRdPSI9hltNUjEA== + dependencies: + tslib "^2.0.0" + "@emotion/babel-plugin@^11.10.8": version "11.10.8" resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.10.8.tgz#bae325c902937665d00684038fd5294223ef9e1d" From d5e152b35eb4cba6c1ba4095302625bcc88676f9 Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Sun, 30 Apr 2023 23:08:05 +1000 Subject: [PATCH 51/68] fix(ui): ignore events after canceling session --- .../web/src/features/system/store/systemSlice.ts | 13 ++++++++++--- .../services/events/util/setEventListeners.ts | 16 ++++++++++++++++ 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/invokeai/frontend/web/src/features/system/store/systemSlice.ts b/invokeai/frontend/web/src/features/system/store/systemSlice.ts index e7f58d2f4b..a74e6dca7e 100644 --- a/invokeai/frontend/web/src/features/system/store/systemSlice.ts +++ b/invokeai/frontend/web/src/features/system/store/systemSlice.ts @@ -79,6 +79,7 @@ export interface SystemState { consoleLogLevel: InvokeLogLevel; shouldLogToConsole: boolean; statusTranslationKey: TFuncKey; + canceledSession: string; } const initialSystemState: SystemState = { @@ -109,6 +110,7 @@ const initialSystemState: SystemState = { consoleLogLevel: 'error', shouldLogToConsole: true, statusTranslationKey: 'common.statusDisconnected', + canceledSession: '', }; export const systemSlice = createSlice({ @@ -254,6 +256,7 @@ export const systemSlice = createSlice({ */ builder.addCase(socketSubscribed, (state, action) => { state.sessionId = action.payload.sessionId; + state.canceledSession = ''; }); /** @@ -299,7 +302,7 @@ export const systemSlice = createSlice({ /** * Invocation Started */ - builder.addCase(invocationStarted, (state) => { + builder.addCase(invocationStarted, (state, action) => { state.isCancelable = true; state.isProcessing = true; state.currentStatusHasSteps = false; @@ -340,14 +343,17 @@ export const systemSlice = createSlice({ builder.addCase(invocationComplete, (state, action) => { const { data, timestamp } = action.payload; - state.isProcessing = true; - state.isCancelable = true; // state.currentIteration = 0; // state.totalIterations = 0; state.currentStatusHasSteps = false; state.currentStep = 0; state.totalSteps = 0; state.statusTranslationKey = 'common.statusProcessingComplete'; + + if (state.canceledSession === data.graph_execution_state_id) { + state.isProcessing = false; + state.isCancelable = true; + } }); /** @@ -384,6 +390,7 @@ export const systemSlice = createSlice({ builder.addCase(sessionCanceled.fulfilled, (state, action) => { const { timestamp } = action.payload; + state.canceledSession = action.meta.arg.sessionId; state.isProcessing = false; state.isCancelable = false; state.isCancelScheduled = false; diff --git a/invokeai/frontend/web/src/services/events/util/setEventListeners.ts b/invokeai/frontend/web/src/services/events/util/setEventListeners.ts index 8454f81508..89bbc717a3 100644 --- a/invokeai/frontend/web/src/services/events/util/setEventListeners.ts +++ b/invokeai/frontend/web/src/services/events/util/setEventListeners.ts @@ -90,6 +90,14 @@ export const setEventListeners = (arg: SetEventListenersArg) => { * Invocation started */ socket.on('invocation_started', (data) => { + if (getState().system.canceledSession === data.graph_execution_state_id) { + log.trace( + { data, sessionId: data.graph_execution_state_id }, + `Ignored invocation started (${data.node.type}) for canceled session (${data.graph_execution_state_id})` + ); + return; + } + log.info( { data, sessionId: data.graph_execution_state_id }, `Invocation started (${data.node.type})` @@ -101,6 +109,14 @@ export const setEventListeners = (arg: SetEventListenersArg) => { * Generator progress */ socket.on('generator_progress', (data) => { + if (getState().system.canceledSession === data.graph_execution_state_id) { + log.trace( + { data, sessionId: data.graph_execution_state_id }, + `Ignored generator progress (${data.node.type}) for canceled session (${data.graph_execution_state_id})` + ); + return; + } + log.trace( { data, sessionId: data.graph_execution_state_id }, `Generator progress (${data.node.type})` From 779671753dc6d53dac853fd2588ca39347e8ea20 Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Sun, 30 Apr 2023 23:08:27 +1000 Subject: [PATCH 52/68] feat(ui): tweak floating preview --- .../frontend/web/src/app/components/App.tsx | 27 +-- .../components/ProgressImagePreview.tsx | 164 +++++++++--------- .../web/src/features/ui/store/uiSlice.ts | 8 +- .../web/src/features/ui/store/uiTypes.ts | 2 +- 4 files changed, 90 insertions(+), 111 deletions(-) diff --git a/invokeai/frontend/web/src/app/components/App.tsx b/invokeai/frontend/web/src/app/components/App.tsx index dff59efdb1..1d5ffb0079 100644 --- a/invokeai/frontend/web/src/app/components/App.tsx +++ b/invokeai/frontend/web/src/app/components/App.tsx @@ -28,13 +28,7 @@ import { configChanged } from 'features/system/store/configSlice'; import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus'; import { useLogger } from 'app/logging/useLogger'; import ProgressImagePreview from 'features/parameters/components/ProgressImagePreview'; -import { - DndContext, - DragEndEvent, - PointerSensor, - useSensor, - useSensors, -} from '@dnd-kit/core'; +import { DndContext, DragEndEvent } from '@dnd-kit/core'; import { floatingProgressImageMoved } from 'features/ui/store/uiSlice'; import { restrictToWindowEdges } from '@dnd-kit/modifiers'; @@ -50,9 +44,6 @@ const App = ({ config = DEFAULT_CONFIG, children }: Props) => { const log = useLogger(); const currentTheme = useAppSelector((state) => state.ui.currentTheme); - const shouldShowProgressImage = useAppSelector( - (state) => state.ui.shouldShowProgressImage - ); const isLightboxEnabled = useFeatureStatus('lightbox').isFeatureEnabled; @@ -85,22 +76,8 @@ const App = ({ config = DEFAULT_CONFIG, children }: Props) => { [dispatch] ); - const pointer = useSensor(PointerSensor, { - // Delay the drag events (allow clicks on elements) - activationConstraint: { - delay: 100, - tolerance: 5, - }, - }); - - const sensors = useSensors(pointer); - return ( - + {isLightboxEnabled && } diff --git a/invokeai/frontend/web/src/features/parameters/components/ProgressImagePreview.tsx b/invokeai/frontend/web/src/features/parameters/components/ProgressImagePreview.tsx index 63771c3ecd..085a52c4b0 100644 --- a/invokeai/frontend/web/src/features/parameters/components/ProgressImagePreview.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/ProgressImagePreview.tsx @@ -1,52 +1,45 @@ -import { - Accordion, - AccordionButton, - AccordionIcon, - AccordionItem, - AccordionPanel, - Box, - Flex, - Icon, - Image, - Text, -} from '@chakra-ui/react'; +import { Box, Flex, Icon, Image, Text } from '@chakra-ui/react'; import { useDraggable } from '@dnd-kit/core'; import { createSelector } from '@reduxjs/toolkit'; -import { useAppSelector } from 'app/store/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { systemSelector } from 'features/system/store/systemSelectors'; -import { memo, useCallback, useRef, MouseEvent } from 'react'; +import { memo, useCallback } from 'react'; import { CSS } from '@dnd-kit/utilities'; -import { FaEye, FaImage } from 'react-icons/fa'; +import { FaEye, FaImage, FaStopwatch } from 'react-icons/fa'; import { uiSelector } from 'features/ui/store/uiSelectors'; import { Resizable } from 're-resizable'; -import { useBoolean, useHoverDirty } from 'react-use'; import IAIIconButton from 'common/components/IAIIconButton'; import { CloseIcon } from '@chakra-ui/icons'; import { useTranslation } from 'react-i18next'; +import { shouldShowProgressImagesToggled } from 'features/ui/store/uiSlice'; const selector = createSelector([systemSelector, uiSelector], (system, ui) => { const { progressImage } = system; - const { floatingProgressImageCoordinates, shouldShowProgressImage } = ui; + const { floatingProgressImageCoordinates, shouldShowProgressImages } = ui; return { progressImage, coords: floatingProgressImageCoordinates, - shouldShowProgressImage, + shouldShowProgressImages, }; }); const ProgressImagePreview = () => { - const { progressImage, coords, shouldShowProgressImage } = + const dispatch = useAppDispatch(); + + const { progressImage, coords, shouldShowProgressImages } = useAppSelector(selector); - const [shouldShowProgressImages, toggleShouldShowProgressImages] = - useBoolean(false); - const { t } = useTranslation(); + const { attributes, listeners, setNodeRef, transform } = useDraggable({ id: 'progress-image', }); + const toggleProgressImages = useCallback(() => { + dispatch(shouldShowProgressImagesToggled()); + }, [dispatch]); + const transformStyles = transform ? { transform: CSS.Translate.toString(transform), @@ -75,80 +68,89 @@ const ProgressImagePreview = () => { defaultSize={{ width: 300, height: 300 }} minWidth={200} minHeight={200} - boundsByDirection={true} - enable={{ bottomRight: true }} > - {progressImage ? ( - - - - ) : ( - - - - )} + + + Progress Images + + + } + variant="ghost" + /> - } - sx={{ - position: 'absolute', - top: 2, - insetInlineEnd: 2, - }} - variant="ghost" - /> + {progressImage ? ( + + + + ) : ( + + + + )} @@ -156,11 +158,11 @@ const ProgressImagePreview = () => { ) : ( } + icon={} /> ); }; diff --git a/invokeai/frontend/web/src/features/ui/store/uiSlice.ts b/invokeai/frontend/web/src/features/ui/store/uiSlice.ts index 4a1cc253bc..86ce8c2a12 100644 --- a/invokeai/frontend/web/src/features/ui/store/uiSlice.ts +++ b/invokeai/frontend/web/src/features/ui/store/uiSlice.ts @@ -23,7 +23,7 @@ const initialUIState: UIState = { openGenerateAccordionItems: [], openUnifiedCanvasAccordionItems: [], floatingProgressImageCoordinates: { x: 0, y: 0 }, - shouldShowProgressImage: false, + shouldShowProgressImages: false, }; const initialState: UIState = initialUIState; @@ -114,8 +114,8 @@ export const uiSlice = createSlice({ state.floatingProgressImageCoordinates = { x: x + _x, y: y + _y }; }, - shouldShowProgressImageChanged: (state, action: PayloadAction) => { - state.shouldShowProgressImage = action.payload; + shouldShowProgressImagesToggled: (state) => { + state.shouldShowProgressImages = !state.shouldShowProgressImages; }, }, }); @@ -141,7 +141,7 @@ export const { toggleGalleryPanel, openAccordionItemsChanged, floatingProgressImageMoved, - shouldShowProgressImageChanged, + shouldShowProgressImagesToggled, } = uiSlice.actions; export default uiSlice.reducer; diff --git a/invokeai/frontend/web/src/features/ui/store/uiTypes.ts b/invokeai/frontend/web/src/features/ui/store/uiTypes.ts index 309b110d4d..3a7c3057c5 100644 --- a/invokeai/frontend/web/src/features/ui/store/uiTypes.ts +++ b/invokeai/frontend/web/src/features/ui/store/uiTypes.ts @@ -20,5 +20,5 @@ export interface UIState { openGenerateAccordionItems: number[]; openUnifiedCanvasAccordionItems: number[]; floatingProgressImageCoordinates: Coordinates; - shouldShowProgressImage: boolean; + shouldShowProgressImages: boolean; } From fecb77e3449c0d4d48fbe445cfc4e882d45da97a Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Sun, 30 Apr 2023 23:39:42 +1000 Subject: [PATCH 53/68] feat(ui): `dndkit` --> `rnd` for draggable --- invokeai/frontend/web/package.json | 3 +- .../components/ProgressImagePreview.tsx | 243 +++++++++--------- .../features/ui/store/uiPersistDenylist.ts | 2 +- .../web/src/features/ui/store/uiSlice.ts | 23 +- .../web/src/features/ui/store/uiTypes.ts | 16 +- invokeai/frontend/web/yarn.lock | 70 ++--- 6 files changed, 194 insertions(+), 163 deletions(-) diff --git a/invokeai/frontend/web/package.json b/invokeai/frontend/web/package.json index 0d41e06897..d9e4f0af5c 100644 --- a/invokeai/frontend/web/package.json +++ b/invokeai/frontend/web/package.json @@ -61,8 +61,6 @@ "@chakra-ui/styled-system": "^2.9.0", "@chakra-ui/theme-tools": "^2.0.16", "@dagrejs/graphlib": "^2.1.12", - "@dnd-kit/core": "^6.0.8", - "@dnd-kit/modifiers": "^6.0.1", "@emotion/react": "^11.10.6", "@emotion/styled": "^11.10.6", "@fontsource/inter": "^4.5.15", @@ -90,6 +88,7 @@ "react-konva": "^18.2.7", "react-konva-utils": "^1.0.4", "react-redux": "^8.0.5", + "react-rnd": "^10.4.1", "react-transition-group": "^4.4.5", "react-use": "^17.4.0", "react-zoom-pan-pinch": "^3.0.7", diff --git a/invokeai/frontend/web/src/features/parameters/components/ProgressImagePreview.tsx b/invokeai/frontend/web/src/features/parameters/components/ProgressImagePreview.tsx index 085a52c4b0..90106ba81f 100644 --- a/invokeai/frontend/web/src/features/parameters/components/ProgressImagePreview.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/ProgressImagePreview.tsx @@ -1,25 +1,28 @@ -import { Box, Flex, Icon, Image, Text } from '@chakra-ui/react'; -import { useDraggable } from '@dnd-kit/core'; +import { Flex, Icon, Image, Text } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { systemSelector } from 'features/system/store/systemSelectors'; import { memo, useCallback } from 'react'; -import { CSS } from '@dnd-kit/utilities'; -import { FaEye, FaImage, FaStopwatch } from 'react-icons/fa'; +import { FaImage, FaStopwatch } from 'react-icons/fa'; import { uiSelector } from 'features/ui/store/uiSelectors'; -import { Resizable } from 're-resizable'; import IAIIconButton from 'common/components/IAIIconButton'; import { CloseIcon } from '@chakra-ui/icons'; import { useTranslation } from 'react-i18next'; -import { shouldShowProgressImagesToggled } from 'features/ui/store/uiSlice'; +import { + floatingProgressImageMoved, + floatingProgressImageResized, + shouldShowProgressImagesToggled, +} from 'features/ui/store/uiSlice'; +import { Rnd } from 'react-rnd'; +import { Rect } from 'features/ui/store/uiTypes'; const selector = createSelector([systemSelector, uiSelector], (system, ui) => { const { progressImage } = system; - const { floatingProgressImageCoordinates, shouldShowProgressImages } = ui; + const { floatingProgressImageRect, shouldShowProgressImages } = ui; return { progressImage, - coords: floatingProgressImageCoordinates, + floatingProgressImageRect, shouldShowProgressImages, }; }); @@ -27,135 +30,137 @@ const selector = createSelector([systemSelector, uiSelector], (system, ui) => { const ProgressImagePreview = () => { const dispatch = useAppDispatch(); - const { progressImage, coords, shouldShowProgressImages } = + const { progressImage, floatingProgressImageRect, shouldShowProgressImages } = useAppSelector(selector); const { t } = useTranslation(); - const { attributes, listeners, setNodeRef, transform } = useDraggable({ - id: 'progress-image', - }); - const toggleProgressImages = useCallback(() => { dispatch(shouldShowProgressImagesToggled()); }, [dispatch]); - const transformStyles = transform - ? { - transform: CSS.Translate.toString(transform), - } - : {}; - return shouldShowProgressImages ? ( - { + dispatch(floatingProgressImageMoved({ x: d.x, y: d.y })); + }} + onResizeStop={(e, direction, ref, delta, position) => { + const newRect: Partial = {}; + + console.log(ref.style.width, ref.style.height, position.x, position.y); + + if (ref.style.width) { + newRect.width = ref.style.width; + } + if (ref.style.height) { + newRect.height = ref.style.height; + } + if (position.x) { + newRect.x = position.x; + } + if (position.x) { + newRect.y = position.y; + } + + dispatch(floatingProgressImageResized(newRect)); }} > - - + - - + Progress Images + + + } + variant="ghost" + /> + + {progressImage ? ( + + - - - - Progress Images - - - } - variant="ghost" - /> - - {progressImage ? ( - - - - ) : ( - - - - )} - - - - - + /> + + ) : ( + + + + )} + + ) : ( `ui.${denylistItem}` diff --git a/invokeai/frontend/web/src/features/ui/store/uiSlice.ts b/invokeai/frontend/web/src/features/ui/store/uiSlice.ts index 86ce8c2a12..b3395b98c9 100644 --- a/invokeai/frontend/web/src/features/ui/store/uiSlice.ts +++ b/invokeai/frontend/web/src/features/ui/store/uiSlice.ts @@ -2,8 +2,7 @@ import type { PayloadAction } from '@reduxjs/toolkit'; import { createSlice } from '@reduxjs/toolkit'; import { setActiveTabReducer } from './extraReducers'; import { InvokeTabName, tabMap } from './tabMap'; -import { AddNewModelType, UIState } from './uiTypes'; -import { Coordinates } from '@dnd-kit/core/dist/types'; +import { AddNewModelType, Coordinates, Rect, UIState } from './uiTypes'; const initialUIState: UIState = { activeTab: 0, @@ -22,7 +21,7 @@ const initialUIState: UIState = { openLinearAccordionItems: [], openGenerateAccordionItems: [], openUnifiedCanvasAccordionItems: [], - floatingProgressImageCoordinates: { x: 0, y: 0 }, + floatingProgressImageRect: { x: 0, y: 0, width: 0, height: 0 }, shouldShowProgressImages: false, }; @@ -109,10 +108,19 @@ export const uiSlice = createSlice({ } }, floatingProgressImageMoved: (state, action: PayloadAction) => { - const { x, y } = state.floatingProgressImageCoordinates; - const { x: _x, y: _y } = action.payload; - - state.floatingProgressImageCoordinates = { x: x + _x, y: y + _y }; + state.floatingProgressImageRect = { + ...state.floatingProgressImageRect, + ...action.payload, + }; + }, + floatingProgressImageResized: ( + state, + action: PayloadAction> + ) => { + state.floatingProgressImageRect = { + ...state.floatingProgressImageRect, + ...action.payload, + }; }, shouldShowProgressImagesToggled: (state) => { state.shouldShowProgressImages = !state.shouldShowProgressImages; @@ -141,6 +149,7 @@ export const { toggleGalleryPanel, openAccordionItemsChanged, floatingProgressImageMoved, + floatingProgressImageResized, shouldShowProgressImagesToggled, } = uiSlice.actions; diff --git a/invokeai/frontend/web/src/features/ui/store/uiTypes.ts b/invokeai/frontend/web/src/features/ui/store/uiTypes.ts index 3a7c3057c5..a1abc6d097 100644 --- a/invokeai/frontend/web/src/features/ui/store/uiTypes.ts +++ b/invokeai/frontend/web/src/features/ui/store/uiTypes.ts @@ -1,7 +1,17 @@ -import { Coordinates } from '@dnd-kit/core/dist/types'; - export type AddNewModelType = 'ckpt' | 'diffusers' | null; +export type Coordinates = { + x: number; + y: number; +}; + +export type Dimensions = { + width: number | string; + height: number | string; +}; + +export type Rect = Coordinates & Dimensions; + export interface UIState { activeTab: number; currentTheme: string; @@ -19,6 +29,6 @@ export interface UIState { openLinearAccordionItems: number[]; openGenerateAccordionItems: number[]; openUnifiedCanvasAccordionItems: number[]; - floatingProgressImageCoordinates: Coordinates; + floatingProgressImageRect: Rect; shouldShowProgressImages: boolean; } diff --git a/invokeai/frontend/web/yarn.lock b/invokeai/frontend/web/yarn.lock index f7f9af51ef..b60071ab65 100644 --- a/invokeai/frontend/web/yarn.lock +++ b/invokeai/frontend/web/yarn.lock @@ -937,37 +937,6 @@ gonzales-pe "^4.3.0" node-source-walk "^5.0.1" -"@dnd-kit/accessibility@^3.0.0": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@dnd-kit/accessibility/-/accessibility-3.0.1.tgz#3ccbefdfca595b0a23a5dc57d3de96bc6935641c" - integrity sha512-HXRrwS9YUYQO9lFRc/49uO/VICbM+O+ZRpFDe9Pd1rwVv2PCNkRiTZRdxrDgng/UkvdC3Re9r2vwPpXXrWeFzg== - dependencies: - tslib "^2.0.0" - -"@dnd-kit/core@^6.0.8": - version "6.0.8" - resolved "https://registry.yarnpkg.com/@dnd-kit/core/-/core-6.0.8.tgz#040ae13fea9787ee078e5f0361f3b49b07f3f005" - integrity sha512-lYaoP8yHTQSLlZe6Rr9qogouGUz9oRUj4AHhDQGQzq/hqaJRpFo65X+JKsdHf8oUFBzx5A+SJPUvxAwTF2OabA== - dependencies: - "@dnd-kit/accessibility" "^3.0.0" - "@dnd-kit/utilities" "^3.2.1" - tslib "^2.0.0" - -"@dnd-kit/modifiers@^6.0.1": - version "6.0.1" - resolved "https://registry.yarnpkg.com/@dnd-kit/modifiers/-/modifiers-6.0.1.tgz#9e39b25fd6e323659604cc74488fe044d33188c8" - integrity sha512-rbxcsg3HhzlcMHVHWDuh9LCjpOVAgqbV78wLGI8tziXY3+qcMQ61qVXIvNKQFuhj75dSfD+o+PYZQ/NUk2A23A== - dependencies: - "@dnd-kit/utilities" "^3.2.1" - tslib "^2.0.0" - -"@dnd-kit/utilities@^3.2.1": - version "3.2.1" - resolved "https://registry.yarnpkg.com/@dnd-kit/utilities/-/utilities-3.2.1.tgz#53f9e2016fd2506ec49e404c289392cfff30332a" - integrity sha512-OOXqISfvBw/1REtkSK2N3Fi2EQiLMlWUlqnOK/UpOISqBZPWpE6TqL+jcPtMOkE8TqYGiURvRdPSI9hltNUjEA== - dependencies: - tslib "^2.0.0" - "@emotion/babel-plugin@^11.10.8": version "11.10.8" resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.10.8.tgz#bae325c902937665d00684038fd5294223ef9e1d" @@ -2615,6 +2584,11 @@ clone@^1.0.2: resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg== +clsx@^1.1.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12" + integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg== + code-block-writer@^12.0.0: version "12.0.0" resolved "https://registry.yarnpkg.com/code-block-writer/-/code-block-writer-12.0.0.tgz#4dd58946eb4234105aff7f0035977b2afdc2a770" @@ -3556,6 +3530,11 @@ fast-loops@^1.1.3: resolved "https://registry.yarnpkg.com/fast-loops/-/fast-loops-1.1.3.tgz#ce96adb86d07e7bf9b4822ab9c6fac9964981f75" integrity sha512-8EZzEP0eKkEEVX+drtd9mtuQ+/QrlfW/5MlwcwK5Nds6EkZ/tRzEexkzUY2mIssnAyVLT+TKHuRXmFNNXYUd6g== +fast-memoize@^2.5.1: + version "2.5.2" + resolved "https://registry.yarnpkg.com/fast-memoize/-/fast-memoize-2.5.2.tgz#79e3bb6a4ec867ea40ba0e7146816f6cdce9b57e" + integrity sha512-Ue0LwpDYErFbmNnZSF0UH6eImUwDmogUO1jyE+JbN2gsQz/jICm1Ve7t9QT0rNSsfJt+Hs4/S3GnsDVjL4HVrw== + fast-printf@^1.6.9: version "1.6.9" resolved "https://registry.yarnpkg.com/fast-printf/-/fast-printf-1.6.9.tgz#212f56570d2dc8ccdd057ee93d50dd414d07d676" @@ -5424,6 +5403,13 @@ rc@1.2.8, rc@^1.2.7, rc@^1.2.8: minimist "^1.2.0" strip-json-comments "~2.0.1" +re-resizable@6.9.6: + version "6.9.6" + resolved "https://registry.yarnpkg.com/re-resizable/-/re-resizable-6.9.6.tgz#b95d37e3821481b56ddfb1e12862940a791e827d" + integrity sha512-0xYKS5+Z0zk+vICQlcZW+g54CcJTTmHluA7JUUgvERDxnKAnytylcyPsA+BSFi759s5hPlHmBRegFrwXs2FuBQ== + dependencies: + fast-memoize "^2.5.1" + re-resizable@^6.9.9: version "6.9.9" resolved "https://registry.yarnpkg.com/re-resizable/-/re-resizable-6.9.9.tgz#99e8b31c67a62115dc9c5394b7e55892265be216" @@ -5449,6 +5435,14 @@ react-dom@^18.2.0: loose-envify "^1.1.0" scheduler "^0.23.0" +react-draggable@4.4.5: + version "4.4.5" + resolved "https://registry.yarnpkg.com/react-draggable/-/react-draggable-4.4.5.tgz#9e37fe7ce1a4cf843030f521a0a4cc41886d7e7c" + integrity sha512-OMHzJdyJbYTZo4uQE393fHcqqPYsEtkjfMgvCHr6rejT+Ezn4OZbNyGH50vv+SunC1RMvwOTSWkEODQLzw1M9g== + dependencies: + clsx "^1.1.1" + prop-types "^15.8.1" + react-dropzone@^14.2.3: version "14.2.3" resolved "https://registry.yarnpkg.com/react-dropzone/-/react-dropzone-14.2.3.tgz#0acab68308fda2d54d1273a1e626264e13d4e84b" @@ -5565,6 +5559,15 @@ react-remove-scroll@^2.5.5: use-callback-ref "^1.3.0" use-sidecar "^1.1.2" +react-rnd@^10.4.1: + version "10.4.1" + resolved "https://registry.yarnpkg.com/react-rnd/-/react-rnd-10.4.1.tgz#9e1c3f244895d7862ef03be98b2a620848c3fba1" + integrity sha512-0m887AjQZr6p2ADLNnipquqsDq4XJu/uqVqI3zuoGD19tRm6uB83HmZWydtkilNp5EWsOHbLGF4IjWMdd5du8Q== + dependencies: + re-resizable "6.9.6" + react-draggable "4.4.5" + tslib "2.3.1" + react-style-singleton@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/react-style-singleton/-/react-style-singleton-2.2.1.tgz#f99e420492b2d8f34d38308ff660b60d0b1205b4" @@ -6432,6 +6435,11 @@ tsconfig-paths@^4.0.0: minimist "^1.2.6" strip-bom "^3.0.0" +tslib@2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" + integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== + tslib@2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" From 29743a9e02e33266526ff67e87ea6f6b80a0d650 Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Mon, 1 May 2023 00:02:19 +1000 Subject: [PATCH 54/68] fix(ui): next/prev image buttons --- .../components/CurrentImagePreview.tsx | 2 +- .../gallery/components/ImageGalleryPanel.tsx | 22 ------ .../components/NextPrevImageButtons.tsx | 77 +++++++++++++------ .../features/gallery/store/gallerySlice.ts | 34 -------- 4 files changed, 55 insertions(+), 80 deletions(-) diff --git a/invokeai/frontend/web/src/features/gallery/components/CurrentImagePreview.tsx b/invokeai/frontend/web/src/features/gallery/components/CurrentImagePreview.tsx index cb666dd128..f6cfa99237 100644 --- a/invokeai/frontend/web/src/features/gallery/components/CurrentImagePreview.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/CurrentImagePreview.tsx @@ -62,7 +62,6 @@ const CurrentImagePreview = () => { }} /> )} - {!shouldShowImageDetails && } {shouldShowImageDetails && image && 'metadata' in image && ( { )} + {!shouldShowImageDetails && } ); }; diff --git a/invokeai/frontend/web/src/features/gallery/components/ImageGalleryPanel.tsx b/invokeai/frontend/web/src/features/gallery/components/ImageGalleryPanel.tsx index 4d2dd628ab..76442d340b 100644 --- a/invokeai/frontend/web/src/features/gallery/components/ImageGalleryPanel.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/ImageGalleryPanel.tsx @@ -110,28 +110,6 @@ export const ImageGalleryPanel = () => { [shouldPinGallery] ); - useHotkeys( - 'left', - () => { - dispatch(selectPrevImage()); - }, - { - enabled: !isStaging || activeTabName !== 'unifiedCanvas', - }, - [isStaging, activeTabName] - ); - - useHotkeys( - 'right', - () => { - dispatch(selectNextImage()); - }, - { - enabled: !isStaging || activeTabName !== 'unifiedCanvas', - }, - [isStaging, activeTabName] - ); - useHotkeys( 'shift+g', () => { diff --git a/invokeai/frontend/web/src/features/gallery/components/NextPrevImageButtons.tsx b/invokeai/frontend/web/src/features/gallery/components/NextPrevImageButtons.tsx index fd5902ba99..d0d25f8bc6 100644 --- a/invokeai/frontend/web/src/features/gallery/components/NextPrevImageButtons.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/NextPrevImageButtons.tsx @@ -1,18 +1,14 @@ import { ChakraProps, Flex, Grid, IconButton } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; -import { isEqual } from 'lodash-es'; -import { useState } from 'react'; +import { clamp, isEqual } from 'lodash-es'; +import { useCallback, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { FaAngleLeft, FaAngleRight } from 'react-icons/fa'; import { gallerySelector } from '../store/gallerySelectors'; import { RootState } from 'app/store/store'; -import { selectResultsEntities } from '../store/resultsSlice'; -// import { -// GalleryCategory, -// selectNextImage, -// selectPrevImage, -// } from '../store/gallerySlice'; +import { imageSelected } from '../store/gallerySlice'; +import { useHotkeys } from 'react-hotkeys-hook'; const nextPrevButtonTriggerAreaStyles: ChakraProps['sx'] = { height: '100%', @@ -40,12 +36,32 @@ export const nextPrevImageButtonsSelector = createSelector( (i) => i === selectedImage.name ); + const nextImageIndex = clamp( + currentImageIndex + 1, + 0, + state[currentCategory].ids.length - 1 + ); + + const prevImageIndex = clamp( + currentImageIndex - 1, + 0, + state[currentCategory].ids.length - 1 + ); + + const nextImageId = state[currentCategory].ids[nextImageIndex]; + const prevImageId = state[currentCategory].ids[prevImageIndex]; + + const nextImage = state[currentCategory].entities[nextImageId]; + const prevImage = state[currentCategory].entities[prevImageId]; + const imagesLength = state[currentCategory].ids.length; return { isOnFirstImage: currentImageIndex === 0, isOnLastImage: !isNaN(currentImageIndex) && currentImageIndex === imagesLength - 1, + nextImage, + prevImage, }; }, { @@ -59,28 +75,43 @@ const NextPrevImageButtons = () => { const dispatch = useAppDispatch(); const { t } = useTranslation(); - const { isOnFirstImage, isOnLastImage } = useAppSelector( - nextPrevImageButtonsSelector - ); + const { isOnFirstImage, isOnLastImage, nextImage, prevImage } = + useAppSelector(nextPrevImageButtonsSelector); const [shouldShowNextPrevButtons, setShouldShowNextPrevButtons] = useState(false); - const handleCurrentImagePreviewMouseOver = () => { + const handleCurrentImagePreviewMouseOver = useCallback(() => { setShouldShowNextPrevButtons(true); - }; + }, []); - const handleCurrentImagePreviewMouseOut = () => { + const handleCurrentImagePreviewMouseOut = useCallback(() => { setShouldShowNextPrevButtons(false); - }; + }, []); - const handleClickPrevButton = () => { - dispatch(selectPrevImage()); - }; + const handlePrevImage = useCallback(() => { + dispatch(imageSelected(prevImage)); + }, [dispatch, prevImage]); - const handleClickNextButton = () => { - dispatch(selectNextImage()); - }; + const handleNextImage = useCallback(() => { + dispatch(imageSelected(nextImage)); + }, [dispatch, nextImage]); + + useHotkeys( + 'left', + () => { + handlePrevImage(); + }, + [prevImage] + ); + + useHotkeys( + 'right', + () => { + handleNextImage(); + }, + [nextImage] + ); return ( { aria-label={t('accessibility.previousImage')} icon={} variant="unstyled" - onClick={handleClickPrevButton} + onClick={handlePrevImage} boxSize={16} sx={nextPrevButtonStyles} /> @@ -123,7 +154,7 @@ const NextPrevImageButtons = () => { aria-label={t('accessibility.nextImage')} icon={} variant="unstyled" - onClick={handleClickNextButton} + onClick={handleNextImage} boxSize={16} sx={nextPrevButtonStyles} /> diff --git a/invokeai/frontend/web/src/features/gallery/store/gallerySlice.ts b/invokeai/frontend/web/src/features/gallery/store/gallerySlice.ts index 4a7aa8a7e7..418d95734d 100644 --- a/invokeai/frontend/web/src/features/gallery/store/gallerySlice.ts +++ b/invokeai/frontend/web/src/features/gallery/store/gallerySlice.ts @@ -41,40 +41,6 @@ export const gallerySlice = createSlice({ ) => { state.selectedImage = action.payload; }, - // selectNextImage: (state) => { - // const { currentImage } = state; - // if (!currentImage) return; - // const tempImages = - // state.categories[currentImage.category as GalleryCategory].images; - - // if (currentImage) { - // const currentImageIndex = tempImages.findIndex( - // (i) => i.uuid === currentImage.uuid - // ); - // if (currentImageIndex < tempImages.length - 1) { - // const newCurrentImage = tempImages[currentImageIndex + 1]; - // state.currentImage = newCurrentImage; - // state.currentImageUuid = newCurrentImage.uuid; - // } - // } - // }, - // selectPrevImage: (state) => { - // const { currentImage } = state; - // if (!currentImage) return; - // const tempImages = - // state.categories[currentImage.category as GalleryCategory].images; - - // if (currentImage) { - // const currentImageIndex = tempImages.findIndex( - // (i) => i.uuid === currentImage.uuid - // ); - // if (currentImageIndex > 0) { - // const newCurrentImage = tempImages[currentImageIndex - 1]; - // state.currentImage = newCurrentImage; - // state.currentImageUuid = newCurrentImage.uuid; - // } - // } - // }, setGalleryImageMinimumWidth: (state, action: PayloadAction) => { state.galleryImageMinimumWidth = action.payload; }, From d4b250d50924b4787d82a9037a77dde4efb17103 Mon Sep 17 00:00:00 2001 From: blessedcoolant <54517381+blessedcoolant@users.noreply.github.com> Date: Mon, 1 May 2023 10:45:27 +1200 Subject: [PATCH 55/68] feat(ui): Add auto show progress previews setting --- invokeai/frontend/web/public/locales/en.json | 1 + .../frontend/web/src/app/components/App.tsx | 123 ++++++++---------- .../web/src/app/components/InvokeAIUI.tsx | 9 +- .../components/ProgressImagePreview.tsx | 59 ++++++--- .../SettingsModal/SettingsModal.tsx | 16 ++- .../web/src/features/ui/store/uiSlice.ts | 14 +- .../web/src/features/ui/store/uiTypes.ts | 1 + 7 files changed, 123 insertions(+), 100 deletions(-) diff --git a/invokeai/frontend/web/public/locales/en.json b/invokeai/frontend/web/public/locales/en.json index e4e49138dc..876cd96b39 100644 --- a/invokeai/frontend/web/public/locales/en.json +++ b/invokeai/frontend/web/public/locales/en.json @@ -527,6 +527,7 @@ "useCanvasBeta": "Use Canvas Beta Layout", "enableImageDebugging": "Enable Image Debugging", "useSlidersForAll": "Use Sliders For All Options", + "autoShowProgress": "Auto Show Progress Images", "resetWebUI": "Reset Web UI", "resetWebUIDesc1": "Resetting the web UI only resets the browser's local cache of your images and remembered settings. It does not delete any images from disk.", "resetWebUIDesc2": "If images aren't showing up in the gallery or something else isn't working, please try resetting before submitting an issue on GitHub.", diff --git a/invokeai/frontend/web/src/app/components/App.tsx b/invokeai/frontend/web/src/app/components/App.tsx index 1d5ffb0079..a7487fa323 100644 --- a/invokeai/frontend/web/src/app/components/App.tsx +++ b/invokeai/frontend/web/src/app/components/App.tsx @@ -28,9 +28,9 @@ import { configChanged } from 'features/system/store/configSlice'; import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus'; import { useLogger } from 'app/logging/useLogger'; import ProgressImagePreview from 'features/parameters/components/ProgressImagePreview'; -import { DndContext, DragEndEvent } from '@dnd-kit/core'; +// import { DndContext, DragEndEvent } from '@dnd-kit/core'; import { floatingProgressImageMoved } from 'features/ui/store/uiSlice'; -import { restrictToWindowEdges } from '@dnd-kit/modifiers'; +// import { restrictToWindowEdges } from '@dnd-kit/modifiers'; const DEFAULT_CONFIG = {}; @@ -67,76 +67,65 @@ const App = ({ config = DEFAULT_CONFIG, children }: Props) => { setLoadingOverridden(true); }, []); - const handleDragEnd = useCallback( - (event: DragEndEvent) => { - dispatch( - floatingProgressImageMoved({ x: event.delta.x, y: event.delta.y }) - ); - }, - [dispatch] - ); - return ( - - - {isLightboxEnabled && } - - - + {isLightboxEnabled && } + + + + {children || } + - {children || } - - - - - - + + + + + - - {!isApplicationReady && !loadingOverridden && ( - - - - - - - )} - + + {!isApplicationReady && !loadingOverridden && ( + + + + + + + )} + - - - - - - - - - + + + + + + + + ); }; diff --git a/invokeai/frontend/web/src/app/components/InvokeAIUI.tsx b/invokeai/frontend/web/src/app/components/InvokeAIUI.tsx index ca48770119..97a8be6fc1 100644 --- a/invokeai/frontend/web/src/app/components/InvokeAIUI.tsx +++ b/invokeai/frontend/web/src/app/components/InvokeAIUI.tsx @@ -1,11 +1,4 @@ -import React, { - lazy, - memo, - PropsWithChildren, - useCallback, - useEffect, - useState, -} from 'react'; +import React, { lazy, memo, PropsWithChildren, useEffect } from 'react'; import { Provider } from 'react-redux'; import { PersistGate } from 'redux-persist/integration/react'; import { store } from 'app/store/store'; diff --git a/invokeai/frontend/web/src/features/parameters/components/ProgressImagePreview.tsx b/invokeai/frontend/web/src/features/parameters/components/ProgressImagePreview.tsx index 90106ba81f..db487577f1 100644 --- a/invokeai/frontend/web/src/features/parameters/components/ProgressImagePreview.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/ProgressImagePreview.tsx @@ -2,7 +2,7 @@ import { Flex, Icon, Image, Text } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { systemSelector } from 'features/system/store/systemSelectors'; -import { memo, useCallback } from 'react'; +import { memo } from 'react'; import { FaImage, FaStopwatch } from 'react-icons/fa'; import { uiSelector } from 'features/ui/store/uiSelectors'; import IAIIconButton from 'common/components/IAIIconButton'; @@ -11,35 +11,49 @@ import { useTranslation } from 'react-i18next'; import { floatingProgressImageMoved, floatingProgressImageResized, - shouldShowProgressImagesToggled, + setShouldShowProgressImages, } from 'features/ui/store/uiSlice'; import { Rnd } from 'react-rnd'; import { Rect } from 'features/ui/store/uiTypes'; +import { isEqual } from 'lodash'; -const selector = createSelector([systemSelector, uiSelector], (system, ui) => { - const { progressImage } = system; - const { floatingProgressImageRect, shouldShowProgressImages } = ui; +const selector = createSelector( + [systemSelector, uiSelector], + (system, ui) => { + const { progressImage, isProcessing } = system; + const { + floatingProgressImageRect, + shouldShowProgressImages, + shouldAutoShowProgressImages, + } = ui; - return { - progressImage, - floatingProgressImageRect, - shouldShowProgressImages, - }; -}); + const showProgressWindow = + shouldAutoShowProgressImages && isProcessing + ? true + : shouldShowProgressImages; + + return { + progressImage, + floatingProgressImageRect, + showProgressWindow, + }; + }, + { + memoizeOptions: { + resultEqualityCheck: isEqual, + }, + } +); const ProgressImagePreview = () => { const dispatch = useAppDispatch(); - const { progressImage, floatingProgressImageRect, shouldShowProgressImages } = + const { showProgressWindow, progressImage, floatingProgressImageRect } = useAppSelector(selector); const { t } = useTranslation(); - const toggleProgressImages = useCallback(() => { - dispatch(shouldShowProgressImagesToggled()); - }, [dispatch]); - - return shouldShowProgressImages ? ( + return showProgressWindow ? ( { dispatch(setShouldShowProgressImages(false))} aria-label={t('ui.hideProgressImages')} size="xs" icon={} @@ -141,7 +155,6 @@ const ProgressImagePreview = () => { maxWidth: '100%', maxHeight: '100%', height: 'auto', - imageRendering: 'pixelated', borderRadius: 'base', p: 2, }} @@ -163,9 +176,13 @@ const ProgressImagePreview = () => { ) : ( dispatch(setShouldShowProgressImages(true))} tooltip={t('ui.showProgressImages')} - sx={{ position: 'absolute', bottom: 4, insetInlineStart: 4 }} + sx={{ + position: 'absolute', + bottom: 4, + insetInlineStart: 4, + }} aria-label={t('ui.showProgressImages')} icon={} /> diff --git a/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsModal.tsx b/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsModal.tsx index 5cadae68be..0ca0b496fc 100644 --- a/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsModal.tsx +++ b/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsModal.tsx @@ -28,6 +28,7 @@ import { } from 'features/system/store/systemSlice'; import { uiSelector } from 'features/ui/store/uiSelectors'; import { + setShouldAutoShowProgressImages, setShouldUseCanvasBetaLayout, setShouldUseSliders, } from 'features/ui/store/uiSlice'; @@ -50,7 +51,11 @@ const selector = createSelector( shouldLogToConsole, } = system; - const { shouldUseCanvasBetaLayout, shouldUseSliders } = ui; + const { + shouldUseCanvasBetaLayout, + shouldUseSliders, + shouldAutoShowProgressImages, + } = ui; return { shouldConfirmOnDelete, @@ -58,6 +63,7 @@ const selector = createSelector( enableImageDebugging, shouldUseCanvasBetaLayout, shouldUseSliders, + shouldAutoShowProgressImages, consoleLogLevel, shouldLogToConsole, }; @@ -108,6 +114,7 @@ const SettingsModal = ({ children }: SettingsModalProps) => { enableImageDebugging, shouldUseCanvasBetaLayout, shouldUseSliders, + shouldAutoShowProgressImages, consoleLogLevel, shouldLogToConsole, } = useAppSelector(selector); @@ -186,6 +193,13 @@ const SettingsModal = ({ children }: SettingsModalProps) => { dispatch(setShouldUseSliders(e.target.checked)) } /> + ) => + dispatch(setShouldAutoShowProgressImages(e.target.checked)) + } + /> diff --git a/invokeai/frontend/web/src/features/ui/store/uiSlice.ts b/invokeai/frontend/web/src/features/ui/store/uiSlice.ts index b3395b98c9..11abf6a20d 100644 --- a/invokeai/frontend/web/src/features/ui/store/uiSlice.ts +++ b/invokeai/frontend/web/src/features/ui/store/uiSlice.ts @@ -23,6 +23,7 @@ const initialUIState: UIState = { openUnifiedCanvasAccordionItems: [], floatingProgressImageRect: { x: 0, y: 0, width: 0, height: 0 }, shouldShowProgressImages: false, + shouldAutoShowProgressImages: false, }; const initialState: UIState = initialUIState; @@ -122,8 +123,14 @@ export const uiSlice = createSlice({ ...action.payload, }; }, - shouldShowProgressImagesToggled: (state) => { - state.shouldShowProgressImages = !state.shouldShowProgressImages; + setShouldShowProgressImages: (state, action: PayloadAction) => { + state.shouldShowProgressImages = action.payload; + }, + setShouldAutoShowProgressImages: ( + state, + action: PayloadAction + ) => { + state.shouldAutoShowProgressImages = action.payload; }, }, }); @@ -150,7 +157,8 @@ export const { openAccordionItemsChanged, floatingProgressImageMoved, floatingProgressImageResized, - shouldShowProgressImagesToggled, + setShouldShowProgressImages, + setShouldAutoShowProgressImages, } = uiSlice.actions; export default uiSlice.reducer; diff --git a/invokeai/frontend/web/src/features/ui/store/uiTypes.ts b/invokeai/frontend/web/src/features/ui/store/uiTypes.ts index a1abc6d097..bdcf0a3c30 100644 --- a/invokeai/frontend/web/src/features/ui/store/uiTypes.ts +++ b/invokeai/frontend/web/src/features/ui/store/uiTypes.ts @@ -31,4 +31,5 @@ export interface UIState { openUnifiedCanvasAccordionItems: number[]; floatingProgressImageRect: Rect; shouldShowProgressImages: boolean; + shouldAutoShowProgressImages: boolean; } From a4313c26cbf10a689403e69e04226009b84e47b5 Mon Sep 17 00:00:00 2001 From: blessedcoolant <54517381+blessedcoolant@users.noreply.github.com> Date: Mon, 1 May 2023 10:56:35 +1200 Subject: [PATCH 56/68] fix: Do not hide Preview button & color code it --- .../components/ProgressImagePreview.tsx | 246 +++++++++--------- 1 file changed, 130 insertions(+), 116 deletions(-) diff --git a/invokeai/frontend/web/src/features/parameters/components/ProgressImagePreview.tsx b/invokeai/frontend/web/src/features/parameters/components/ProgressImagePreview.tsx index db487577f1..28dd6adf4f 100644 --- a/invokeai/frontend/web/src/features/parameters/components/ProgressImagePreview.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/ProgressImagePreview.tsx @@ -53,88 +53,50 @@ const ProgressImagePreview = () => { const { t } = useTranslation(); - return showProgressWindow ? ( - { - dispatch(floatingProgressImageMoved({ x: d.x, y: d.y })); - }} - onResizeStop={(e, direction, ref, delta, position) => { - const newRect: Partial = {}; + return ( + <> + {showProgressWindow && ( + { + dispatch(floatingProgressImageMoved({ x: d.x, y: d.y })); + }} + onResizeStop={(e, direction, ref, delta, position) => { + const newRect: Partial = {}; - console.log(ref.style.width, ref.style.height, position.x, position.y); + console.log( + ref.style.width, + ref.style.height, + position.x, + position.y + ); - if (ref.style.width) { - newRect.width = ref.style.width; - } - if (ref.style.height) { - newRect.height = ref.style.height; - } - if (position.x) { - newRect.x = position.x; - } - if (position.x) { - newRect.y = position.y; - } + if (ref.style.width) { + newRect.width = ref.style.width; + } + if (ref.style.height) { + newRect.height = ref.style.height; + } + if (position.x) { + newRect.x = position.x; + } + if (position.x) { + newRect.y = position.y; + } - dispatch(floatingProgressImageResized(newRect)); - }} - > - - - - - Progress Images - - - dispatch(setShouldShowProgressImages(false))} - aria-label={t('ui.hideProgressImages')} - size="xs" - icon={} - variant="ghost" - /> - - {progressImage ? ( { h: 'full', alignItems: 'center', justifyContent: 'center', + flexDir: 'column', + boxShadow: 'dark-lg', + bg: 'base.800', + borderRadius: 'base', }} > - + > + + + Progress Images + + + dispatch(setShouldShowProgressImages(false))} + aria-label={t('ui.hideProgressImages')} + size="xs" + icon={} + variant="ghost" + /> + + {progressImage ? ( + + + + ) : ( + + + + )} - ) : ( - - - - )} - - - ) : ( - dispatch(setShouldShowProgressImages(true))} - tooltip={t('ui.showProgressImages')} - sx={{ - position: 'absolute', - bottom: 4, - insetInlineStart: 4, - }} - aria-label={t('ui.showProgressImages')} - icon={} - /> + + )} + + dispatch(setShouldShowProgressImages(!showProgressWindow)) + } + tooltip={t('ui.showProgressImages')} + sx={{ + position: 'absolute', + bottom: 4, + insetInlineStart: 4, + background: showProgressWindow ? 'accent.600' : 'base.700', + _hover: { + background: showProgressWindow ? 'accent.500' : 'base.600', + }, + }} + aria-label={t('ui.showProgressImages')} + icon={} + /> + ); }; From a6be44789bdc4c1243a56a244a072f972b537288 Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Mon, 1 May 2023 10:22:08 +1000 Subject: [PATCH 57/68] fix(ui): progress image rerender, checkbox --- .../frontend/web/src/app/components/App.tsx | 3 - .../parameters/components/ProgressImage.tsx | 67 +++++++++++++++ .../components/ProgressImagePreview.tsx | 81 +++++-------------- 3 files changed, 88 insertions(+), 63 deletions(-) create mode 100644 invokeai/frontend/web/src/features/parameters/components/ProgressImage.tsx diff --git a/invokeai/frontend/web/src/app/components/App.tsx b/invokeai/frontend/web/src/app/components/App.tsx index a7487fa323..3aebfa4097 100644 --- a/invokeai/frontend/web/src/app/components/App.tsx +++ b/invokeai/frontend/web/src/app/components/App.tsx @@ -28,9 +28,6 @@ import { configChanged } from 'features/system/store/configSlice'; import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus'; import { useLogger } from 'app/logging/useLogger'; import ProgressImagePreview from 'features/parameters/components/ProgressImagePreview'; -// import { DndContext, DragEndEvent } from '@dnd-kit/core'; -import { floatingProgressImageMoved } from 'features/ui/store/uiSlice'; -// import { restrictToWindowEdges } from '@dnd-kit/modifiers'; const DEFAULT_CONFIG = {}; diff --git a/invokeai/frontend/web/src/features/parameters/components/ProgressImage.tsx b/invokeai/frontend/web/src/features/parameters/components/ProgressImage.tsx new file mode 100644 index 0000000000..869f4dbc63 --- /dev/null +++ b/invokeai/frontend/web/src/features/parameters/components/ProgressImage.tsx @@ -0,0 +1,67 @@ +import { Flex, Icon, Image } from '@chakra-ui/react'; +import { createSelector } from '@reduxjs/toolkit'; +import { useAppSelector } from 'app/store/storeHooks'; +import { systemSelector } from 'features/system/store/systemSelectors'; +import { isEqual } from 'lodash-es'; +import { memo } from 'react'; +import { FaImage } from 'react-icons/fa'; + +const selector = createSelector( + [systemSelector], + (system) => { + const { progressImage } = system; + + return { + progressImage, + }; + }, + { + memoizeOptions: { + resultEqualityCheck: isEqual, + }, + } +); + +const ProgressImage = () => { + const { progressImage } = useAppSelector(selector); + return progressImage ? ( + + + + ) : ( + + + + ); +}; + +export default memo(ProgressImage); diff --git a/invokeai/frontend/web/src/features/parameters/components/ProgressImagePreview.tsx b/invokeai/frontend/web/src/features/parameters/components/ProgressImagePreview.tsx index 28dd6adf4f..9a54e37463 100644 --- a/invokeai/frontend/web/src/features/parameters/components/ProgressImagePreview.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/ProgressImagePreview.tsx @@ -1,9 +1,9 @@ -import { Flex, Icon, Image, Text } from '@chakra-ui/react'; +import { Flex, Text } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { systemSelector } from 'features/system/store/systemSelectors'; import { memo } from 'react'; -import { FaImage, FaStopwatch } from 'react-icons/fa'; +import { FaStopwatch } from 'react-icons/fa'; import { uiSelector } from 'features/ui/store/uiSelectors'; import IAIIconButton from 'common/components/IAIIconButton'; import { CloseIcon } from '@chakra-ui/icons'; @@ -16,11 +16,12 @@ import { import { Rnd } from 'react-rnd'; import { Rect } from 'features/ui/store/uiTypes'; import { isEqual } from 'lodash'; +import ProgressImage from './ProgressImage'; const selector = createSelector( [systemSelector, uiSelector], (system, ui) => { - const { progressImage, isProcessing } = system; + const { isProcessing } = system; const { floatingProgressImageRect, shouldShowProgressImages, @@ -33,7 +34,6 @@ const selector = createSelector( : shouldShowProgressImages; return { - progressImage, floatingProgressImageRect, showProgressWindow, }; @@ -48,13 +48,28 @@ const selector = createSelector( const ProgressImagePreview = () => { const dispatch = useAppDispatch(); - const { showProgressWindow, progressImage, floatingProgressImageRect } = + const { showProgressWindow, floatingProgressImageRect } = useAppSelector(selector); const { t } = useTranslation(); return ( <> + {' '} + + dispatch(setShouldShowProgressImages(!showProgressWindow)) + } + tooltip={t('ui.showProgressImages')} + isChecked={showProgressWindow} + sx={{ + position: 'absolute', + bottom: 4, + insetInlineStart: 4, + }} + aria-label={t('ui.showProgressImages')} + icon={} + /> {showProgressWindow && ( { variant="ghost" /> - {progressImage ? ( - - - - ) : ( - - - - )} + )} - - dispatch(setShouldShowProgressImages(!showProgressWindow)) - } - tooltip={t('ui.showProgressImages')} - sx={{ - position: 'absolute', - bottom: 4, - insetInlineStart: 4, - background: showProgressWindow ? 'accent.600' : 'base.700', - _hover: { - background: showProgressWindow ? 'accent.500' : 'base.600', - }, - }} - aria-label={t('ui.showProgressImages')} - icon={} - /> ); }; From b49d76ebee7429823d57229837129ebf1591fb07 Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Mon, 1 May 2023 16:54:27 +1000 Subject: [PATCH 58/68] feat(nodes): fix image to image `fit` param it was ignored previously. --- invokeai/app/invocations/generate.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/invokeai/app/invocations/generate.py b/invokeai/app/invocations/generate.py index df79baa0f3..ba25cd2e6a 100644 --- a/invokeai/app/invocations/generate.py +++ b/invokeai/app/invocations/generate.py @@ -150,6 +150,9 @@ class ImageToImageInvocation(TextToImageInvocation): ) mask = None + if self.fit: + image = image.resize((self.width, self.height)) + # Handle invalid model parameter model = choose_model(context.services.model_manager, self.model) From 276dfc591bb4ffa70e005e356de39c6ad02c5ae8 Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Mon, 1 May 2023 16:55:05 +1000 Subject: [PATCH 59/68] feat(ui): disable w/h when img2img & not fit --- .../MainParameters/HeightSlider.tsx | 27 ++++++++++++++++--- .../components/MainParameters/WidthSlider.tsx | 26 +++++++++++++++--- 2 files changed, 45 insertions(+), 8 deletions(-) diff --git a/invokeai/frontend/web/src/features/parameters/components/MainParameters/HeightSlider.tsx b/invokeai/frontend/web/src/features/parameters/components/MainParameters/HeightSlider.tsx index 2609ae0e40..35e97fb266 100644 --- a/invokeai/frontend/web/src/features/parameters/components/MainParameters/HeightSlider.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/MainParameters/HeightSlider.tsx @@ -13,17 +13,35 @@ const selector = createSelector( (generation, hotkeys, config) => { const { initial, min, sliderMax, inputMax, fineStep, coarseStep } = config.sd.height; - const { height } = generation; + const { height, shouldFitToWidthHeight, isImageToImageEnabled } = + generation; const step = hotkeys.shift ? fineStep : coarseStep; - return { height, initial, min, sliderMax, inputMax, step }; + return { + height, + initial, + min, + sliderMax, + inputMax, + step, + shouldFitToWidthHeight, + isImageToImageEnabled, + }; } ); const HeightSlider = () => { - const { height, initial, min, sliderMax, inputMax, step } = - useAppSelector(selector); + const { + height, + initial, + min, + sliderMax, + inputMax, + step, + shouldFitToWidthHeight, + isImageToImageEnabled, + } = useAppSelector(selector); const dispatch = useAppDispatch(); const { t } = useTranslation(); @@ -40,6 +58,7 @@ const HeightSlider = () => { return ( { const { initial, min, sliderMax, inputMax, fineStep, coarseStep } = config.sd.width; - const { width } = generation; + const { width, shouldFitToWidthHeight, isImageToImageEnabled } = generation; const step = hotkeys.shift ? fineStep : coarseStep; - return { width, initial, min, sliderMax, inputMax, step }; + return { + width, + initial, + min, + sliderMax, + inputMax, + step, + shouldFitToWidthHeight, + isImageToImageEnabled, + }; } ); const WidthSlider = () => { - const { width, initial, min, sliderMax, inputMax, step } = - useAppSelector(selector); + const { + width, + initial, + min, + sliderMax, + inputMax, + step, + shouldFitToWidthHeight, + isImageToImageEnabled, + } = useAppSelector(selector); const dispatch = useAppDispatch(); const { t } = useTranslation(); @@ -40,6 +57,7 @@ const WidthSlider = () => { return ( Date: Mon, 1 May 2023 16:27:44 -0400 Subject: [PATCH 60/68] use logger in ApiDependencies --- invokeai/app/api/dependencies.py | 5 ++++- invokeai/app/api_app.py | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/invokeai/app/api/dependencies.py b/invokeai/app/api/dependencies.py index 5f4a66ce6b..99127c4332 100644 --- a/invokeai/app/api/dependencies.py +++ b/invokeai/app/api/dependencies.py @@ -3,6 +3,7 @@ import os import invokeai.backend.util.logging as logger +from typing import types from ..services.default_graphs import create_system_graphs from ..services.latent_storage import DiskLatentsStorage, ForwardCacheLatentsStorage @@ -42,13 +43,15 @@ class ApiDependencies: invoker: Invoker = None @staticmethod - def initialize(config, event_handler_id: int): + def initialize(config, event_handler_id: int, logger: types.ModuleType=logger): Globals.try_patchmatch = config.patchmatch Globals.always_use_cpu = config.always_use_cpu Globals.internet_available = config.internet_available and check_internet() Globals.disable_xformers = not config.xformers Globals.ckpt_convert = config.ckpt_convert + # TO DO: Use the config to select the logger rather than use the default + # invokeai logging module logger.info(f"Internet connectivity is {Globals.internet_available}") events = FastAPIEventService(event_handler_id) diff --git a/invokeai/app/api_app.py b/invokeai/app/api_app.py index ab05cb3344..f935de542e 100644 --- a/invokeai/app/api_app.py +++ b/invokeai/app/api_app.py @@ -3,6 +3,7 @@ import asyncio from inspect import signature import uvicorn +import invokeai.backend.util.logging as logger from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from fastapi.openapi.docs import get_redoc_html, get_swagger_ui_html @@ -16,7 +17,6 @@ from ..backend import Args from .api.dependencies import ApiDependencies from .api.routers import images, sessions, models from .api.sockets import SocketIO -from .invocations import * from .invocations.baseinvocation import BaseInvocation # Create the app @@ -56,7 +56,7 @@ async def startup_event(): config.parse_args() ApiDependencies.initialize( - config=config, event_handler_id=event_handler_id + config=config, event_handler_id=event_handler_id, logger=logger ) From d14a7d756e075d467f0dcc79a76c3494bbeb7c81 Mon Sep 17 00:00:00 2001 From: Eugene Date: Mon, 1 May 2023 11:13:16 -0400 Subject: [PATCH 61/68] nodes-api: enforce single thread for the processor On hyperthreaded CPUs we get two threads operating on the queue by default on each core. This cases two threads to process queue items. This results in pytorch errors and sometimes generates garbage. Locking this to single thread makes sense because we are bound by the number of GPUs in the system, not by CPU cores. And to parallelize across GPUs we should just start multiple processors (and use async instead of threading) Fixes #3289 --- invokeai/app/services/processor.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/invokeai/app/services/processor.py b/invokeai/app/services/processor.py index c622906750..35cbcd5068 100644 --- a/invokeai/app/services/processor.py +++ b/invokeai/app/services/processor.py @@ -1,5 +1,5 @@ import traceback -from threading import Event, Thread +from threading import Event, Thread, BoundedSemaphore from ..invocations.baseinvocation import InvocationContext from .invocation_queue import InvocationQueueItem @@ -10,8 +10,11 @@ class DefaultInvocationProcessor(InvocationProcessorABC): __invoker_thread: Thread __stop_event: Event __invoker: Invoker + __threadLimit: BoundedSemaphore def start(self, invoker) -> None: + # if we do want multithreading at some point, we could make this configurable + self.__threadLimit = BoundedSemaphore(1) self.__invoker = invoker self.__stop_event = Event() self.__invoker_thread = Thread( @@ -20,7 +23,7 @@ class DefaultInvocationProcessor(InvocationProcessorABC): kwargs=dict(stop_event=self.__stop_event), ) self.__invoker_thread.daemon = ( - True # TODO: probably better to just not use threads? + True # TODO: make async and do not use threads ) self.__invoker_thread.start() @@ -29,6 +32,7 @@ class DefaultInvocationProcessor(InvocationProcessorABC): def __process(self, stop_event: Event): try: + self.__threadLimit.acquire() while not stop_event.is_set(): queue_item: InvocationQueueItem = self.__invoker.services.queue.get() if not queue_item: # Probably stopping @@ -110,7 +114,7 @@ class DefaultInvocationProcessor(InvocationProcessorABC): ) pass - + # Check queue to see if this is canceled, and skip if so if self.__invoker.services.queue.is_canceled( graph_execution_state.id @@ -127,4 +131,6 @@ class DefaultInvocationProcessor(InvocationProcessorABC): ) except KeyboardInterrupt: - ... # Log something? + pass # Log something? KeyboardInterrupt is probably not going to be seen by the processor + finally: + self.__threadLimit.release() From d39de0ad38d5ef278275594aeb808f6dfcf10d15 Mon Sep 17 00:00:00 2001 From: Eugene Date: Mon, 1 May 2023 17:30:20 -0400 Subject: [PATCH 62/68] fix(nodes): fix duplicate Invoker start/stop events --- invokeai/app/services/invoker.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/invokeai/app/services/invoker.py b/invokeai/app/services/invoker.py index e3fa6da851..a7c9ae444d 100644 --- a/invokeai/app/services/invoker.py +++ b/invokeai/app/services/invoker.py @@ -49,7 +49,7 @@ class Invoker: new_state = GraphExecutionState(graph=Graph() if graph is None else graph) self.services.graph_execution_manager.set(new_state) return new_state - + def cancel(self, graph_execution_state_id: str) -> None: """Cancels the given execution state""" self.services.queue.cancel(graph_execution_state_id) @@ -71,18 +71,12 @@ class Invoker: for service in vars(self.services): self.__start_service(getattr(self.services, service)) - for service in vars(self.services): - self.__start_service(getattr(self.services, service)) - def stop(self) -> None: """Stops the invoker. A new invoker will have to be created to execute further.""" # First stop all services for service in vars(self.services): self.__stop_service(getattr(self.services, service)) - for service in vars(self.services): - self.__stop_service(getattr(self.services, service)) - self.services.queue.put(None) From 475b6bef53501a91b9f96d70a944e9a7eb2e41f1 Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Mon, 1 May 2023 16:04:25 +1000 Subject: [PATCH 63/68] feat(ui): use windowing for gallery vastly improves the gallery performance when many images are loaded. - `react-virtuoso` to do the virtualized list - `overlayscrollbars` for a scrollbar --- invokeai/frontend/web/package.json | 3 + .../app/components/ThemeLocaleProvider.tsx | 2 + .../gallery/components/HoverableImage.tsx | 61 ++--- .../components/ImageGalleryContent.tsx | 239 ++++++++++++------ .../web/src/theme/css/overlayscrollbars.css | 48 ++++ invokeai/frontend/web/yarn.lock | 15 ++ 6 files changed, 261 insertions(+), 107 deletions(-) create mode 100644 invokeai/frontend/web/src/theme/css/overlayscrollbars.css diff --git a/invokeai/frontend/web/package.json b/invokeai/frontend/web/package.json index d9e4f0af5c..feb2ea1200 100644 --- a/invokeai/frontend/web/package.json +++ b/invokeai/frontend/web/package.json @@ -76,6 +76,8 @@ "i18next-http-backend": "^2.2.0", "konva": "^9.0.1", "lodash-es": "^4.17.21", + "overlayscrollbars": "^2.1.1", + "overlayscrollbars-react": "^0.5.0", "patch-package": "^7.0.0", "re-resizable": "^6.9.9", "react": "^18.2.0", @@ -91,6 +93,7 @@ "react-rnd": "^10.4.1", "react-transition-group": "^4.4.5", "react-use": "^17.4.0", + "react-virtuoso": "^4.3.3", "react-zoom-pan-pinch": "^3.0.7", "reactflow": "^11.7.0", "redux-deep-persist": "^1.0.7", diff --git a/invokeai/frontend/web/src/app/components/ThemeLocaleProvider.tsx b/invokeai/frontend/web/src/app/components/ThemeLocaleProvider.tsx index e574456e37..f0e2e75240 100644 --- a/invokeai/frontend/web/src/app/components/ThemeLocaleProvider.tsx +++ b/invokeai/frontend/web/src/app/components/ThemeLocaleProvider.tsx @@ -18,6 +18,8 @@ import '@fontsource/inter/600.css'; import '@fontsource/inter/700.css'; import '@fontsource/inter/800.css'; import '@fontsource/inter/900.css'; +import 'overlayscrollbars/overlayscrollbars.css'; +import 'theme/css/overlayscrollbars.css'; type ThemeLocaleProviderProps = { children: ReactNode; diff --git a/invokeai/frontend/web/src/features/gallery/components/HoverableImage.tsx b/invokeai/frontend/web/src/features/gallery/components/HoverableImage.tsx index d0ff9aee40..032784fbf9 100644 --- a/invokeai/frontend/web/src/features/gallery/components/HoverableImage.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/HoverableImage.tsx @@ -5,6 +5,7 @@ import { Image, MenuItem, MenuList, + Skeleton, useDisclosure, useTheme, useToast, @@ -12,7 +13,7 @@ import { import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { imageSelected } from 'features/gallery/store/gallerySlice'; import { DragEvent, memo, useCallback, useState } from 'react'; -import { FaCheck, FaExpand, FaShare, FaTrash } from 'react-icons/fa'; +import { FaCheck, FaExpand, FaImage, FaShare, FaTrash } from 'react-icons/fa'; import DeleteImageModal from './DeleteImageModal'; import { ContextMenu } from 'chakra-ui-contextmenu'; import * as InvokeAI from 'app/types/invokeai'; @@ -268,58 +269,48 @@ const HoverableImage = memo((props: HoverableImageProps) => { userSelect="none" draggable={true} onDragStart={handleDragStart} + onClick={handleSelectImage} ref={ref} sx={{ - padding: 2, display: 'flex', justifyContent: 'center', + alignItems: 'center', + w: 'full', + h: 'full', transition: 'transform 0.2s ease-out', - _hover: { - cursor: 'pointer', - - zIndex: 2, - }, - _before: { - content: '""', - display: 'block', - paddingBottom: '100%', - }, + aspectRatio: '1/1', }} > } sx={{ - position: 'absolute', width: '100%', height: '100%', maxWidth: '100%', maxHeight: '100%', - top: '50%', - transform: 'translate(-50%,-50%)', - ...(direction === 'rtl' - ? { insetInlineEnd: '50%' } - : { insetInlineStart: '50%' }), }} /> - - {isSelected && ( + {isSelected && ( + { fill: 'ok.500', }} /> - )} - - {isHovered && galleryImageMinimumWidth >= 64 && ( + + )} + {isHovered && galleryImageMinimumWidth >= 100 && ( { const { t } = useTranslation(); const resizeObserverRef = useRef(null); const [shouldShouldIconButtons, setShouldShouldIconButtons] = useState(true); + const rootRef = useRef(null); + const [scroller, setScroller] = useState(null); + const [initialize, osInstance] = useOverlayScrollbars({ + defer: true, + options: { + scrollbars: { + visibility: 'auto', + autoHide: 'leave', + autoHideDelay: 1300, + theme: 'os-theme-dark', + }, + overflow: { x: 'hidden' }, + }, + }); const { // images, currentCategory, shouldPinGallery, galleryImageMinimumWidth, - galleryGridTemplateColumns, galleryImageObjectFit, shouldAutoSwitchToNewImages, - // areMoreImagesAvailable, shouldUseSingleGalleryColumn, selectedImage, } = useAppSelector(imageGallerySelector); @@ -85,9 +110,6 @@ const ImageGalleryContent = () => { const { images, areMoreImagesAvailable, isLoading } = useAppSelector(gallerySelector); - // const handleClickLoadMore = () => { - // dispatch(requestImages(currentCategory)); - // }; const handleClickLoadMore = () => { if (currentCategory === 'results') { dispatch(receivedResultImagesPage()); @@ -129,6 +151,25 @@ const ImageGalleryContent = () => { return () => resizeObserver.disconnect(); // clean up }, []); + useEffect(() => { + const { current: root } = rootRef; + if (scroller && root) { + initialize({ + target: root, + elements: { + viewport: scroller, + }, + }); + } + return () => osInstance()?.destroy(); + }, [scroller, initialize, osInstance]); + + const setScrollerRef = useCallback((ref: HTMLElement | Window | null) => { + if (ref instanceof HTMLElement) { + setScroller(ref); + } + }, []); + return ( { /> - - - {images.length || areMoreImagesAvailable ? ( - <> - - {images.map((image) => { - const { name } = image; - const isSelected = selectedImage?.name === name; - return ( - - ); - })} - - - {areMoreImagesAvailable - ? t('gallery.loadMore') - : t('gallery.allImagesLoaded')} - - - ) : ( - + {images.length || areMoreImagesAvailable ? ( + <> + + {shouldUseSingleGalleryColumn ? ( + setScrollerRef(ref)} + itemContent={(index, image) => { + const { name } = image; + const isSelected = selectedImage?.name === name; + + return ( + + + + ); + }} + /> + ) : ( + { + const { name } = image; + const isSelected = selectedImage?.name === name; + + return ( + + ); + }} + /> + )} + + - - {t('gallery.noImagesInGallery')} - - )} - - + {areMoreImagesAvailable + ? t('gallery.loadMore') + : t('gallery.allImagesLoaded')} + + + ) : ( + + + {t('gallery.noImagesInGallery')} + + )} + ); }; -ImageGalleryContent.displayName = 'ImageGalleryContent'; -export default ImageGalleryContent; +type ItemContainerProps = PropsWithChildren & FlexProps; +const ItemContainer = forwardRef((props: ItemContainerProps, ref) => ( + + {props.children} + +)); + +type ListContainerProps = PropsWithChildren & FlexProps; +const ListContainer = forwardRef((props: ListContainerProps, ref) => { + const galleryImageMinimumWidth = useAppSelector( + (state: RootState) => state.gallery.galleryImageMinimumWidth + ); + + return ( + + {props.children} + + ); +}); + +export default memo(ImageGalleryContent); diff --git a/invokeai/frontend/web/src/theme/css/overlayscrollbars.css b/invokeai/frontend/web/src/theme/css/overlayscrollbars.css new file mode 100644 index 0000000000..b5acaca75d --- /dev/null +++ b/invokeai/frontend/web/src/theme/css/overlayscrollbars.css @@ -0,0 +1,48 @@ +.os-scrollbar { + /* The size of the scrollbar */ + /* --os-size: 0; */ + /* The axis-perpedicular padding of the scrollbar (horizontal: padding-y, vertical: padding-x) */ + /* --os-padding-perpendicular: 0; */ + /* The axis padding of the scrollbar (horizontal: padding-x, vertical: padding-y) */ + /* --os-padding-axis: 0; */ + /* The border radius of the scrollbar track */ + /* --os-track-border-radius: 0; */ + /* The background of the scrollbar track */ + --os-track-bg: rgba(0, 0, 0, 0.3); + /* The :hover background of the scrollbar track */ + --os-track-bg-hover: rgba(0, 0, 0, 0.3); + /* The :active background of the scrollbar track */ + --os-track-bg-active: rgba(0, 0, 0, 0.3); + /* The border of the scrollbar track */ + /* --os-track-border: none; */ + /* The :hover background of the scrollbar track */ + /* --os-track-border-hover: none; */ + /* The :active background of the scrollbar track */ + /* --os-track-border-active: none; */ + /* The border radius of the scrollbar handle */ + /* --os-handle-border-radius: 0; */ + /* The background of the scrollbar handle */ + --os-handle-bg: var(--invokeai-colors-accent-500); + /* The :hover background of the scrollbar handle */ + --os-handle-bg-hover: var(--invokeai-colors-accent-450); + /* The :active background of the scrollbar handle */ + --os-handle-bg-active: var(--invokeai-colors-accent-400); + /* The border of the scrollbar handle */ + /* --os-handle-border: none; */ + /* The :hover border of the scrollbar handle */ + /* --os-handle-border-hover: none; */ + /* The :active border of the scrollbar handle */ + /* --os-handle-border-active: none; */ + /* The min size of the scrollbar handle */ + --os-handle-min-size: 50px; + /* The max size of the scrollbar handle */ + /* --os-handle-max-size: none; */ + /* The axis-perpedicular size of the scrollbar handle (horizontal: height, vertical: width) */ + /* --os-handle-perpendicular-size: 100%; */ + /* The :hover axis-perpedicular size of the scrollbar handle (horizontal: height, vertical: width) */ + /* --os-handle-perpendicular-size-hover: 100%; */ + /* The :active axis-perpedicular size of the scrollbar handle (horizontal: height, vertical: width) */ + /* --os-handle-perpendicular-size-active: 100%; */ + /* Increases the interactive area of the scrollbar handle. */ + /* --os-handle-interactive-area-offset: 0; */ +} \ No newline at end of file diff --git a/invokeai/frontend/web/yarn.lock b/invokeai/frontend/web/yarn.lock index b60071ab65..872be96040 100644 --- a/invokeai/frontend/web/yarn.lock +++ b/invokeai/frontend/web/yarn.lock @@ -5100,6 +5100,16 @@ os-tmpdir@~1.0.2: resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== +overlayscrollbars-react@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/overlayscrollbars-react/-/overlayscrollbars-react-0.5.0.tgz#0272bdc6304c7228a58d30e5b678e97fd5c5d8dd" + integrity sha512-uCNTnkfWW74veoiEv3kSwoLelKt4e8gTNv65D771X3il0x5g5Yo0fUbro7SpQzR9yNgi23cvB2mQHTTdQH96pA== + +overlayscrollbars@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/overlayscrollbars/-/overlayscrollbars-2.1.1.tgz#a7414fe9c96cf140dbe4975bbe9312861750388d" + integrity sha512-xvs2g8Tcq9+CZDpLEUchN3YUzjJhnTWw9kwqT/qcC53FIkOyP9mqnRMot5sW16tcsPT1KaMyzF0AMXw/7E4a8g== + p-cancelable@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" @@ -5612,6 +5622,11 @@ react-use@^17.4.0: ts-easing "^0.2.0" tslib "^2.1.0" +react-virtuoso@^4.3.3: + version "4.3.3" + resolved "https://registry.yarnpkg.com/react-virtuoso/-/react-virtuoso-4.3.3.tgz#04b8d105b5d97365223fb13c9a594f7501f7e975" + integrity sha512-x0DeGmVAVOVaTXRMG7jzrHBwK7+dkt7n0G3tNmZXphQUBgkVBYuZoaJltQeZGFN42++3XvrgwStKCtmzgMJ0lA== + react-zoom-pan-pinch@^3.0.7: version "3.0.7" resolved "https://registry.yarnpkg.com/react-zoom-pan-pinch/-/react-zoom-pan-pinch-3.0.7.tgz#def52f6886bc11e1b160dedf4250aae95470b94d" From 4d885653e9414cbf261347f3a84c07577a05b45a Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Mon, 1 May 2023 16:55:17 +1000 Subject: [PATCH 64/68] feat(ui): tidy --- .../web/src/features/gallery/store/gallerySlice.ts | 2 ++ .../parameters/components/ProgressImagePreview.tsx | 7 ------- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/invokeai/frontend/web/src/features/gallery/store/gallerySlice.ts b/invokeai/frontend/web/src/features/gallery/store/gallerySlice.ts index 418d95734d..47c2c4e0fd 100644 --- a/invokeai/frontend/web/src/features/gallery/store/gallerySlice.ts +++ b/invokeai/frontend/web/src/features/gallery/store/gallerySlice.ts @@ -40,6 +40,8 @@ export const gallerySlice = createSlice({ action: PayloadAction ) => { state.selectedImage = action.payload; + // TODO: if the user selects an image, disable the auto switch? + // state.shouldAutoSwitchToNewImages = false; }, setGalleryImageMinimumWidth: (state, action: PayloadAction) => { state.galleryImageMinimumWidth = action.payload; diff --git a/invokeai/frontend/web/src/features/parameters/components/ProgressImagePreview.tsx b/invokeai/frontend/web/src/features/parameters/components/ProgressImagePreview.tsx index 9a54e37463..c31215a13e 100644 --- a/invokeai/frontend/web/src/features/parameters/components/ProgressImagePreview.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/ProgressImagePreview.tsx @@ -89,13 +89,6 @@ const ProgressImagePreview = () => { onResizeStop={(e, direction, ref, delta, position) => { const newRect: Partial = {}; - console.log( - ref.style.width, - ref.style.height, - position.x, - position.y - ); - if (ref.style.width) { newRect.width = ref.style.width; } From 3264d30b44d9fe5848735df01a36db181bf17dda Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Mon, 24 Apr 2023 20:35:31 +1000 Subject: [PATCH 65/68] feat(nodes): allow multiples of 8 for dimensions --- invokeai/app/invocations/generate.py | 4 ++-- invokeai/app/invocations/latent.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/invokeai/app/invocations/generate.py b/invokeai/app/invocations/generate.py index ba25cd2e6a..dd44ee0ed9 100644 --- a/invokeai/app/invocations/generate.py +++ b/invokeai/app/invocations/generate.py @@ -46,8 +46,8 @@ class TextToImageInvocation(BaseInvocation, SDImageInvocation): prompt: Optional[str] = Field(description="The prompt to generate an image from") seed: int = Field(default=-1,ge=-1, le=np.iinfo(np.uint32).max, description="The seed to use (-1 for a random seed)", ) steps: int = Field(default=10, gt=0, description="The number of steps to use to generate the image") - width: int = Field(default=512, multiple_of=64, gt=0, description="The width of the resulting image", ) - height: int = Field(default=512, multiple_of=64, gt=0, description="The height of the resulting image", ) + width: int = Field(default=512, multiple_of=8, gt=0, description="The width of the resulting image", ) + height: int = Field(default=512, multiple_of=8, gt=0, description="The height of the resulting image", ) cfg_scale: float = Field(default=7.5, gt=0, description="The Classifier-Free Guidance, higher values may result in a result closer to the prompt", ) scheduler: SAMPLER_NAME_VALUES = Field(default="k_lms", description="The scheduler to use" ) seamless: bool = Field(default=False, description="Whether or not to generate an image that can tile without seams", ) diff --git a/invokeai/app/invocations/latent.py b/invokeai/app/invocations/latent.py index 9dadc79597..c6ea8a686a 100644 --- a/invokeai/app/invocations/latent.py +++ b/invokeai/app/invocations/latent.py @@ -113,8 +113,8 @@ class NoiseInvocation(BaseInvocation): # Inputs seed: int = Field(ge=0, le=np.iinfo(np.uint32).max, description="The seed to use", default_factory=random_seed) - width: int = Field(default=512, multiple_of=64, gt=0, description="The width of the resulting noise", ) - height: int = Field(default=512, multiple_of=64, gt=0, description="The height of the resulting noise", ) + width: int = Field(default=512, multiple_of=8, gt=0, description="The width of the resulting noise", ) + height: int = Field(default=512, multiple_of=8, gt=0, description="The height of the resulting noise", ) # Schema customisation From f9f40adcdc2cf26b8b648451504e7351c709c9dc Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Tue, 2 May 2023 11:24:55 +1000 Subject: [PATCH 66/68] fix(nodes): fix `t2i` graph Removed width and height edges. --- invokeai/app/services/default_graphs.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/invokeai/app/services/default_graphs.py b/invokeai/app/services/default_graphs.py index 637d906e75..fd0c8f5b8d 100644 --- a/invokeai/app/services/default_graphs.py +++ b/invokeai/app/services/default_graphs.py @@ -23,8 +23,6 @@ def create_text_to_image() -> LibraryGraph: edges=[ Edge(source=EdgeConnection(node_id='width', field='a'), destination=EdgeConnection(node_id='3', field='width')), Edge(source=EdgeConnection(node_id='height', field='a'), destination=EdgeConnection(node_id='3', field='height')), - Edge(source=EdgeConnection(node_id='width', field='a'), destination=EdgeConnection(node_id='4', field='width')), - Edge(source=EdgeConnection(node_id='height', field='a'), destination=EdgeConnection(node_id='4', field='height')), Edge(source=EdgeConnection(node_id='3', field='noise'), destination=EdgeConnection(node_id='4', field='noise')), Edge(source=EdgeConnection(node_id='4', field='latents'), destination=EdgeConnection(node_id='5', field='latents')), ] From 0419f50ab012d39ccf18cdb76353aef41d9ccea5 Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Tue, 2 May 2023 20:10:57 +1000 Subject: [PATCH 67/68] chore(ui): bump react-virtuoso - Resolves an issue with gallery not rendering all items --- invokeai/frontend/web/package.json | 2 +- invokeai/frontend/web/yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/invokeai/frontend/web/package.json b/invokeai/frontend/web/package.json index feb2ea1200..ef61f65cf4 100644 --- a/invokeai/frontend/web/package.json +++ b/invokeai/frontend/web/package.json @@ -93,7 +93,7 @@ "react-rnd": "^10.4.1", "react-transition-group": "^4.4.5", "react-use": "^17.4.0", - "react-virtuoso": "^4.3.3", + "react-virtuoso": "^4.3.5", "react-zoom-pan-pinch": "^3.0.7", "reactflow": "^11.7.0", "redux-deep-persist": "^1.0.7", diff --git a/invokeai/frontend/web/yarn.lock b/invokeai/frontend/web/yarn.lock index 872be96040..59a2607db7 100644 --- a/invokeai/frontend/web/yarn.lock +++ b/invokeai/frontend/web/yarn.lock @@ -5622,10 +5622,10 @@ react-use@^17.4.0: ts-easing "^0.2.0" tslib "^2.1.0" -react-virtuoso@^4.3.3: - version "4.3.3" - resolved "https://registry.yarnpkg.com/react-virtuoso/-/react-virtuoso-4.3.3.tgz#04b8d105b5d97365223fb13c9a594f7501f7e975" - integrity sha512-x0DeGmVAVOVaTXRMG7jzrHBwK7+dkt7n0G3tNmZXphQUBgkVBYuZoaJltQeZGFN42++3XvrgwStKCtmzgMJ0lA== +react-virtuoso@^4.3.5: + version "4.3.5" + resolved "https://registry.yarnpkg.com/react-virtuoso/-/react-virtuoso-4.3.5.tgz#1e882d435b2d3d8abf7c4b85235199cbfadd935d" + integrity sha512-MdWzmM9d8Gt5YGPIgGzRoqnYygTsriWlZrq+SqxphJTiiHs9cffnjf2Beo3SA3wRYzQJD8FI2HXtN5ACWzPFbQ== react-zoom-pan-pinch@^3.0.7: version "3.0.7" From 994b247f8e9b5abe8865bb43e171089c86ec81ca Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Wed, 3 May 2023 23:40:22 +1000 Subject: [PATCH 68/68] feat(ui): do not persist gallery images - I've sorted out the issues that make *not* persisting troublesome, these will be rolled out with canvas - Also realized that persisting gallery images very quickly fills up localStorage, so we can't really do it anyways --- invokeai/frontend/web/src/app/store/store.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/invokeai/frontend/web/src/app/store/store.ts b/invokeai/frontend/web/src/app/store/store.ts index e9e104dac2..b0f73a759e 100644 --- a/invokeai/frontend/web/src/app/store/store.ts +++ b/invokeai/frontend/web/src/app/store/store.ts @@ -73,10 +73,12 @@ const rootPersistConfig = getPersistConfig({ ...modelsDenylist, ...nodesDenylist, ...postprocessingDenylist, - ...resultsDenylist, + // ...resultsDenylist, + 'results', ...systemDenylist, ...uiDenylist, - ...uploadsDenylist, + // ...uploadsDenylist, + 'uploads', 'hotkeys', 'config', ],