From d796ea7becb5c4db4417bb9a2ac7d03cc3a7445a Mon Sep 17 00:00:00 2001 From: blessedcoolant <54517381+blessedcoolant@users.noreply.github.com> Date: Sat, 13 May 2023 02:13:49 +1200 Subject: [PATCH 01/14] feat: Logging Improvements --- invokeai/backend/util/logging.py | 98 ++++++++++++++++---------------- scripts/invoke-new.py | 3 + 2 files changed, 52 insertions(+), 49 deletions(-) diff --git a/invokeai/backend/util/logging.py b/invokeai/backend/util/logging.py index 73f980aeff..523aa42d7d 100644 --- a/invokeai/backend/util/logging.py +++ b/invokeai/backend/util/logging.py @@ -2,34 +2,37 @@ """invokeai.util.logging -Logging class for InvokeAI that produces console messages that follow -the conventions established in InvokeAI 1.X through 2.X. +Logging class for InvokeAI that produces console messages - -One way to use it: +Usage: 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') +logger = InvokeAILogger.getLogger(name='InvokeAI') // Initialization +(or) +logger = InvokeAILogger.getLogger(__name__) // To use the filename + +logger.critical('this is critical') // Critical Message +logger.error('this is an error') // Error Message +logger.warning('this is a warning') // Warning Message +logger.info('this is info') // Info Message +logger.debug('this is debugging') // Debug Message Console messages: - ### this is critical - *** this is an error *** - ** this is a warning - >> this is info - | this is debugging + [12-05-2023 20]::[InvokeAI]::CRITICAL --> This is an info message [In Bold Red] + [12-05-2023 20]::[InvokeAI]::ERROR --> This is an info message [In Red] + [12-05-2023 20]::[InvokeAI]::WARNING --> This is an info message [In Yellow] + [12-05-2023 20]::[InvokeAI]::INFO --> This is an info message [In Grey] + [12-05-2023 20]::[InvokeAI]::DEBUG --> This is an info message [In Grey] -Another way: -import invokeai.backend.util.logging as ialog -ialogger.debug('this is a debugging message') +Alternate Method (in this case the logger name will be set to InvokeAI): +import invokeai.backend.util.logging as IAILogger +IAILogger.debug('this is a debugging message') """ + import logging + # module level functions def debug(msg, *args, **kwargs): InvokeAILogger.getLogger().debug(msg, *args, **kwargs) @@ -42,7 +45,7 @@ def warning(msg, *args, **kwargs): def error(msg, *args, **kwargs): InvokeAILogger.getLogger().error(msg, *args, **kwargs) - + def critical(msg, *args, **kwargs): InvokeAILogger.getLogger().critical(msg, *args, **kwargs) @@ -55,49 +58,46 @@ def disable(level=logging.CRITICAL): def basicConfig(**kwargs): InvokeAILogger.getLogger().basicConfig(**kwargs) -def getLogger(name: str=None)->logging.Logger: +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 + Custom Formatting for the InvokeAI Logger ''' - 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='%') + # Color Codes + grey = "\x1b[38;20m" + yellow = "\x1b[33;20m" + red = "\x1b[31;20m" + bold_red = "\x1b[31;1m" + reset = "\x1b[0m" + + # Log Format + format = "[%(asctime)s]::[%(name)s]::%(levelname)s --> %(message)s" + ## More Formatting Options: %(pathname)s, %(filename)s, %(module)s, %(lineno)d + + # Format Map + FORMATS = { + logging.DEBUG: grey + format + reset, + logging.INFO: grey + format + reset, + logging.WARNING: yellow + format + reset, + logging.ERROR: red + format + reset, + logging.CRITICAL: bold_red + format + reset + } 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 + log_fmt = self.FORMATS.get(record.levelno) + formatter = logging.Formatter(log_fmt, datefmt="%d-%m-%Y %H:%M:%S") + return formatter.format(record) - # 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: + def getLogger(self, name: str = 'InvokeAI') -> logging.Logger: if name not in self.loggers: logger = logging.getLogger(name) logger.setLevel(logging.DEBUG) diff --git a/scripts/invoke-new.py b/scripts/invoke-new.py index a47d6238bd..faf83a9993 100755 --- a/scripts/invoke-new.py +++ b/scripts/invoke-new.py @@ -2,6 +2,9 @@ # Copyright (c) 2022 Kyle Schouviller (https://github.com/kyle0654) +import logging +logging.getLogger("xformers").addFilter(lambda record: 'A matching Triton is not available' not in record.getMessage()) + import os import sys From 691e1bf829f455b2c97f00375c010b92e164e437 Mon Sep 17 00:00:00 2001 From: blessedcoolant <54517381+blessedcoolant@users.noreply.github.com> Date: Sun, 14 May 2023 09:06:57 +1200 Subject: [PATCH 02/14] Make debug messages cyan/blue --- invokeai/backend/util/logging.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/invokeai/backend/util/logging.py b/invokeai/backend/util/logging.py index 523aa42d7d..3822ccafbe 100644 --- a/invokeai/backend/util/logging.py +++ b/invokeai/backend/util/logging.py @@ -71,6 +71,7 @@ class InvokeAILogFormatter(logging.Formatter): grey = "\x1b[38;20m" yellow = "\x1b[33;20m" red = "\x1b[31;20m" + cyan = "\x1b[36;20m" bold_red = "\x1b[31;1m" reset = "\x1b[0m" @@ -80,7 +81,7 @@ class InvokeAILogFormatter(logging.Formatter): # Format Map FORMATS = { - logging.DEBUG: grey + format + reset, + logging.DEBUG: cyan + format + reset, logging.INFO: grey + format + reset, logging.WARNING: yellow + format + reset, logging.ERROR: red + format + reset, From 026d3260b4128fe4f2fc603ae9cfbd7ca18b7fae Mon Sep 17 00:00:00 2001 From: blessedcoolant <54517381+blessedcoolant@users.noreply.github.com> Date: Sat, 13 May 2023 02:43:32 +1200 Subject: [PATCH 03/14] Add Heun Karras Scheduler --- invokeai/backend/args.py | 1 + invokeai/backend/stable_diffusion/schedulers/schedulers.py | 3 ++- invokeai/backend/web/modules/parameters.py | 1 + invokeai/frontend/web/src/app/constants.ts | 1 + invokeai/frontend/web/src/app/types/invokeai.ts | 1 + 5 files changed, 6 insertions(+), 1 deletion(-) diff --git a/invokeai/backend/args.py b/invokeai/backend/args.py index db6fbe08df..6a29847c6e 100644 --- a/invokeai/backend/args.py +++ b/invokeai/backend/args.py @@ -113,6 +113,7 @@ SAMPLER_CHOICES = [ "lms", "pndm", "heun", + "heun_k", "euler", "euler_k", "euler_a", diff --git a/invokeai/backend/stable_diffusion/schedulers/schedulers.py b/invokeai/backend/stable_diffusion/schedulers/schedulers.py index fab28aca8c..08f85cf559 100644 --- a/invokeai/backend/stable_diffusion/schedulers/schedulers.py +++ b/invokeai/backend/stable_diffusion/schedulers/schedulers.py @@ -9,7 +9,8 @@ SCHEDULER_MAP = dict( deis=(DEISMultistepScheduler, dict()), lms=(LMSDiscreteScheduler, dict()), pndm=(PNDMScheduler, dict()), - heun=(HeunDiscreteScheduler, dict()), + heun=(HeunDiscreteScheduler, dict(use_karras_sigmas=False)), + heun_k=(HeunDiscreteScheduler, dict(use_karras_sigmas=True)), euler=(EulerDiscreteScheduler, dict(use_karras_sigmas=False)), euler_k=(EulerDiscreteScheduler, dict(use_karras_sigmas=True)), euler_a=(EulerAncestralDiscreteScheduler, dict()), diff --git a/invokeai/backend/web/modules/parameters.py b/invokeai/backend/web/modules/parameters.py index 72211857a3..9a4bc0aec3 100644 --- a/invokeai/backend/web/modules/parameters.py +++ b/invokeai/backend/web/modules/parameters.py @@ -9,6 +9,7 @@ SAMPLER_CHOICES = [ "lms", "pndm", "heun", + 'heun_k', "euler", "euler_k", "euler_a", diff --git a/invokeai/frontend/web/src/app/constants.ts b/invokeai/frontend/web/src/app/constants.ts index 189fbc9dd4..6ecd20d7fe 100644 --- a/invokeai/frontend/web/src/app/constants.ts +++ b/invokeai/frontend/web/src/app/constants.ts @@ -7,6 +7,7 @@ export const DIFFUSERS_SCHEDULERS: Array = [ 'lms', 'pndm', 'heun', + 'heun_k', 'euler', 'euler_k', 'euler_a', diff --git a/invokeai/frontend/web/src/app/types/invokeai.ts b/invokeai/frontend/web/src/app/types/invokeai.ts index d0e5437d36..f684dc1ccf 100644 --- a/invokeai/frontend/web/src/app/types/invokeai.ts +++ b/invokeai/frontend/web/src/app/types/invokeai.ts @@ -52,6 +52,7 @@ export type CommonGeneratedImageMetadata = { | 'lms' | 'pndm' | 'heun' + | 'heun_k' | 'euler' | 'euler_k' | 'euler_a' From d2ebc6741b22eef6363565635c31edfaa7416442 Mon Sep 17 00:00:00 2001 From: blessedcoolant <54517381+blessedcoolant@users.noreply.github.com> Date: Sat, 13 May 2023 08:17:45 +1200 Subject: [PATCH 04/14] feat: Add setting to hide / display schedulers --- invokeai/frontend/web/public/locales/en.json | 5 +- invokeai/frontend/web/src/app/constants.ts | 22 +++---- .../Parameters/Core/ParamSampler.tsx | 16 ++--- .../SettingsModal/SettingsModal.tsx | 11 +++- .../SettingsModal/SettingsSchedulers.tsx | 59 +++++++++++++++++++ .../web/src/features/ui/store/uiSlice.ts | 7 +++ .../web/src/features/ui/store/uiTypes.ts | 1 + 7 files changed, 98 insertions(+), 23 deletions(-) create mode 100644 invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsSchedulers.tsx diff --git a/invokeai/frontend/web/public/locales/en.json b/invokeai/frontend/web/public/locales/en.json index 3592e141d0..f82b3af677 100644 --- a/invokeai/frontend/web/public/locales/en.json +++ b/invokeai/frontend/web/public/locales/en.json @@ -540,7 +540,10 @@ "consoleLogLevel": "Log Level", "shouldLogToConsole": "Console Logging", "developer": "Developer", - "general": "General" + "general": "General", + "generation": "Generation", + "ui": "User Interface", + "availableSchedulers": "Available Schedulers" }, "toast": { "serverError": "Server Error", diff --git a/invokeai/frontend/web/src/app/constants.ts b/invokeai/frontend/web/src/app/constants.ts index 6ecd20d7fe..b74c67befd 100644 --- a/invokeai/frontend/web/src/app/constants.ts +++ b/invokeai/frontend/web/src/app/constants.ts @@ -1,30 +1,24 @@ // TODO: use Enums? -export const DIFFUSERS_SCHEDULERS: Array = [ +export const SCHEDULERS: Array = [ 'ddim', - 'ddpm', - 'deis', 'lms', - 'pndm', - 'heun', - 'heun_k', 'euler', 'euler_k', 'euler_a', - 'kdpm_2', - 'kdpm_2_a', 'dpmpp_2s', 'dpmpp_2m', 'dpmpp_2m_k', + 'kdpm_2', + 'kdpm_2_a', + 'deis', + 'ddpm', + 'pndm', + 'heun', + 'heun_k', 'unipc', ]; -export const IMG2IMG_DIFFUSERS_SCHEDULERS = DIFFUSERS_SCHEDULERS.filter( - (scheduler) => { - return scheduler !== 'dpmpp_2s'; - } -); - // Valid image widths export const WIDTHS: Array = Array.from(Array(64)).map( (_x, i) => (i + 1) * 64 diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamSampler.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamSampler.tsx index 9bd22d9abe..bd31a73829 100644 --- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamSampler.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamSampler.tsx @@ -1,7 +1,3 @@ -import { - DIFFUSERS_SCHEDULERS, - IMG2IMG_DIFFUSERS_SCHEDULERS, -} from 'app/constants'; import { RootState } from 'app/store/store'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAISelect from 'common/components/IAISelect'; @@ -17,6 +13,12 @@ const ParamSampler = () => { const activeTabName = useAppSelector(activeTabNameSelector); + const schedulers = useAppSelector((state: RootState) => state.ui.schedulers); + + const img2imgSchedulers = schedulers.filter((scheduler) => { + return !['dpmpp_2s'].includes(scheduler); + }); + const dispatch = useAppDispatch(); const { t } = useTranslation(); @@ -31,9 +33,9 @@ const ParamSampler = () => { value={sampler} onChange={handleChange} validValues={ - activeTabName === 'img2img' || activeTabName == 'unifiedCanvas' - ? IMG2IMG_DIFFUSERS_SCHEDULERS - : DIFFUSERS_SCHEDULERS + ['img2img', 'unifiedCanvas'].includes(activeTabName) + ? img2imgSchedulers + : schedulers } minWidth={36} /> 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 58e6684b04..aa3d274dc3 100644 --- a/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsModal.tsx +++ b/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsModal.tsx @@ -40,6 +40,7 @@ import { useTranslation } from 'react-i18next'; import { VALID_LOG_LEVELS } from 'app/logging/useLogger'; import { LogLevelName } from 'roarr'; import { LOCALSTORAGE_KEYS, LOCALSTORAGE_PREFIX } from 'app/store/constants'; +import SettingsSchedulers from './SettingsSchedulers'; const selector = createSelector( [systemSelector, uiSelector], @@ -171,7 +172,6 @@ const SettingsModal = ({ children }: SettingsModalProps) => { {t('settings.general')} - { dispatch(setShouldConfirmOnDelete(e.target.checked)) } /> + + + + {t('settings.generation')} + + + + + {t('settings.ui')} state.ui.schedulers); + + const dispatch = useAppDispatch(); + const { t } = useTranslation(); + + const schedulerSettingsHandler = (v: string | string[]) => { + if (isArray(v)) dispatch(setSchedulers(v.sort())); + }; + + const renderSchedulerMenuItems = () => { + const schedulerMenuItemsToRender: ReactNode[] = []; + + SCHEDULERS.forEach((scheduler) => { + schedulerMenuItemsToRender.push( + + {scheduler} + + ); + }); + + return schedulerMenuItemsToRender; + }; + + return ( + + + {t('settings.availableSchedulers')} + + + + {renderSchedulerMenuItems()} + + + + ); +} diff --git a/invokeai/frontend/web/src/features/ui/store/uiSlice.ts b/invokeai/frontend/web/src/features/ui/store/uiSlice.ts index b99ebb2c51..6c3eb95a31 100644 --- a/invokeai/frontend/web/src/features/ui/store/uiSlice.ts +++ b/invokeai/frontend/web/src/features/ui/store/uiSlice.ts @@ -5,6 +5,7 @@ import { InvokeTabName, tabMap } from './tabMap'; import { AddNewModelType, Coordinates, Rect, UIState } from './uiTypes'; import { initialImageSelected } from 'features/parameters/store/actions'; import { initialImageChanged } from 'features/parameters/store/generationSlice'; +import { SCHEDULERS } from 'app/constants'; export const initialUIState: UIState = { activeTab: 0, @@ -27,6 +28,7 @@ export const initialUIState: UIState = { shouldShowProgressImages: false, shouldShowProgressInViewer: false, shouldShowImageParameters: false, + schedulers: SCHEDULERS, }; export const uiSlice = createSlice({ @@ -146,6 +148,10 @@ export const uiSlice = createSlice({ ) => { state.shouldShowImageParameters = action.payload; }, + setSchedulers: (state, action: PayloadAction) => { + state.schedulers = []; + state.schedulers = action.payload; + }, }, extraReducers(builder) { builder.addCase(initialImageChanged, (state) => { @@ -179,6 +185,7 @@ export const { setShouldShowProgressImages, setShouldShowProgressInViewer, shouldShowImageParametersChanged, + setSchedulers, } = 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 030ec4f1ce..db9c60e292 100644 --- a/invokeai/frontend/web/src/features/ui/store/uiTypes.ts +++ b/invokeai/frontend/web/src/features/ui/store/uiTypes.ts @@ -33,4 +33,5 @@ export interface UIState { shouldShowProgressImages: boolean; shouldShowProgressInViewer: boolean; shouldShowImageParameters: boolean; + schedulers: string[]; } From 0e9470503fe117621a35aed934037564639d840f Mon Sep 17 00:00:00 2001 From: blessedcoolant <54517381+blessedcoolant@users.noreply.github.com> Date: Sat, 13 May 2023 08:18:16 +1200 Subject: [PATCH 05/14] fix: Rework the layout of the parameters scrollbar --- .../src/features/ui/components/ParametersPinnedWrapper.tsx | 7 ++++++- .../features/ui/components/common/OverlayScrollable.tsx | 6 +++--- .../ui/components/tabs/ImageToImage/ImageToImageTab.tsx | 2 +- .../ui/components/tabs/TextToImage/TextToImageTab.tsx | 2 +- .../ui/components/tabs/UnifiedCanvas/UnifiedCanvasTab.tsx | 2 +- 5 files changed, 12 insertions(+), 7 deletions(-) diff --git a/invokeai/frontend/web/src/features/ui/components/ParametersPinnedWrapper.tsx b/invokeai/frontend/web/src/features/ui/components/ParametersPinnedWrapper.tsx index 407187294c..cfb2ad267c 100644 --- a/invokeai/frontend/web/src/features/ui/components/ParametersPinnedWrapper.tsx +++ b/invokeai/frontend/web/src/features/ui/components/ParametersPinnedWrapper.tsx @@ -43,13 +43,18 @@ const ParametersPinnedWrapper = (props: ParametersPinnedWrapperProps) => { h: 'full', w: 'full', position: 'absolute', + paddingRight: 4, }} > {props.children} ); diff --git a/invokeai/frontend/web/src/features/ui/components/common/OverlayScrollable.tsx b/invokeai/frontend/web/src/features/ui/components/common/OverlayScrollable.tsx index 71413fd01a..a993f02ce6 100644 --- a/invokeai/frontend/web/src/features/ui/components/common/OverlayScrollable.tsx +++ b/invokeai/frontend/web/src/features/ui/components/common/OverlayScrollable.tsx @@ -8,9 +8,9 @@ const OverlayScrollable = (props: PropsWithChildren) => { style={{ height: '100%', width: '100%' }} options={{ scrollbars: { - visibility: 'auto', - autoHide: 'move', - autoHideDelay: 1300, + visibility: 'visible', + autoHide: 'never', + autoHideDelay: 500, theme: 'os-theme-dark', }, overflow: { x: 'hidden' }, diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/ImageToImage/ImageToImageTab.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/ImageToImage/ImageToImageTab.tsx index cbd261f455..46d416204d 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/ImageToImage/ImageToImageTab.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/ImageToImage/ImageToImageTab.tsx @@ -23,7 +23,7 @@ const ImageToImageTab = () => { }, []); return ( - + diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/TextToImage/TextToImageTab.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/TextToImage/TextToImageTab.tsx index 87e77cc3ba..6c140172be 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/TextToImage/TextToImageTab.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/TextToImage/TextToImageTab.tsx @@ -6,7 +6,7 @@ import ParametersPinnedWrapper from '../../ParametersPinnedWrapper'; const TextToImageTab = () => { return ( - + diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasTab.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasTab.tsx index 2d591d1ecc..aa8c1c6a76 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasTab.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasTab.tsx @@ -20,7 +20,7 @@ const UnifiedCanvasTab = () => { const { shouldUseCanvasBetaLayout } = useAppSelector(selector); return ( - + From 6d3e8507cc5a9750a0003d1c05bca59a3f30cacf Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Sat, 13 May 2023 21:15:19 +1000 Subject: [PATCH 06/14] fix(ui): fix "no image" fallbacks --- .../gallery/components/CurrentImageDisplay.tsx | 4 ++-- .../Parameters/ImageToImage/InitialImagePreview.tsx | 13 +++++++++++-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/invokeai/frontend/web/src/features/gallery/components/CurrentImageDisplay.tsx b/invokeai/frontend/web/src/features/gallery/components/CurrentImageDisplay.tsx index 36451cfb2c..9b928d45c4 100644 --- a/invokeai/frontend/web/src/features/gallery/components/CurrentImageDisplay.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/CurrentImageDisplay.tsx @@ -4,10 +4,10 @@ import { useAppSelector } from 'app/store/storeHooks'; import { systemSelector } from 'features/system/store/systemSelectors'; import { isEqual } from 'lodash-es'; -import { MdPhoto } from 'react-icons/md'; import { selectedImageSelector } from '../store/gallerySelectors'; import CurrentImageButtons from './CurrentImageButtons'; import CurrentImagePreview from './CurrentImagePreview'; +import { FaImage } from 'react-icons/fa'; export const currentImageDisplaySelector = createSelector( [systemSelector, selectedImageSelector], @@ -61,7 +61,7 @@ const CurrentImageDisplay = () => { ) : ( { )} - {!initialImage?.url && } + {!initialImage?.url && ( + + )} ); }; From 37da0fc0753a0588045027f425cda26689b92ac6 Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Sat, 13 May 2023 21:15:45 +1000 Subject: [PATCH 07/14] feat(ui): IAICustomSelect v1 --- .../src/common/components/IAICustomSelect.tsx | 163 ++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 invokeai/frontend/web/src/common/components/IAICustomSelect.tsx diff --git a/invokeai/frontend/web/src/common/components/IAICustomSelect.tsx b/invokeai/frontend/web/src/common/components/IAICustomSelect.tsx new file mode 100644 index 0000000000..dd1b7ab5e2 --- /dev/null +++ b/invokeai/frontend/web/src/common/components/IAICustomSelect.tsx @@ -0,0 +1,163 @@ +import { CheckIcon, ChevronUpIcon } from '@chakra-ui/icons'; +import { + Flex, + FormControl, + FormControlProps, + FormLabel, + Grid, + GridItem, + Input, + List, + ListItem, + Select, + Spacer, + Text, +} from '@chakra-ui/react'; +import { useEnsureOnScreen } from 'common/hooks/useEnsureOnScreen'; +import { useSelect } from 'downshift'; +import { OverlayScrollbarsComponent } from 'overlayscrollbars-react'; + +import { memo, useRef } from 'react'; +import { useIntersection } from 'react-use'; + +const BUTTON_BG = 'base.900'; +const BORDER_HOVER = 'base.700'; +const BORDER_FOCUS = 'accent.600'; + +type IAICustomSelectProps = { + label?: string; + items: string[]; + selectedItem: string; + setSelectedItem: (v: string | null | undefined) => void; + withCheckIcon?: boolean; + formControlProps?: FormControlProps; +}; + +const IAICustomSelect = (props: IAICustomSelectProps) => { + const { + label, + items, + setSelectedItem, + selectedItem, + withCheckIcon, + formControlProps, + } = props; + + const { + isOpen, + getToggleButtonProps, + getLabelProps, + getMenuProps, + highlightedIndex, + getItemProps, + } = useSelect({ + items, + selectedItem, + onSelectedItemChange: ({ selectedItem: newSelectedItem }) => + setSelectedItem(newSelectedItem), + }); + + const toggleButtonRef = useRef(null); + const menuRef = useRef(null); + + return ( + + {label && ( + { + toggleButtonRef.current && toggleButtonRef.current.focus(); + }} + > + {label} + + )} + + + + {isOpen && + items.map((item, index) => ( + + {withCheckIcon ? ( + + + {selectedItem === item && } + + + + {item} + + + + ) : ( + + {item} + + )} + + ))} + + + + ); +}; + +export default memo(IAICustomSelect); From 658b556544be6f00e5033673f216f4a3788b6778 Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Sat, 13 May 2023 23:46:47 +1000 Subject: [PATCH 08/14] feat(ui): IAICustomSelect v2, implement for scheduler & model --- .../src/common/components/IAICustomSelect.tsx | 205 +++++++++--------- .../Parameters/Core/ParamSampler.tsx | 18 +- .../Core/ParamSchedulerAndModel.tsx | 19 ++ .../parameters/store/generationSlice.ts | 13 +- .../system/components/ModelSelect.tsx | 33 +-- .../ImageToImageTabCoreParameters.tsx | 23 +- .../TextToImageTabCoreParameters.tsx | 23 +- .../UnifiedCanvasCoreParameters.tsx | 23 +- 8 files changed, 181 insertions(+), 176 deletions(-) create mode 100644 invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamSchedulerAndModel.tsx diff --git a/invokeai/frontend/web/src/common/components/IAICustomSelect.tsx b/invokeai/frontend/web/src/common/components/IAICustomSelect.tsx index dd1b7ab5e2..d9610346ec 100644 --- a/invokeai/frontend/web/src/common/components/IAICustomSelect.tsx +++ b/invokeai/frontend/web/src/common/components/IAICustomSelect.tsx @@ -1,28 +1,25 @@ -import { CheckIcon, ChevronUpIcon } from '@chakra-ui/icons'; +import { CheckIcon } from '@chakra-ui/icons'; import { + Box, Flex, + FlexProps, FormControl, FormControlProps, FormLabel, Grid, GridItem, - Input, List, ListItem, Select, - Spacer, Text, + Tooltip, + TooltipProps, } from '@chakra-ui/react'; -import { useEnsureOnScreen } from 'common/hooks/useEnsureOnScreen'; +import { autoUpdate, offset, shift, useFloating } from '@floating-ui/react-dom'; import { useSelect } from 'downshift'; import { OverlayScrollbarsComponent } from 'overlayscrollbars-react'; -import { memo, useRef } from 'react'; -import { useIntersection } from 'react-use'; - -const BUTTON_BG = 'base.900'; -const BORDER_HOVER = 'base.700'; -const BORDER_FOCUS = 'accent.600'; +import { memo } from 'react'; type IAICustomSelectProps = { label?: string; @@ -31,6 +28,9 @@ type IAICustomSelectProps = { setSelectedItem: (v: string | null | undefined) => void; withCheckIcon?: boolean; formControlProps?: FormControlProps; + buttonProps?: FlexProps; + tooltip?: string; + tooltipProps?: Omit; }; const IAICustomSelect = (props: IAICustomSelectProps) => { @@ -41,6 +41,9 @@ const IAICustomSelect = (props: IAICustomSelectProps) => { selectedItem, withCheckIcon, formControlProps, + tooltip, + buttonProps, + tooltipProps, } = props; const { @@ -57,105 +60,111 @@ const IAICustomSelect = (props: IAICustomSelectProps) => { setSelectedItem(newSelectedItem), }); - const toggleButtonRef = useRef(null); - const menuRef = useRef(null); + const { refs, floatingStyles } = useFloating({ + whileElementsMounted: autoUpdate, + middleware: [offset(4), shift({ crossAxis: true, padding: 8 })], + }); return ( - + {label && ( { - toggleButtonRef.current && toggleButtonRef.current.focus(); + refs.floating.current && refs.floating.current.focus(); }} > {label} )} - - - - {isOpen && - items.map((item, index) => ( - - {withCheckIcon ? ( - - - {selectedItem === item && } - - - - {item} - - - - ) : ( - - {item} - - )} - - ))} - - + + + + + {isOpen && ( + + + {items.map((item, index) => ( + + {withCheckIcon ? ( + + + {selectedItem === item && } + + + + {item} + + + + ) : ( + + {item} + + )} + + ))} + + + )} + ); }; diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamSampler.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamSampler.tsx index bd31a73829..b3dd4a0f27 100644 --- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamSampler.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamSampler.tsx @@ -1,5 +1,6 @@ import { RootState } from 'app/store/store'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; +import IAICustomSelect from 'common/components/IAICustomSelect'; import IAISelect from 'common/components/IAISelect'; import { setSampler } from 'features/parameters/store/generationSlice'; import { activeTabNameSelector } from 'features/ui/store/uiSelectors'; @@ -23,21 +24,26 @@ const ParamSampler = () => { const { t } = useTranslation(); const handleChange = useCallback( - (e: ChangeEvent) => dispatch(setSampler(e.target.value)), + (v: string | null | undefined) => { + if (!v) { + return; + } + dispatch(setSampler(v)); + }, [dispatch] ); return ( - ); }; diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamSchedulerAndModel.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamSchedulerAndModel.tsx new file mode 100644 index 0000000000..489d4fad55 --- /dev/null +++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamSchedulerAndModel.tsx @@ -0,0 +1,19 @@ +import { Box, Flex } from '@chakra-ui/react'; +import { memo } from 'react'; +import ParamSampler from './ParamSampler'; +import ModelSelect from 'features/system/components/ModelSelect'; + +const ParamSchedulerAndModel = () => { + return ( + + + + + + + + + ); +}; + +export default memo(ParamSchedulerAndModel); diff --git a/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts b/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts index 5ad0e4973c..604aabbc9b 100644 --- a/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts +++ b/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts @@ -2,8 +2,9 @@ import type { PayloadAction } from '@reduxjs/toolkit'; import { createSlice } from '@reduxjs/toolkit'; import * as InvokeAI from 'app/types/invokeai'; import promptToString from 'common/util/promptToString'; -import { clamp } from 'lodash-es'; +import { clamp, sample } from 'lodash-es'; import { setAllParametersReducer } from './setAllParametersReducer'; +import { receivedModels } from 'services/thunks/model'; export interface GenerationState { cfgScale: number; @@ -236,6 +237,16 @@ export const generationSlice = createSlice({ state.model = action.payload; }, }, + extraReducers: (builder) => { + builder.addCase(receivedModels.fulfilled, (state, action) => { + if (!state.model) { + const randomModel = sample(action.payload); + if (randomModel) { + state.model = randomModel.name; + } + } + }); + }, }); export const { diff --git a/invokeai/frontend/web/src/features/system/components/ModelSelect.tsx b/invokeai/frontend/web/src/features/system/components/ModelSelect.tsx index e38fda2676..520e30b60a 100644 --- a/invokeai/frontend/web/src/features/system/components/ModelSelect.tsx +++ b/invokeai/frontend/web/src/features/system/components/ModelSelect.tsx @@ -1,21 +1,20 @@ import { createSelector } from '@reduxjs/toolkit'; -import { ChangeEvent, memo } from 'react'; +import { memo, useCallback } from 'react'; import { isEqual } from 'lodash-es'; import { useTranslation } from 'react-i18next'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; -import IAISelect from 'common/components/IAISelect'; import { selectModelsById, selectModelsIds } from '../store/modelSlice'; import { RootState } from 'app/store/store'; import { modelSelected } from 'features/parameters/store/generationSlice'; import { generationSelector } from 'features/parameters/store/generationSelectors'; +import IAICustomSelect from 'common/components/IAICustomSelect'; const selector = createSelector( [(state: RootState) => state, generationSelector], (state, generation) => { - // const selectedModel = selectedModelSelector(state); const selectedModel = selectModelsById(state, generation.model); - const allModelNames = selectModelsIds(state); + const allModelNames = selectModelsIds(state).map((id) => String(id)); return { allModelNames, selectedModel, @@ -32,19 +31,25 @@ const ModelSelect = () => { const dispatch = useAppDispatch(); const { t } = useTranslation(); const { allModelNames, selectedModel } = useAppSelector(selector); - const handleChangeModel = (e: ChangeEvent) => { - dispatch(modelSelected(e.target.value)); - }; + const handleChangeModel = useCallback( + (v: string | null | undefined) => { + if (!v) { + return; + } + dispatch(modelSelected(v)); + }, + [dispatch] + ); return ( - ); }; diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/ImageToImage/ImageToImageTabCoreParameters.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/ImageToImage/ImageToImageTabCoreParameters.tsx index aba85646af..c4161154bb 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/ImageToImage/ImageToImageTabCoreParameters.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/ImageToImage/ImageToImageTabCoreParameters.tsx @@ -1,5 +1,5 @@ import { memo } from 'react'; -import { Box, Flex } from '@chakra-ui/react'; +import { Flex } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; import { uiSelector } from 'features/ui/store/uiSelectors'; import { useAppSelector } from 'app/store/storeHooks'; @@ -9,11 +9,10 @@ import ParamSteps from 'features/parameters/components/Parameters/Core/ParamStep import ParamCFGScale from 'features/parameters/components/Parameters/Core/ParamCFGScale'; import ParamWidth from 'features/parameters/components/Parameters/Core/ParamWidth'; import ParamHeight from 'features/parameters/components/Parameters/Core/ParamHeight'; -import ParamSampler from 'features/parameters/components/Parameters/Core/ParamSampler'; -import ModelSelect from 'features/system/components/ModelSelect'; import ImageToImageStrength from 'features/parameters/components/Parameters/ImageToImage/ImageToImageStrength'; import ImageToImageFit from 'features/parameters/components/Parameters/ImageToImage/ImageToImageFit'; import { generationSelector } from 'features/parameters/store/generationSelectors'; +import ParamSchedulerAndModel from 'features/parameters/components/Parameters/Core/ParamSchedulerAndModel'; const selector = createSelector( [uiSelector, generationSelector], @@ -48,14 +47,7 @@ const ImageToImageTabCoreParameters = () => { - - - - - - - - + ) : ( @@ -64,14 +56,7 @@ const ImageToImageTabCoreParameters = () => { - - - - - - - - + diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/TextToImage/TextToImageTabCoreParameters.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/TextToImage/TextToImageTabCoreParameters.tsx index d7edef148c..59512775bc 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/TextToImage/TextToImageTabCoreParameters.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/TextToImage/TextToImageTabCoreParameters.tsx @@ -3,14 +3,13 @@ import ParamSteps from 'features/parameters/components/Parameters/Core/ParamStep import ParamCFGScale from 'features/parameters/components/Parameters/Core/ParamCFGScale'; import ParamWidth from 'features/parameters/components/Parameters/Core/ParamWidth'; import ParamHeight from 'features/parameters/components/Parameters/Core/ParamHeight'; -import ParamSampler from 'features/parameters/components/Parameters/Core/ParamSampler'; -import ModelSelect from 'features/system/components/ModelSelect'; -import { Box, Flex } from '@chakra-ui/react'; +import { Flex } from '@chakra-ui/react'; import { useAppSelector } from 'app/store/storeHooks'; import { createSelector } from '@reduxjs/toolkit'; import { uiSelector } from 'features/ui/store/uiSelectors'; import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; import { memo } from 'react'; +import ParamSchedulerAndModel from 'features/parameters/components/Parameters/Core/ParamSchedulerAndModel'; const selector = createSelector( uiSelector, @@ -42,14 +41,7 @@ const TextToImageTabCoreParameters = () => { - - - - - - - - + ) : ( @@ -58,14 +50,7 @@ const TextToImageTabCoreParameters = () => { - - - - - - - - + diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasCoreParameters.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasCoreParameters.tsx index 74949a399d..f2529e5529 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasCoreParameters.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasCoreParameters.tsx @@ -1,10 +1,9 @@ import { memo } from 'react'; -import { Box, Flex } from '@chakra-ui/react'; +import { Flex } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; import { uiSelector } from 'features/ui/store/uiSelectors'; import { useAppSelector } from 'app/store/storeHooks'; import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; -import ModelSelect from 'features/system/components/ModelSelect'; import ParamIterations from 'features/parameters/components/Parameters/Core/ParamIterations'; import ParamSteps from 'features/parameters/components/Parameters/Core/ParamSteps'; import ParamCFGScale from 'features/parameters/components/Parameters/Core/ParamCFGScale'; @@ -12,7 +11,7 @@ import ParamWidth from 'features/parameters/components/Parameters/Core/ParamWidt import ParamHeight from 'features/parameters/components/Parameters/Core/ParamHeight'; import ImageToImageStrength from 'features/parameters/components/Parameters/ImageToImage/ImageToImageStrength'; import ImageToImageFit from 'features/parameters/components/Parameters/ImageToImage/ImageToImageFit'; -import ParamSampler from 'features/parameters/components/Parameters/Core/ParamSampler'; +import ParamSchedulerAndModel from 'features/parameters/components/Parameters/Core/ParamSchedulerAndModel'; const selector = createSelector( uiSelector, @@ -46,14 +45,7 @@ const UnifiedCanvasCoreParameters = () => { - - - - - - - - + ) : ( @@ -62,14 +54,7 @@ const UnifiedCanvasCoreParameters = () => { - - - - - - - - + From 0020457fc706715bb79a1a6fc9e03e92817b16a8 Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Sat, 13 May 2023 23:59:03 +1000 Subject: [PATCH 09/14] fix(ui): tweak settings scheduler styling --- .../SettingsModal/SettingsSchedulers.tsx | 26 ++++++------------- 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsSchedulers.tsx b/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsSchedulers.tsx index dd0dac284a..7e44257408 100644 --- a/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsSchedulers.tsx +++ b/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsSchedulers.tsx @@ -1,4 +1,5 @@ import { + Box, Menu, MenuButton, MenuItemOption, @@ -12,8 +13,7 @@ import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIButton from 'common/components/IAIButton'; import { setSchedulers } from 'features/ui/store/uiSlice'; import { isArray } from 'lodash-es'; - -import { ReactNode } from 'react'; +import { OverlayScrollbarsComponent } from 'overlayscrollbars-react'; import { useTranslation } from 'react-i18next'; export default function SettingsSchedulers() { @@ -26,32 +26,22 @@ export default function SettingsSchedulers() { if (isArray(v)) dispatch(setSchedulers(v.sort())); }; - const renderSchedulerMenuItems = () => { - const schedulerMenuItemsToRender: ReactNode[] = []; - - SCHEDULERS.forEach((scheduler) => { - schedulerMenuItemsToRender.push( - - {scheduler} - - ); - }); - - return schedulerMenuItemsToRender; - }; - return ( {t('settings.availableSchedulers')} - + - {renderSchedulerMenuItems()} + {SCHEDULERS.map((scheduler) => ( + + {scheduler} + + ))} From 5a7b687c84fbf5be4e1f42bc80da923dd60bad7c Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Sat, 13 May 2023 23:59:20 +1000 Subject: [PATCH 10/14] fix(ui): add missing packages --- invokeai/frontend/web/package.json | 2 ++ invokeai/frontend/web/yarn.lock | 46 ++++++++++++++++++++++++++++-- 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/invokeai/frontend/web/package.json b/invokeai/frontend/web/package.json index 13f79f4a44..404d20d937 100644 --- a/invokeai/frontend/web/package.json +++ b/invokeai/frontend/web/package.json @@ -62,11 +62,13 @@ "@dagrejs/graphlib": "^2.1.12", "@emotion/react": "^11.10.6", "@emotion/styled": "^11.10.6", + "@floating-ui/react-dom": "^2.0.0", "@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", + "downshift": "^7.6.0", "formik": "^2.2.9", "framer-motion": "^10.12.4", "fuse.js": "^6.6.2", diff --git a/invokeai/frontend/web/yarn.lock b/invokeai/frontend/web/yarn.lock index 2313cf91c7..de2925ae8c 100644 --- a/invokeai/frontend/web/yarn.lock +++ b/invokeai/frontend/web/yarn.lock @@ -57,7 +57,7 @@ dependencies: regenerator-runtime "^0.13.11" -"@babel/runtime@^7.1.2": +"@babel/runtime@^7.1.2", "@babel/runtime@^7.14.8": version "7.21.5" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.21.5.tgz#8492dddda9644ae3bda3b45eabe87382caee7200" integrity sha512-8jI69toZqqcsnqGGqwGS4Qb1VwLOEp4hz+CXPywcvjs60u3B4Pom/U/7rm4W8tMOYEB+E9wgD0mW1l3r8qlI9Q== @@ -1198,6 +1198,25 @@ resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.39.0.tgz#58b536bcc843f4cd1e02a7e6171da5c040f4d44b" integrity sha512-kf9RB0Fg7NZfap83B3QOqOGg9QmD9yBudqQXzzOtn3i4y7ZUXe5ONeW34Gwi+TxhH4mvj72R1Zc300KUMa9Bng== +"@floating-ui/core@^1.2.6": + version "1.2.6" + resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.2.6.tgz#d21ace437cc919cdd8f1640302fa8851e65e75c0" + integrity sha512-EvYTiXet5XqweYGClEmpu3BoxmsQ4hkj3QaYA6qEnigCWffTP3vNRwBReTdrwDwo7OoJ3wM8Uoe9Uk4n+d4hfg== + +"@floating-ui/dom@^1.2.7": + version "1.2.7" + resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.2.7.tgz#c123e4db014b07b97e996cd459245fa217049c6b" + integrity sha512-DyqylONj1ZaBnzj+uBnVfzdjjCkFCL2aA9ESHLyUOGSqb03RpbLMImP1ekIQXYs4KLk9jAjJfZAU8hXfWSahEg== + dependencies: + "@floating-ui/core" "^1.2.6" + +"@floating-ui/react-dom@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-2.0.0.tgz#7514baac526c818892bbcc84e1c3115008c029f9" + integrity sha512-Ke0oU3SeuABC2C4OFu2mSAwHIP5WUiV98O9YWoHV4Q5aT6E9k06DV0Khi5uYspR8xmmBk08t8ZDcz3TR3ARkEg== + dependencies: + "@floating-ui/dom" "^1.2.7" + "@fontsource/inter@^4.5.15": version "4.5.15" resolved "https://registry.yarnpkg.com/@fontsource/inter/-/inter-4.5.15.tgz#eed1873d68755d3b52d6fcfcfa3493118430a512" @@ -2680,6 +2699,11 @@ compute-scroll-into-view@1.0.20: resolved "https://registry.yarnpkg.com/compute-scroll-into-view/-/compute-scroll-into-view-1.0.20.tgz#1768b5522d1172754f5d0c9b02de3af6be506a43" integrity sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg== +compute-scroll-into-view@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/compute-scroll-into-view/-/compute-scroll-into-view-2.0.4.tgz#2b444b2b9e4724819d2531efacb7ac094155fdf6" + integrity sha512-y/ZA3BGnxoM/QHHQ2Uy49CLtnWPbt4tTPpEEZiEmmiWBFKjej7nEyH8Ryz54jH0MLXflUYA3Er2zUxPSJu5R+g== + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -3131,6 +3155,17 @@ dot-prop@^5.2.0: dependencies: is-obj "^2.0.0" +downshift@^7.6.0: + version "7.6.0" + resolved "https://registry.yarnpkg.com/downshift/-/downshift-7.6.0.tgz#de04fb2962bd6c4ea94589c797c91f34aa9816f3" + integrity sha512-VSoTVynTAsabou/hbZ6HJHUVhtBiVOjQoBsCPcQq5eAROIGP+9XKMp9asAKQ3cEcUP4oe0fFdD2pziUjhFY33Q== + dependencies: + "@babel/runtime" "^7.14.8" + compute-scroll-into-view "^2.0.4" + prop-types "^15.7.2" + react-is "^17.0.2" + tslib "^2.3.0" + duplexer3@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.5.tgz#0b5e4d7bad5de8901ea4440624c8e1d20099217e" @@ -5356,7 +5391,7 @@ pretty-ms@^7.0.1: dependencies: parse-ms "^2.1.0" -prop-types@^15.6.2, prop-types@^15.8.1: +prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== @@ -5517,6 +5552,11 @@ react-is@^16.13.1, react-is@^16.7.0: resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== +react-is@^17.0.2: + version "17.0.2" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" + integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== + react-is@^18.0.0: version "18.2.0" resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" @@ -6485,7 +6525,7 @@ tslib@^1.10.0, tslib@^1.8.1: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.0.0, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.4.0: +tslib@^2.0.0, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.0, tslib@^2.4.0: version "2.5.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.0.tgz#42bfed86f5787aeb41d031866c8f402429e0fddf" integrity sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg== From d3a7fea9396f5cee15374e54ecdcab84fd4108ad Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Sat, 13 May 2023 23:59:30 +1000 Subject: [PATCH 11/14] Revert "fix: Rework the layout of the parameters scrollbar" This reverts commit 6f1fc397f75fe0fdb3a50639cfad52bf98604146. --- .../src/features/ui/components/ParametersPinnedWrapper.tsx | 7 +------ .../features/ui/components/common/OverlayScrollable.tsx | 6 +++--- .../ui/components/tabs/ImageToImage/ImageToImageTab.tsx | 2 +- .../ui/components/tabs/TextToImage/TextToImageTab.tsx | 2 +- .../ui/components/tabs/UnifiedCanvas/UnifiedCanvasTab.tsx | 2 +- 5 files changed, 7 insertions(+), 12 deletions(-) diff --git a/invokeai/frontend/web/src/features/ui/components/ParametersPinnedWrapper.tsx b/invokeai/frontend/web/src/features/ui/components/ParametersPinnedWrapper.tsx index cfb2ad267c..407187294c 100644 --- a/invokeai/frontend/web/src/features/ui/components/ParametersPinnedWrapper.tsx +++ b/invokeai/frontend/web/src/features/ui/components/ParametersPinnedWrapper.tsx @@ -43,18 +43,13 @@ const ParametersPinnedWrapper = (props: ParametersPinnedWrapperProps) => { h: 'full', w: 'full', position: 'absolute', - paddingRight: 4, }} > {props.children} ); diff --git a/invokeai/frontend/web/src/features/ui/components/common/OverlayScrollable.tsx b/invokeai/frontend/web/src/features/ui/components/common/OverlayScrollable.tsx index a993f02ce6..71413fd01a 100644 --- a/invokeai/frontend/web/src/features/ui/components/common/OverlayScrollable.tsx +++ b/invokeai/frontend/web/src/features/ui/components/common/OverlayScrollable.tsx @@ -8,9 +8,9 @@ const OverlayScrollable = (props: PropsWithChildren) => { style={{ height: '100%', width: '100%' }} options={{ scrollbars: { - visibility: 'visible', - autoHide: 'never', - autoHideDelay: 500, + visibility: 'auto', + autoHide: 'move', + autoHideDelay: 1300, theme: 'os-theme-dark', }, overflow: { x: 'hidden' }, diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/ImageToImage/ImageToImageTab.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/ImageToImage/ImageToImageTab.tsx index 46d416204d..cbd261f455 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/ImageToImage/ImageToImageTab.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/ImageToImage/ImageToImageTab.tsx @@ -23,7 +23,7 @@ const ImageToImageTab = () => { }, []); return ( - + diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/TextToImage/TextToImageTab.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/TextToImage/TextToImageTab.tsx index 6c140172be..87e77cc3ba 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/TextToImage/TextToImageTab.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/TextToImage/TextToImageTab.tsx @@ -6,7 +6,7 @@ import ParametersPinnedWrapper from '../../ParametersPinnedWrapper'; const TextToImageTab = () => { return ( - + diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasTab.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasTab.tsx index aa8c1c6a76..2d591d1ecc 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasTab.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasTab.tsx @@ -20,7 +20,7 @@ const UnifiedCanvasTab = () => { const { shouldUseCanvasBetaLayout } = useAppSelector(selector); return ( - + From dac82adb5b61ed953e129b89f0db8faa6ce92af2 Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Sun, 14 May 2023 18:41:11 +1000 Subject: [PATCH 12/14] fix(ui): make logo component non-selectable --- .../system/components/InvokeAILogoComponent.tsx | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/invokeai/frontend/web/src/features/system/components/InvokeAILogoComponent.tsx b/invokeai/frontend/web/src/features/system/components/InvokeAILogoComponent.tsx index e736450563..a38a751b8b 100644 --- a/invokeai/frontend/web/src/features/system/components/InvokeAILogoComponent.tsx +++ b/invokeai/frontend/web/src/features/system/components/InvokeAILogoComponent.tsx @@ -17,8 +17,17 @@ const InvokeAILogoComponent = () => { h="32px" minW="32px" minH="32px" + userSelect="none" /> - + invoke ai From f5df1500973ef73accd886b47a0b2a4382a7ca8f Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Sun, 14 May 2023 18:42:15 +1000 Subject: [PATCH 13/14] feat(ui): add callback to signal app is ready needed for commercial --- .../frontend/web/src/app/components/App.tsx | 17 ++++++++++++++++- .../web/src/app/components/InvokeAIUI.tsx | 15 +++++++++++++-- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/invokeai/frontend/web/src/app/components/App.tsx b/invokeai/frontend/web/src/app/components/App.tsx index 3fbcbc49ea..eb6496f43e 100644 --- a/invokeai/frontend/web/src/app/components/App.tsx +++ b/invokeai/frontend/web/src/app/components/App.tsx @@ -30,9 +30,14 @@ const DEFAULT_CONFIG = {}; interface Props { config?: PartialAppConfig; headerComponent?: ReactNode; + setIsReady?: (isReady: boolean) => void; } -const App = ({ config = DEFAULT_CONFIG, headerComponent }: Props) => { +const App = ({ + config = DEFAULT_CONFIG, + headerComponent, + setIsReady, +}: Props) => { useToastWatcher(); useGlobalHotkeys(); @@ -61,6 +66,16 @@ const App = ({ config = DEFAULT_CONFIG, headerComponent }: Props) => { setLoadingOverridden(true); }, []); + useEffect(() => { + if (isApplicationReady && setIsReady) { + setIsReady(true); + } + + return () => { + setIsReady && setIsReady(false); + }; + }, [isApplicationReady, setIsReady]); + return ( {isLightboxEnabled && } diff --git a/invokeai/frontend/web/src/app/components/InvokeAIUI.tsx b/invokeai/frontend/web/src/app/components/InvokeAIUI.tsx index 442c1d967a..c04a8184d7 100644 --- a/invokeai/frontend/web/src/app/components/InvokeAIUI.tsx +++ b/invokeai/frontend/web/src/app/components/InvokeAIUI.tsx @@ -24,9 +24,16 @@ interface Props extends PropsWithChildren { token?: string; config?: PartialAppConfig; headerComponent?: ReactNode; + setIsReady?: (isReady: boolean) => void; } -const InvokeAIUI = ({ apiUrl, token, config, headerComponent }: Props) => { +const InvokeAIUI = ({ + apiUrl, + token, + config, + headerComponent, + setIsReady, +}: Props) => { useEffect(() => { // configure API client token if (token) { @@ -55,7 +62,11 @@ const InvokeAIUI = ({ apiUrl, token, config, headerComponent }: Props) => { }> - + From cf36e4029e269a759cba7371e437ca012f0d9fa2 Mon Sep 17 00:00:00 2001 From: Eugene Brodsky Date: Sun, 14 May 2023 14:38:15 -0400 Subject: [PATCH 14/14] fix(ui): fix syntax error in the logo component flexbox --- .../src/features/system/components/InvokeAILogoComponent.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/invokeai/frontend/web/src/features/system/components/InvokeAILogoComponent.tsx b/invokeai/frontend/web/src/features/system/components/InvokeAILogoComponent.tsx index a38a751b8b..f6017d02f0 100644 --- a/invokeai/frontend/web/src/features/system/components/InvokeAILogoComponent.tsx +++ b/invokeai/frontend/web/src/features/system/components/InvokeAILogoComponent.tsx @@ -25,7 +25,7 @@ const InvokeAILogoComponent = () => { base: 'inherit', sm: 'none', md: 'inherit', - userSelect = 'none', + userSelect: 'none', }} >