diff --git a/invokeai/app/services/default_graphs.py b/invokeai/app/services/default_graphs.py index 0ac6b08b4d..5eda5e957d 100644 --- a/invokeai/app/services/default_graphs.py +++ b/invokeai/app/services/default_graphs.py @@ -48,13 +48,14 @@ def create_text_to_image() -> LibraryGraph: def create_system_graphs(graph_library: ItemStorageABC[LibraryGraph]) -> list[LibraryGraph]: """Creates the default system graphs, or adds new versions if the old ones don't match""" - + + # TODO: Uncomment this when we are ready to fix this up to prevent breaking changes graphs: list[LibraryGraph] = list() # text_to_image = graph_library.get(default_text_to_image_graph_id) - # TODO: Check if the graph is the same as the default one, and if not, update it - #if text_to_image is None: + # # TODO: Check if the graph is the same as the default one, and if not, update it + # #if text_to_image is None: text_to_image = create_text_to_image() graph_library.set(text_to_image) diff --git a/invokeai/app/services/processor.py b/invokeai/app/services/processor.py index 35cbcd5068..9e3b5a0a30 100644 --- a/invokeai/app/services/processor.py +++ b/invokeai/app/services/processor.py @@ -1,3 +1,4 @@ +import time import traceback from threading import Event, Thread, BoundedSemaphore @@ -6,6 +7,7 @@ from .invocation_queue import InvocationQueueItem from .invoker import InvocationProcessorABC, Invoker from ..models.exceptions import CanceledException +import invokeai.backend.util.logging as logger class DefaultInvocationProcessor(InvocationProcessorABC): __invoker_thread: Thread __stop_event: Event @@ -34,8 +36,14 @@ class DefaultInvocationProcessor(InvocationProcessorABC): try: self.__threadLimit.acquire() while not stop_event.is_set(): - queue_item: InvocationQueueItem = self.__invoker.services.queue.get() + try: + queue_item: InvocationQueueItem = self.__invoker.services.queue.get() + except Exception as e: + logger.debug("Exception while getting from queue: %s" % e) + if not queue_item: # Probably stopping + # do not hammer the queue + time.sleep(0.5) continue graph_execution_state = ( @@ -124,7 +132,16 @@ class DefaultInvocationProcessor(InvocationProcessorABC): # Queue any further commands if invoking all is_complete = graph_execution_state.is_complete() if queue_item.invoke_all and not is_complete: - self.__invoker.invoke(graph_execution_state, invoke_all=True) + try: + self.__invoker.invoke(graph_execution_state, invoke_all=True) + except Exception as e: + logger.error("Error while invoking: %s" % e) + self.__invoker.services.events.emit_invocation_error( + graph_execution_state_id=graph_execution_state.id, + node=invocation.dict(), + source_node_id=source_node_id, + error=traceback.format_exc() + ) elif is_complete: self.__invoker.services.events.emit_graph_execution_complete( graph_execution_state.id 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/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/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 189fbc9dd4..b74c67befd 100644 --- a/invokeai/frontend/web/src/app/constants.ts +++ b/invokeai/frontend/web/src/app/constants.ts @@ -1,29 +1,24 @@ // TODO: use Enums? -export const DIFFUSERS_SCHEDULERS: Array = [ +export const SCHEDULERS: Array = [ 'ddim', - 'ddpm', - 'deis', 'lms', - 'pndm', - 'heun', '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/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' 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..d9610346ec --- /dev/null +++ b/invokeai/frontend/web/src/common/components/IAICustomSelect.tsx @@ -0,0 +1,172 @@ +import { CheckIcon } from '@chakra-ui/icons'; +import { + Box, + Flex, + FlexProps, + FormControl, + FormControlProps, + FormLabel, + Grid, + GridItem, + List, + ListItem, + Select, + Text, + Tooltip, + TooltipProps, +} from '@chakra-ui/react'; +import { autoUpdate, offset, shift, useFloating } from '@floating-ui/react-dom'; +import { useSelect } from 'downshift'; +import { OverlayScrollbarsComponent } from 'overlayscrollbars-react'; + +import { memo } from 'react'; + +type IAICustomSelectProps = { + label?: string; + items: string[]; + selectedItem: string; + setSelectedItem: (v: string | null | undefined) => void; + withCheckIcon?: boolean; + formControlProps?: FormControlProps; + buttonProps?: FlexProps; + tooltip?: string; + tooltipProps?: Omit; +}; + +const IAICustomSelect = (props: IAICustomSelectProps) => { + const { + label, + items, + setSelectedItem, + selectedItem, + withCheckIcon, + formControlProps, + tooltip, + buttonProps, + tooltipProps, + } = props; + + const { + isOpen, + getToggleButtonProps, + getLabelProps, + getMenuProps, + highlightedIndex, + getItemProps, + } = useSelect({ + items, + selectedItem, + onSelectedItemChange: ({ selectedItem: newSelectedItem }) => + setSelectedItem(newSelectedItem), + }); + + const { refs, floatingStyles } = useFloating({ + whileElementsMounted: autoUpdate, + middleware: [offset(4), shift({ crossAxis: true, padding: 8 })], + }); + + return ( + + {label && ( + { + refs.floating.current && refs.floating.current.focus(); + }} + > + {label} + + )} + + + + + {isOpen && ( + + + {items.map((item, index) => ( + + {withCheckIcon ? ( + + + {selectedItem === item && } + + + + {item} + + + + ) : ( + + {item} + + )} + + ))} + + + )} + + + ); +}; + +export default memo(IAICustomSelect); 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 = () => { ) : ( { + // rehydrate selectedImage URL when results list comes in + // solves case when outdated URL is in local storage + if (state.selectedImage) { + const selectedImageInResults = action.payload.items.find( + (image) => image.image_name === state.selectedImage!.name + ); + if (selectedImageInResults) { + state.selectedImage.url = selectedImageInResults.image_url; + } + } + }); + builder.addCase(receivedUploadImagesPage.fulfilled, (state, action) => { + // rehydrate selectedImage URL when results list comes in + // solves case when outdated URL is in local storage + if (state.selectedImage) { + const selectedImageInResults = action.payload.items.find( + (image) => image.image_name === state.selectedImage!.name + ); + if (selectedImageInResults) { + state.selectedImage.url = selectedImageInResults.image_url; + } + } + }); }, }); 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..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,9 +1,6 @@ -import { - DIFFUSERS_SCHEDULERS, - IMG2IMG_DIFFUSERS_SCHEDULERS, -} from 'app/constants'; 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'; @@ -17,25 +14,36 @@ 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(); 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/components/Parameters/ImageToImage/InitialImagePreview.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/ImageToImage/InitialImagePreview.tsx index 3de1e1cebb..ca54d2fd67 100644 --- a/invokeai/frontend/web/src/features/parameters/components/Parameters/ImageToImage/InitialImagePreview.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/ImageToImage/InitialImagePreview.tsx @@ -1,4 +1,4 @@ -import { Flex, Image } from '@chakra-ui/react'; +import { Flex, Icon, Image } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import SelectImagePlaceholder from 'common/components/SelectImagePlaceholder'; @@ -13,6 +13,7 @@ import { generationSelector } from 'features/parameters/store/generationSelector import { initialImageSelected } from 'features/parameters/store/actions'; import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; import ImageFallbackSpinner from 'features/gallery/components/ImageFallbackSpinner'; +import { FaImage } from 'react-icons/fa'; const selector = createSelector( [generationSelector], @@ -83,7 +84,15 @@ const InitialImagePreview = () => { )} - {!initialImage?.url && } + {!initialImage?.url && ( + + )} ); }; 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/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())); + }; + + return ( + + + {t('settings.availableSchedulers')} + + + + {SCHEDULERS.map((scheduler) => ( + + {scheduler} + + ))} + + + + ); +} 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 = () => { - - - - - - - - + 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[]; } 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==