ui: cleanup (#3418)

- tidy up a lot of cruft
- `sampler` --> `scheduler`
This commit is contained in:
blessedcoolant 2023-05-16 15:27:12 +12:00 committed by GitHub
commit 30af20a056
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
50 changed files with 223 additions and 567 deletions

View File

@ -450,7 +450,7 @@
"cfgScale": "CFG Scale", "cfgScale": "CFG Scale",
"width": "Width", "width": "Width",
"height": "Height", "height": "Height",
"sampler": "Sampler", "scheduler": "Scheduler",
"seed": "Seed", "seed": "Seed",
"imageToImage": "Image to Image", "imageToImage": "Image to Image",
"randomizeSeed": "Randomize Seed", "randomizeSeed": "Randomize Seed",

View File

@ -6,7 +6,7 @@ import FloatingGalleryButton from 'features/ui/components/FloatingGalleryButton'
import FloatingParametersPanelButtons from 'features/ui/components/FloatingParametersPanelButtons'; import FloatingParametersPanelButtons from 'features/ui/components/FloatingParametersPanelButtons';
import { Box, Flex, Grid, Portal } from '@chakra-ui/react'; import { Box, Flex, Grid, Portal } from '@chakra-ui/react';
import { APP_HEIGHT, APP_WIDTH } from 'theme/util/constants'; import { APP_HEIGHT, APP_WIDTH } from 'theme/util/constants';
import GalleryDrawer from 'features/gallery/components/ImageGalleryPanel'; import GalleryDrawer from 'features/gallery/components/GalleryPanel';
import Lightbox from 'features/lightbox/components/Lightbox'; import Lightbox from 'features/lightbox/components/Lightbox';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { memo, ReactNode, useCallback, useEffect, useState } from 'react'; import { memo, ReactNode, useCallback, useEffect, useState } from 'react';
@ -22,7 +22,6 @@ import { languageSelector } from 'features/system/store/systemSelectors';
import i18n from 'i18n'; import i18n from 'i18n';
import Toaster from './Toaster'; import Toaster from './Toaster';
import GlobalHotkeys from './GlobalHotkeys'; import GlobalHotkeys from './GlobalHotkeys';
import AuxiliaryProgressIndicator from './AuxiliaryProgressIndicator';
const DEFAULT_CONFIG = {}; const DEFAULT_CONFIG = {};

View File

@ -1,6 +1,6 @@
// TODO: use Enums? // TODO: use Enums?
export const SCHEDULERS: Array<string> = [ export const SCHEDULERS = [
'ddim', 'ddim',
'lms', 'lms',
'euler', 'euler',
@ -17,7 +17,12 @@ export const SCHEDULERS: Array<string> = [
'heun', 'heun',
'heun_k', 'heun_k',
'unipc', 'unipc',
]; ] as const;
export type Scheduler = (typeof SCHEDULERS)[number];
export const isScheduler = (x: string): x is Scheduler =>
SCHEDULERS.includes(x as Scheduler);
// Valid image widths // Valid image widths
export const WIDTHS: Array<number> = Array.from(Array(64)).map( export const WIDTHS: Array<number> = Array.from(Array(64)).map(

View File

@ -3,18 +3,8 @@ import { CanvasState } from './canvasTypes';
/** /**
* Canvas slice persist denylist * Canvas slice persist denylist
*/ */
const itemsToDenylist: (keyof CanvasState)[] = [
'cursorPosition',
'isCanvasInitialized',
'doesCanvasNeedScaling',
];
export const canvasPersistDenylist: (keyof CanvasState)[] = [ export const canvasPersistDenylist: (keyof CanvasState)[] = [
'cursorPosition', 'cursorPosition',
'isCanvasInitialized', 'isCanvasInitialized',
'doesCanvasNeedScaling', 'doesCanvasNeedScaling',
]; ];
export const canvasDenylist = itemsToDenylist.map(
(denylistItem) => `canvas.${denylistItem}`
);

View File

@ -47,10 +47,7 @@ import {
FaTrash, FaTrash,
FaWrench, FaWrench,
} from 'react-icons/fa'; } from 'react-icons/fa';
import { import { gallerySelector } from '../store/gallerySelectors';
gallerySelector,
selectedImageSelector,
} from '../store/gallerySelectors';
import DeleteImageModal from './DeleteImageModal'; import DeleteImageModal from './DeleteImageModal';
import { useCallback } from 'react'; import { useCallback } from 'react';
import { requestCanvasRescale } from 'features/canvas/store/thunks/requestCanvasScale'; import { requestCanvasRescale } from 'features/canvas/store/thunks/requestCanvasScale';
@ -73,15 +70,15 @@ const currentImageButtonsSelector = createSelector(
uiSelector, uiSelector,
lightboxSelector, lightboxSelector,
activeTabNameSelector, activeTabNameSelector,
selectedImageSelector,
], ],
(system, gallery, postprocessing, ui, lightbox, activeTabName, image) => { (system, gallery, postprocessing, ui, lightbox, activeTabName) => {
const { const {
isProcessing, isProcessing,
isConnected, isConnected,
isGFPGANAvailable, isGFPGANAvailable,
isESRGANAvailable, isESRGANAvailable,
shouldConfirmOnDelete, shouldConfirmOnDelete,
progressImage,
} = system; } = system;
const { upscalingLevel, facetoolStrength } = postprocessing; const { upscalingLevel, facetoolStrength } = postprocessing;
@ -90,7 +87,7 @@ const currentImageButtonsSelector = createSelector(
const { shouldShowImageDetails, shouldHidePreview } = ui; const { shouldShowImageDetails, shouldHidePreview } = ui;
const { intermediateImage, currentImage } = gallery; const { selectedImage } = gallery;
return { return {
canDeleteImage: isConnected && !isProcessing, canDeleteImage: isConnected && !isProcessing,
@ -101,15 +98,14 @@ const currentImageButtonsSelector = createSelector(
isESRGANAvailable, isESRGANAvailable,
upscalingLevel, upscalingLevel,
facetoolStrength, facetoolStrength,
shouldDisableToolbarButtons: Boolean(intermediateImage) || !currentImage, shouldDisableToolbarButtons: Boolean(progressImage) || !selectedImage,
currentImage,
shouldShowImageDetails, shouldShowImageDetails,
activeTabName, activeTabName,
isLightboxOpen, isLightboxOpen,
shouldHidePreview, shouldHidePreview,
image, image: selectedImage,
seed: image?.metadata?.invokeai?.node?.seed, seed: selectedImage?.metadata?.invokeai?.node?.seed,
prompt: image?.metadata?.invokeai?.node?.prompt, prompt: selectedImage?.metadata?.invokeai?.node?.prompt,
}; };
}, },
{ {

View File

@ -4,18 +4,18 @@ import { useAppSelector } from 'app/store/storeHooks';
import { systemSelector } from 'features/system/store/systemSelectors'; import { systemSelector } from 'features/system/store/systemSelectors';
import { isEqual } from 'lodash-es'; import { isEqual } from 'lodash-es';
import { selectedImageSelector } from '../store/gallerySelectors'; import { gallerySelector } from '../store/gallerySelectors';
import CurrentImageButtons from './CurrentImageButtons'; import CurrentImageButtons from './CurrentImageButtons';
import CurrentImagePreview from './CurrentImagePreview'; import CurrentImagePreview from './CurrentImagePreview';
import { FaImage } from 'react-icons/fa'; import { FaImage } from 'react-icons/fa';
export const currentImageDisplaySelector = createSelector( export const currentImageDisplaySelector = createSelector(
[systemSelector, selectedImageSelector], [systemSelector, gallerySelector],
(system, selectedImage) => { (system, gallery) => {
const { progressImage } = system; const { progressImage } = system;
return { return {
hasAnImageToDisplay: selectedImage || progressImage, hasAnImageToDisplay: gallery.selectedImage || progressImage,
}; };
}, },
{ {

View File

@ -1,10 +1,6 @@
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { gallerySelector } from 'features/gallery/store/gallerySelectors'; import { gallerySelector } from 'features/gallery/store/gallerySelectors';
import { import { setGalleryImageMinimumWidth } from 'features/gallery/store/gallerySlice';
// selectNextImage,
// selectPrevImage,
setGalleryImageMinimumWidth,
} from 'features/gallery/store/gallerySlice';
import { clamp, isEqual } from 'lodash-es'; import { clamp, isEqual } from 'lodash-es';
import { useHotkeys } from 'react-hotkeys-hook'; import { useHotkeys } from 'react-hotkeys-hook';
@ -23,20 +19,7 @@ import { requestCanvasRescale } from 'features/canvas/store/thunks/requestCanvas
import { lightboxSelector } from 'features/lightbox/store/lightboxSelectors'; import { lightboxSelector } from 'features/lightbox/store/lightboxSelectors';
import { memo } from 'react'; import { memo } from 'react';
// const GALLERY_TAB_WIDTHS: Record< const selector = createSelector(
// InvokeTabName,
// { galleryMinWidth: number; galleryMaxWidth: number }
// > = {
// txt2img: { galleryMinWidth: 200, galleryMaxWidth: 500 },
// img2img: { galleryMinWidth: 200, galleryMaxWidth: 500 },
// generate: { galleryMinWidth: 200, galleryMaxWidth: 500 },
// unifiedCanvas: { galleryMinWidth: 200, galleryMaxWidth: 200 },
// nodes: { galleryMinWidth: 200, galleryMaxWidth: 500 },
// postprocessing: { galleryMinWidth: 200, galleryMaxWidth: 500 },
// training: { galleryMinWidth: 200, galleryMaxWidth: 500 },
// };
const galleryPanelSelector = createSelector(
[ [
activeTabNameSelector, activeTabNameSelector,
uiSelector, uiSelector,
@ -76,41 +59,13 @@ const GalleryDrawer = () => {
// isStaging, // isStaging,
// isResizable, // isResizable,
// isLightboxOpen, // isLightboxOpen,
} = useAppSelector(galleryPanelSelector); } = useAppSelector(selector);
// const handleSetShouldPinGallery = () => {
// dispatch(togglePinGalleryPanel());
// dispatch(requestCanvasRescale());
// };
// const handleToggleGallery = () => {
// dispatch(toggleGalleryPanel());
// shouldPinGallery && dispatch(requestCanvasRescale());
// };
const handleCloseGallery = () => { const handleCloseGallery = () => {
dispatch(setShouldShowGallery(false)); dispatch(setShouldShowGallery(false));
shouldPinGallery && dispatch(requestCanvasRescale()); shouldPinGallery && dispatch(requestCanvasRescale());
}; };
// const resolution = useResolution();
// useHotkeys(
// 'g',
// () => {
// handleToggleGallery();
// },
// [shouldPinGallery]
// );
// useHotkeys(
// 'shift+g',
// () => {
// handleSetShouldPinGallery();
// },
// [shouldPinGallery]
// );
useHotkeys( useHotkeys(
'esc', 'esc',
() => { () => {
@ -155,54 +110,6 @@ const GalleryDrawer = () => {
[galleryImageMinimumWidth] [galleryImageMinimumWidth]
); );
// const calcGalleryMinHeight = () => {
// if (resolution === 'desktop') return;
// return 300;
// };
// const imageGalleryContent = () => {
// return (
// <Flex
// w="100vw"
// h={{ base: 300, xl: '100vh' }}
// paddingRight={{ base: 8, xl: 0 }}
// paddingBottom={{ base: 4, xl: 0 }}
// >
// <ImageGalleryContent />
// </Flex>
// );
// };
// const resizableImageGalleryContent = () => {
// return (
// <ResizableDrawer
// direction="right"
// isResizable={isResizable || !shouldPinGallery}
// isOpen={shouldShowGallery}
// onClose={handleCloseGallery}
// isPinned={shouldPinGallery && !isLightboxOpen}
// minWidth={
// shouldPinGallery
// ? GALLERY_TAB_WIDTHS[activeTabName].galleryMinWidth
// : 200
// }
// maxWidth={
// shouldPinGallery
// ? GALLERY_TAB_WIDTHS[activeTabName].galleryMaxWidth
// : undefined
// }
// minHeight={calcGalleryMinHeight()}
// >
// <ImageGalleryContent />
// </ResizableDrawer>
// );
// };
// const renderImageGallery = () => {
// if (['mobile', 'tablet'].includes(resolution)) return imageGalleryContent();
// return resizableImageGalleryContent();
// };
if (shouldPinGallery) { if (shouldPinGallery) {
return null; return null;
} }
@ -218,8 +125,6 @@ const GalleryDrawer = () => {
<ImageGalleryContent /> <ImageGalleryContent />
</ResizableDrawer> </ResizableDrawer>
); );
// return renderImageGallery();
}; };
export default memo(GalleryDrawer); export default memo(GalleryDrawer);

View File

@ -15,10 +15,7 @@ import IAICheckbox from 'common/components/IAICheckbox';
import IAIIconButton from 'common/components/IAIIconButton'; import IAIIconButton from 'common/components/IAIIconButton';
import IAIPopover from 'common/components/IAIPopover'; import IAIPopover from 'common/components/IAIPopover';
import IAISlider from 'common/components/IAISlider'; import IAISlider from 'common/components/IAISlider';
import { import { gallerySelector } from 'features/gallery/store/gallerySelectors';
gallerySelector,
imageGallerySelector,
} from 'features/gallery/store/gallerySelectors';
import { import {
setCurrentCategory, setCurrentCategory,
setGalleryImageMinimumWidth, setGalleryImageMinimumWidth,
@ -57,11 +54,12 @@ import { Virtuoso, VirtuosoGrid } from 'react-virtuoso';
import { Image as ImageType } from 'app/types/invokeai'; import { Image as ImageType } from 'app/types/invokeai';
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
import GalleryProgressImage from './GalleryProgressImage'; import GalleryProgressImage from './GalleryProgressImage';
import { uiSelector } from 'features/ui/store/uiSelectors';
const GALLERY_SHOW_BUTTONS_MIN_WIDTH = 290; const GALLERY_SHOW_BUTTONS_MIN_WIDTH = 290;
const PROGRESS_IMAGE_PLACEHOLDER = 'PROGRESS_IMAGE_PLACEHOLDER'; const PROGRESS_IMAGE_PLACEHOLDER = 'PROGRESS_IMAGE_PLACEHOLDER';
const selector = createSelector( const categorySelector = createSelector(
[(state: RootState) => state], [(state: RootState) => state],
(state) => { (state) => {
const { results, uploads, system, gallery } = state; const { results, uploads, system, gallery } = state;
@ -92,6 +90,33 @@ const selector = createSelector(
defaultSelectorOptions defaultSelectorOptions
); );
const mainSelector = createSelector(
[gallerySelector, uiSelector],
(gallery, ui) => {
const {
currentCategory,
galleryImageMinimumWidth,
galleryImageObjectFit,
shouldAutoSwitchToNewImages,
shouldUseSingleGalleryColumn,
selectedImage,
} = gallery;
const { shouldPinGallery } = ui;
return {
currentCategory,
shouldPinGallery,
galleryImageMinimumWidth,
galleryImageObjectFit,
shouldAutoSwitchToNewImages,
shouldUseSingleGalleryColumn,
selectedImage,
};
},
defaultSelectorOptions
);
const ImageGalleryContent = () => { const ImageGalleryContent = () => {
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const { t } = useTranslation(); const { t } = useTranslation();
@ -113,7 +138,6 @@ const ImageGalleryContent = () => {
}); });
const { const {
// images,
currentCategory, currentCategory,
shouldPinGallery, shouldPinGallery,
galleryImageMinimumWidth, galleryImageMinimumWidth,
@ -121,10 +145,10 @@ const ImageGalleryContent = () => {
shouldAutoSwitchToNewImages, shouldAutoSwitchToNewImages,
shouldUseSingleGalleryColumn, shouldUseSingleGalleryColumn,
selectedImage, selectedImage,
} = useAppSelector(imageGallerySelector); } = useAppSelector(mainSelector);
const { images, areMoreImagesAvailable, isLoading } = const { images, areMoreImagesAvailable, isLoading } =
useAppSelector(selector); useAppSelector(categorySelector);
const handleClickLoadMore = () => { const handleClickLoadMore = () => {
if (currentCategory === 'results') { if (currentCategory === 'results') {

View File

@ -19,7 +19,7 @@ import {
setHeight, setHeight,
setImg2imgStrength, setImg2imgStrength,
setPerlin, setPerlin,
setSampler, setScheduler,
setSeamless, setSeamless,
setSeed, setSeed,
setSeedWeights, setSeedWeights,
@ -202,9 +202,9 @@ const ImageMetadataViewer = memo(({ image }: ImageMetadataViewerProps) => {
)} )}
{node.scheduler && ( {node.scheduler && (
<MetadataItem <MetadataItem
label="Sampler" label="Scheduler"
value={node.scheduler} value={node.scheduler}
onClick={() => dispatch(setSampler(node.scheduler))} onClick={() => dispatch(setScheduler(node.scheduler))}
/> />
)} )}
{node.steps && ( {node.steps && (

View File

@ -3,16 +3,7 @@ import { GalleryState } from './gallerySlice';
/** /**
* Gallery slice persist denylist * Gallery slice persist denylist
*/ */
const itemsToDenylist: (keyof GalleryState)[] = [
'currentCategory',
'shouldAutoSwitchToNewImages',
];
export const galleryPersistDenylist: (keyof GalleryState)[] = [ export const galleryPersistDenylist: (keyof GalleryState)[] = [
'currentCategory', 'currentCategory',
'shouldAutoSwitchToNewImages', 'shouldAutoSwitchToNewImages',
]; ];
export const galleryDenylist = itemsToDenylist.map(
(denylistItem) => `gallery.${denylistItem}`
);

View File

@ -1,83 +1,3 @@
import { createSelector } from '@reduxjs/toolkit';
import { RootState } from 'app/store/store'; import { RootState } from 'app/store/store';
import { lightboxSelector } from 'features/lightbox/store/lightboxSelectors';
import {
activeTabNameSelector,
uiSelector,
} from 'features/ui/store/uiSelectors';
import { isEqual } from 'lodash-es';
import { selectResultsById, selectResultsEntities } from './resultsSlice';
import { selectUploadsAll, selectUploadsById } from './uploadsSlice';
export const gallerySelector = (state: RootState) => state.gallery; export const gallerySelector = (state: RootState) => state.gallery;
export const imageGallerySelector = createSelector(
[
(state: RootState) => state,
gallerySelector,
uiSelector,
lightboxSelector,
activeTabNameSelector,
],
(state, gallery, ui, lightbox, activeTabName) => {
const {
currentCategory,
galleryImageMinimumWidth,
galleryImageObjectFit,
shouldAutoSwitchToNewImages,
galleryWidth,
shouldUseSingleGalleryColumn,
selectedImage,
} = gallery;
const { shouldPinGallery } = ui;
const { isLightboxOpen } = lightbox;
const images =
currentCategory === 'results'
? selectResultsEntities(state)
: selectUploadsAll(state);
return {
shouldPinGallery,
galleryImageMinimumWidth,
galleryImageObjectFit,
galleryGridTemplateColumns: shouldUseSingleGalleryColumn
? 'auto'
: `repeat(auto-fill, minmax(${galleryImageMinimumWidth}px, auto))`,
shouldAutoSwitchToNewImages,
currentCategory,
images,
galleryWidth,
shouldEnableResize:
isLightboxOpen ||
(activeTabName === 'unifiedCanvas' && shouldPinGallery)
? false
: true,
shouldUseSingleGalleryColumn,
selectedImage,
};
},
{
memoizeOptions: {
resultEqualityCheck: isEqual,
},
}
);
export const selectedImageSelector = createSelector(
[(state: RootState) => state, gallerySelector],
(state, gallery) => {
const selectedImage = gallery.selectedImage;
if (selectedImage?.type === 'results') {
return selectResultsById(state, selectedImage.name);
}
if (selectedImage?.type === 'uploads') {
return selectUploadsById(state, selectedImage.name);
}
}
);

View File

@ -10,14 +10,10 @@ import {
type GalleryImageObjectFitType = 'contain' | 'cover'; type GalleryImageObjectFitType = 'contain' | 'cover';
export interface GalleryState { export interface GalleryState {
/**
* The selected image
*/
selectedImage?: Image; selectedImage?: Image;
galleryImageMinimumWidth: number; galleryImageMinimumWidth: number;
galleryImageObjectFit: GalleryImageObjectFitType; galleryImageObjectFit: GalleryImageObjectFitType;
shouldAutoSwitchToNewImages: boolean; shouldAutoSwitchToNewImages: boolean;
galleryWidth: number;
shouldUseSingleGalleryColumn: boolean; shouldUseSingleGalleryColumn: boolean;
currentCategory: 'results' | 'uploads'; currentCategory: 'results' | 'uploads';
} }
@ -26,7 +22,6 @@ export const initialGalleryState: GalleryState = {
galleryImageMinimumWidth: 64, galleryImageMinimumWidth: 64,
galleryImageObjectFit: 'cover', galleryImageObjectFit: 'cover',
shouldAutoSwitchToNewImages: true, shouldAutoSwitchToNewImages: true,
galleryWidth: 300,
shouldUseSingleGalleryColumn: false, shouldUseSingleGalleryColumn: false,
currentCategory: 'results', currentCategory: 'results',
}; };
@ -58,9 +53,6 @@ export const gallerySlice = createSlice({
) => { ) => {
state.currentCategory = action.payload; state.currentCategory = action.payload;
}, },
setGalleryWidth: (state, action: PayloadAction<number>) => {
state.galleryWidth = action.payload;
},
setShouldUseSingleGalleryColumn: ( setShouldUseSingleGalleryColumn: (
state, state,
action: PayloadAction<boolean> action: PayloadAction<boolean>
@ -93,24 +85,28 @@ export const gallerySlice = createSlice({
builder.addCase(receivedResultImagesPage.fulfilled, (state, action) => { builder.addCase(receivedResultImagesPage.fulfilled, (state, action) => {
// rehydrate selectedImage URL when results list comes in // rehydrate selectedImage URL when results list comes in
// solves case when outdated URL is in local storage // solves case when outdated URL is in local storage
if (state.selectedImage) { const selectedImage = state.selectedImage;
if (selectedImage) {
const selectedImageInResults = action.payload.items.find( const selectedImageInResults = action.payload.items.find(
(image) => image.image_name === state.selectedImage!.name (image) => image.image_name === selectedImage.name
); );
if (selectedImageInResults) { if (selectedImageInResults) {
state.selectedImage.url = selectedImageInResults.image_url; selectedImage.url = selectedImageInResults.image_url;
state.selectedImage = selectedImage;
} }
} }
}); });
builder.addCase(receivedUploadImagesPage.fulfilled, (state, action) => { builder.addCase(receivedUploadImagesPage.fulfilled, (state, action) => {
// rehydrate selectedImage URL when results list comes in // rehydrate selectedImage URL when results list comes in
// solves case when outdated URL is in local storage // solves case when outdated URL is in local storage
if (state.selectedImage) { const selectedImage = state.selectedImage;
if (selectedImage) {
const selectedImageInResults = action.payload.items.find( const selectedImageInResults = action.payload.items.find(
(image) => image.image_name === state.selectedImage!.name (image) => image.image_name === selectedImage.name
); );
if (selectedImageInResults) { if (selectedImageInResults) {
state.selectedImage.url = selectedImageInResults.image_url; selectedImage.url = selectedImageInResults.image_url;
state.selectedImage = selectedImage;
} }
} }
}); });
@ -122,7 +118,6 @@ export const {
setGalleryImageMinimumWidth, setGalleryImageMinimumWidth,
setGalleryImageObjectFit, setGalleryImageObjectFit,
setShouldAutoSwitchToNewImages, setShouldAutoSwitchToNewImages,
setGalleryWidth,
setShouldUseSingleGalleryColumn, setShouldUseSingleGalleryColumn,
setCurrentCategory, setCurrentCategory,
} = gallerySlice.actions; } = gallerySlice.actions;

View File

@ -3,12 +3,6 @@ import { ResultsState } from './resultsSlice';
/** /**
* Results slice persist denylist * Results slice persist denylist
* *
* Currently denylisting results slice entirely, see persist config in store.ts * Currently denylisting results slice entirely, see `serialize.ts`
*/ */
const itemsToDenylist: (keyof ResultsState)[] = [];
export const resultsPersistDenylist: (keyof ResultsState)[] = []; export const resultsPersistDenylist: (keyof ResultsState)[] = [];
export const resultsDenylist = itemsToDenylist.map(
(denylistItem) => `results.${denylistItem}`
);

View File

@ -3,11 +3,6 @@ import { UploadsState } from './uploadsSlice';
/** /**
* Uploads slice persist denylist * Uploads slice persist denylist
* *
* Currently denylisting uploads slice entirely, see persist config in store.ts * Currently denylisting uploads slice entirely, see `serialize.ts`
*/ */
const itemsToDenylist: (keyof UploadsState)[] = [];
export const uploadsPersistDenylist: (keyof UploadsState)[] = []; export const uploadsPersistDenylist: (keyof UploadsState)[] = [];
export const uploadsDenylist = itemsToDenylist.map(
(denylistItem) => `uploads.${denylistItem}`
);

View File

@ -3,11 +3,6 @@ import { LightboxState } from './lightboxSlice';
/** /**
* Lightbox slice persist denylist * Lightbox slice persist denylist
*/ */
const itemsToDenylist: (keyof LightboxState)[] = ['isLightboxOpen'];
export const lightboxPersistDenylist: (keyof LightboxState)[] = [ export const lightboxPersistDenylist: (keyof LightboxState)[] = [
'isLightboxOpen', 'isLightboxOpen',
]; ];
export const lightboxDenylist = itemsToDenylist.map(
(denylistItem) => `lightbox.${denylistItem}`
);

View File

@ -3,12 +3,7 @@ import { NodesState } from './nodesSlice';
/** /**
* Nodes slice persist denylist * Nodes slice persist denylist
*/ */
const itemsToDenylist: (keyof NodesState)[] = ['schema', 'invocationTemplates'];
export const nodesPersistDenylist: (keyof NodesState)[] = [ export const nodesPersistDenylist: (keyof NodesState)[] = [
'schema', 'schema',
'invocationTemplates', 'invocationTemplates',
]; ];
export const nodesDenylist = itemsToDenylist.map(
(denylistItem) => `nodes.${denylistItem}`
);

View File

@ -26,16 +26,18 @@ const buildBaseNode = (
| ImageToImageInvocation | ImageToImageInvocation
| InpaintInvocation | InpaintInvocation
| undefined => { | undefined => {
const dimensionsOverride = state.canvas.boundingBoxDimensions;
if (nodeType === 'txt2img') { if (nodeType === 'txt2img') {
return buildTxt2ImgNode(state, state.canvas.boundingBoxDimensions); return buildTxt2ImgNode(state, dimensionsOverride);
} }
if (nodeType === 'img2img') { if (nodeType === 'img2img') {
return buildImg2ImgNode(state, state.canvas.boundingBoxDimensions); return buildImg2ImgNode(state, dimensionsOverride);
} }
if (nodeType === 'inpaint' || nodeType === 'outpaint') { if (nodeType === 'inpaint' || nodeType === 'outpaint') {
return buildInpaintNode(state, state.canvas.boundingBoxDimensions); return buildInpaintNode(state, dimensionsOverride);
} }
}; };

View File

@ -25,7 +25,7 @@ export const buildImg2ImgNode = (
width, width,
height, height,
cfgScale, cfgScale,
sampler, scheduler,
model, model,
img2imgStrength: strength, img2imgStrength: strength,
shouldFitToWidthHeight: fit, shouldFitToWidthHeight: fit,
@ -43,14 +43,14 @@ export const buildImg2ImgNode = (
width, width,
height, height,
cfg_scale: cfgScale, cfg_scale: cfgScale,
scheduler: sampler as ImageToImageInvocation['scheduler'], scheduler,
model, model,
strength, strength,
fit, fit,
}; };
// on Canvas tab, we do not manually specific init image // on Canvas tab, we do not manually specific init image
if (activeTabName === 'img2img') { if (activeTabName !== 'unifiedCanvas') {
if (!initialImage) { if (!initialImage) {
// TODO: handle this more better // TODO: handle this more better
throw 'no initial image'; throw 'no initial image';

View File

@ -1,17 +1,16 @@
import { v4 as uuidv4 } from 'uuid'; import { v4 as uuidv4 } from 'uuid';
import { RootState } from 'app/store/store'; import { RootState } from 'app/store/store';
import { InpaintInvocation } from 'services/api'; import { InpaintInvocation } from 'services/api';
import { initialImageSelector } from 'features/parameters/store/generationSelectors';
import { O } from 'ts-toolbelt'; import { O } from 'ts-toolbelt';
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
export const buildInpaintNode = ( export const buildInpaintNode = (
state: RootState, state: RootState,
overrides: O.Partial<InpaintInvocation, 'deep'> = {} overrides: O.Partial<InpaintInvocation, 'deep'> = {}
): InpaintInvocation => { ): InpaintInvocation => {
const nodeId = uuidv4(); const nodeId = uuidv4();
const { generation, models } = state; const { generation } = state;
const activeTabName = activeTabNameSelector(state);
const { selectedModelName } = models;
const { const {
prompt, prompt,
@ -21,21 +20,15 @@ export const buildInpaintNode = (
width, width,
height, height,
cfgScale, cfgScale,
sampler, scheduler,
seamless, model,
img2imgStrength: strength, img2imgStrength: strength,
shouldFitToWidthHeight: fit, shouldFitToWidthHeight: fit,
shouldRandomizeSeed, shouldRandomizeSeed,
initialImage,
} = generation; } = generation;
const initialImage = initialImageSelector(state); const inpaintNode: InpaintInvocation = {
if (!initialImage) {
// TODO: handle this
// throw 'no initial image';
}
const imageToImageNode: InpaintInvocation = {
id: nodeId, id: nodeId,
type: 'inpaint', type: 'inpaint',
prompt: `${prompt} [${negativePrompt}]`, prompt: `${prompt} [${negativePrompt}]`,
@ -43,25 +36,30 @@ export const buildInpaintNode = (
width, width,
height, height,
cfg_scale: cfgScale, cfg_scale: cfgScale,
scheduler: sampler as InpaintInvocation['scheduler'], scheduler,
seamless, model,
model: selectedModelName,
progress_images: true,
image: initialImage
? {
image_name: initialImage.name,
image_type: initialImage.type,
}
: undefined,
strength, strength,
fit, fit,
}; };
if (!shouldRandomizeSeed) { // on Canvas tab, we do not manually specific init image
imageToImageNode.seed = seed; if (activeTabName !== 'unifiedCanvas') {
if (!initialImage) {
// TODO: handle this more better
throw 'no initial image';
}
inpaintNode.image = {
image_name: initialImage.name,
image_type: initialImage.type,
};
} }
Object.assign(imageToImageNode, overrides); if (!shouldRandomizeSeed) {
inpaintNode.seed = seed;
}
return imageToImageNode; Object.assign(inpaintNode, overrides);
return inpaintNode;
}; };

View File

@ -18,7 +18,7 @@ export const buildTxt2ImgNode = (
width, width,
height, height,
cfgScale: cfg_scale, cfgScale: cfg_scale,
sampler, scheduler,
shouldRandomizeSeed, shouldRandomizeSeed,
model, model,
} = generation; } = generation;
@ -31,7 +31,7 @@ export const buildTxt2ImgNode = (
width, width,
height, height,
cfg_scale, cfg_scale,
scheduler: sampler as TextToImageInvocation['scheduler'], scheduler,
model, model,
}; };

View File

@ -1,15 +1,15 @@
import { Scheduler } from 'app/constants';
import { RootState } from 'app/store/store'; import { RootState } from 'app/store/store';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import IAICustomSelect from 'common/components/IAICustomSelect'; import IAICustomSelect from 'common/components/IAICustomSelect';
import IAISelect from 'common/components/IAISelect'; import { setScheduler } from 'features/parameters/store/generationSlice';
import { setSampler } from 'features/parameters/store/generationSlice';
import { activeTabNameSelector } from 'features/ui/store/uiSelectors'; import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
import { ChangeEvent, memo, useCallback } from 'react'; import { memo, useCallback } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
const ParamSampler = () => { const ParamScheduler = () => {
const sampler = useAppSelector( const scheduler = useAppSelector(
(state: RootState) => state.generation.sampler (state: RootState) => state.generation.scheduler
); );
const activeTabName = useAppSelector(activeTabNameSelector); const activeTabName = useAppSelector(activeTabNameSelector);
@ -28,15 +28,15 @@ const ParamSampler = () => {
if (!v) { if (!v) {
return; return;
} }
dispatch(setSampler(v)); dispatch(setScheduler(v as Scheduler));
}, },
[dispatch] [dispatch]
); );
return ( return (
<IAICustomSelect <IAICustomSelect
label={t('parameters.sampler')} label={t('parameters.scheduler')}
selectedItem={sampler} selectedItem={scheduler}
setSelectedItem={handleChange} setSelectedItem={handleChange}
items={ items={
['img2img', 'unifiedCanvas'].includes(activeTabName) ['img2img', 'unifiedCanvas'].includes(activeTabName)
@ -48,4 +48,4 @@ const ParamSampler = () => {
); );
}; };
export default memo(ParamSampler); export default memo(ParamScheduler);

View File

@ -1,13 +1,13 @@
import { Box, Flex } from '@chakra-ui/react'; import { Box, Flex } from '@chakra-ui/react';
import { memo } from 'react'; import { memo } from 'react';
import ParamSampler from './ParamSampler';
import ModelSelect from 'features/system/components/ModelSelect'; import ModelSelect from 'features/system/components/ModelSelect';
import ParamScheduler from './ParamScheduler';
const ParamSchedulerAndModel = () => { const ParamSchedulerAndModel = () => {
return ( return (
<Flex gap={3} w="full"> <Flex gap={3} w="full">
<Box w="16rem"> <Box w="16rem">
<ParamSampler /> <ParamScheduler />
</Box> </Box>
<Box w="full"> <Box w="full">
<ModelSelect /> <ModelSelect />

View File

@ -3,9 +3,4 @@ import { GenerationState } from './generationSlice';
/** /**
* Generation slice persist denylist * Generation slice persist denylist
*/ */
const itemsToDenylist: (keyof GenerationState)[] = [];
export const generationPersistDenylist: (keyof GenerationState)[] = []; export const generationPersistDenylist: (keyof GenerationState)[] = [];
export const generationDenylist = itemsToDenylist.map(
(denylistItem) => `generation.${denylistItem}`
);

View File

@ -5,19 +5,19 @@ import promptToString from 'common/util/promptToString';
import { clamp, sample } from 'lodash-es'; import { clamp, sample } from 'lodash-es';
import { setAllParametersReducer } from './setAllParametersReducer'; import { setAllParametersReducer } from './setAllParametersReducer';
import { receivedModels } from 'services/thunks/model'; import { receivedModels } from 'services/thunks/model';
import { Scheduler } from 'app/constants';
export interface GenerationState { export interface GenerationState {
cfgScale: number; cfgScale: number;
height: number; height: number;
img2imgStrength: number; img2imgStrength: number;
infillMethod: string; infillMethod: string;
initialImage?: InvokeAI.Image; // can be an Image or url initialImage?: InvokeAI.Image;
iterations: number; iterations: number;
maskPath: string;
perlin: number; perlin: number;
prompt: string; prompt: string;
negativePrompt: string; negativePrompt: string;
sampler: string; scheduler: Scheduler;
seamBlur: number; seamBlur: number;
seamSize: number; seamSize: number;
seamSteps: number; seamSteps: number;
@ -48,11 +48,10 @@ export const initialGenerationState: GenerationState = {
img2imgStrength: 0.75, img2imgStrength: 0.75,
infillMethod: 'patchmatch', infillMethod: 'patchmatch',
iterations: 1, iterations: 1,
maskPath: '',
perlin: 0, perlin: 0,
prompt: '', prompt: '',
negativePrompt: '', negativePrompt: '',
sampler: 'lms', scheduler: 'lms',
seamBlur: 16, seamBlur: 16,
seamSize: 96, seamSize: 96,
seamSteps: 30, seamSteps: 30,
@ -135,8 +134,8 @@ export const generationSlice = createSlice({
setWidth: (state, action: PayloadAction<number>) => { setWidth: (state, action: PayloadAction<number>) => {
state.width = action.payload; state.width = action.payload;
}, },
setSampler: (state, action: PayloadAction<string>) => { setScheduler: (state, action: PayloadAction<Scheduler>) => {
state.sampler = action.payload; state.scheduler = action.payload;
}, },
setSeed: (state, action: PayloadAction<number>) => { setSeed: (state, action: PayloadAction<number>) => {
state.seed = action.payload; state.seed = action.payload;
@ -145,9 +144,6 @@ export const generationSlice = createSlice({
setImg2imgStrength: (state, action: PayloadAction<number>) => { setImg2imgStrength: (state, action: PayloadAction<number>) => {
state.img2imgStrength = action.payload; state.img2imgStrength = action.payload;
}, },
setMaskPath: (state, action: PayloadAction<string>) => {
state.maskPath = action.payload;
},
setSeamless: (state, action: PayloadAction<boolean>) => { setSeamless: (state, action: PayloadAction<boolean>) => {
state.shouldUseSeamless = action.payload; state.shouldUseSeamless = action.payload;
}, },
@ -163,19 +159,6 @@ export const generationSlice = createSlice({
resetSeed: (state) => { resetSeed: (state) => {
state.seed = -1; state.seed = -1;
}, },
setParameter: (
state,
action: PayloadAction<{ key: string; value: string | number | boolean }>
) => {
// TODO: This probably needs to be refactored.
// TODO: This probably also needs to be fixed after the reorg.
const { key, value } = action.payload;
const temp = { ...state, [key]: value };
if (key === 'seed') {
temp.shouldRandomizeSeed = false;
}
return temp;
},
setShouldGenerateVariations: (state, action: PayloadAction<boolean>) => { setShouldGenerateVariations: (state, action: PayloadAction<boolean>) => {
state.shouldGenerateVariations = action.payload; state.shouldGenerateVariations = action.payload;
}, },
@ -258,14 +241,11 @@ export const {
setHeight, setHeight,
setImg2imgStrength, setImg2imgStrength,
setInfillMethod, setInfillMethod,
// setInitialImage,
setIterations, setIterations,
setMaskPath,
setParameter,
setPerlin, setPerlin,
setPrompt, setPrompt,
setNegativePrompt, setNegativePrompt,
setSampler, setScheduler,
setSeamBlur, setSeamBlur,
setSeamSize, setSeamSize,
setSeamSteps, setSeamSteps,

View File

@ -3,9 +3,4 @@ import { PostprocessingState } from './postprocessingSlice';
/** /**
* Postprocessing slice persist denylist * Postprocessing slice persist denylist
*/ */
const itemsToDenylist: (keyof PostprocessingState)[] = [];
export const postprocessingPersistDenylist: (keyof PostprocessingState)[] = []; export const postprocessingPersistDenylist: (keyof PostprocessingState)[] = [];
export const postprocessingDenylist = itemsToDenylist.map(
(denylistItem) => `postprocessing.${denylistItem}`
);

View File

@ -2,6 +2,7 @@ import { Draft, PayloadAction } from '@reduxjs/toolkit';
import { Image } from 'app/types/invokeai'; import { Image } from 'app/types/invokeai';
import { GenerationState } from './generationSlice'; import { GenerationState } from './generationSlice';
import { ImageToImageInvocation } from 'services/api'; import { ImageToImageInvocation } from 'services/api';
import { isScheduler } from 'app/constants';
export const setAllParametersReducer = ( export const setAllParametersReducer = (
state: Draft<GenerationState>, state: Draft<GenerationState>,
@ -34,7 +35,10 @@ export const setAllParametersReducer = (
state.prompt = String(prompt); state.prompt = String(prompt);
} }
if (scheduler !== undefined) { if (scheduler !== undefined) {
state.sampler = String(scheduler); const schedulerString = String(scheduler);
if (isScheduler(schedulerString)) {
state.scheduler = schedulerString;
}
} }
if (seed !== undefined) { if (seed !== undefined) {
state.seed = Number(seed); state.seed = Number(seed);

View File

@ -13,26 +13,15 @@ export const modelsAdapter = createEntityAdapter<Model>({
sortComparer: (a, b) => a.name.localeCompare(b.name), sortComparer: (a, b) => a.name.localeCompare(b.name),
}); });
type AdditionalModelsState = { export const initialModelsState = modelsAdapter.getInitialState();
selectedModelName: string;
};
export const initialModelsState =
modelsAdapter.getInitialState<AdditionalModelsState>({
selectedModelName: '',
});
export type ModelsState = typeof initialModelsState; export type ModelsState = typeof initialModelsState;
export const modelsSlice = createSlice({ export const modelsSlice = createSlice({
name: 'models', name: 'models',
initialState: modelsAdapter.getInitialState(), initialState: initialModelsState,
// initialState: initialModelsState,
reducers: { reducers: {
modelAdded: modelsAdapter.upsertOne, modelAdded: modelsAdapter.upsertOne,
// modelSelected: (state, action: PayloadAction<string>) => {
// state.selectedModelName = action.payload;
// },
}, },
extraReducers(builder) { extraReducers(builder) {
/** /**
@ -41,32 +30,10 @@ export const modelsSlice = createSlice({
builder.addCase(receivedModels.fulfilled, (state, action) => { builder.addCase(receivedModels.fulfilled, (state, action) => {
const models = action.payload; const models = action.payload;
modelsAdapter.setAll(state, models); modelsAdapter.setAll(state, models);
// If the current selected model is `''` or isn't actually in the list of models,
// choose a random model
// if (
// !state.selectedModelName ||
// !keys(models).includes(state.selectedModelName)
// ) {
// const randomModel = sample(models);
// if (randomModel) {
// state.selectedModelName = randomModel.name;
// } else {
// state.selectedModelName = '';
// }
// }
}); });
}, },
}); });
// export const selectedModelSelector = (state: RootState) => {
// const { selectedModelName } = state.models;
// const selectedModel = selectModelsById(state, selectedModelName);
// return selectedModel ?? null;
// };
export const { export const {
selectAll: selectModelsAll, selectAll: selectModelsAll,
selectById: selectModelsById, selectById: selectModelsById,
@ -75,9 +42,6 @@ export const {
selectTotal: selectModelsTotal, selectTotal: selectModelsTotal,
} = modelsAdapter.getSelectors<RootState>((state) => state.models); } = modelsAdapter.getSelectors<RootState>((state) => state.models);
export const { export const { modelAdded } = modelsSlice.actions;
modelAdded,
// modelSelected
} = modelsSlice.actions;
export default modelsSlice.reducer; export default modelsSlice.reducer;

View File

@ -3,9 +3,4 @@ import { ModelsState } from './modelSlice';
/** /**
* Models slice persist denylist * Models slice persist denylist
*/ */
const itemsToDenylist: (keyof ModelsState)[] = ['entities', 'ids'];
export const modelsPersistDenylist: (keyof ModelsState)[] = ['entities', 'ids']; export const modelsPersistDenylist: (keyof ModelsState)[] = ['entities', 'ids'];
export const modelsDenylist = itemsToDenylist.map(
(denylistItem) => `models.${denylistItem}`
);

View File

@ -5,14 +5,12 @@ import { SystemState } from './systemSlice';
*/ */
export const systemPersistDenylist: (keyof SystemState)[] = [ export const systemPersistDenylist: (keyof SystemState)[] = [
'currentIteration', 'currentIteration',
'currentStatus',
'currentStep', 'currentStep',
'isCancelable', 'isCancelable',
'isConnected', 'isConnected',
'isESRGANAvailable', 'isESRGANAvailable',
'isGFPGANAvailable', 'isGFPGANAvailable',
'isProcessing', 'isProcessing',
'socketId',
'totalIterations', 'totalIterations',
'totalSteps', 'totalSteps',
'openModel', 'openModel',

View File

@ -143,73 +143,15 @@ export const systemSlice = createSlice({
setCurrentStatus: (state, action: PayloadAction<TFuncKey>) => { setCurrentStatus: (state, action: PayloadAction<TFuncKey>) => {
state.statusTranslationKey = action.payload; state.statusTranslationKey = action.payload;
}, },
errorOccurred: (state) => {
state.isProcessing = false;
state.isCancelable = true;
state.currentStep = 0;
state.totalSteps = 0;
state.currentIteration = 0;
state.totalIterations = 0;
state.currentStatusHasSteps = false;
state.statusTranslationKey = 'common.statusError';
},
setIsConnected: (state, action: PayloadAction<boolean>) => {
state.isConnected = action.payload;
state.isProcessing = false;
state.isCancelable = true;
state.currentStep = 0;
state.totalSteps = 0;
state.currentIteration = 0;
state.totalIterations = 0;
state.currentStatusHasSteps = false;
},
setShouldConfirmOnDelete: (state, action: PayloadAction<boolean>) => { setShouldConfirmOnDelete: (state, action: PayloadAction<boolean>) => {
state.shouldConfirmOnDelete = action.payload; state.shouldConfirmOnDelete = action.payload;
}, },
setShouldDisplayGuides: (state, action: PayloadAction<boolean>) => { setShouldDisplayGuides: (state, action: PayloadAction<boolean>) => {
state.shouldDisplayGuides = action.payload; state.shouldDisplayGuides = action.payload;
}, },
processingCanceled: (state) => {
state.isProcessing = false;
state.isCancelable = true;
state.currentStep = 0;
state.totalSteps = 0;
state.currentIteration = 0;
state.totalIterations = 0;
state.currentStatusHasSteps = false;
state.statusTranslationKey = 'common.statusProcessingCanceled';
},
generationRequested: (state) => {
state.isProcessing = true;
state.isCancelable = true;
state.currentStep = 0;
state.totalSteps = 0;
state.currentIteration = 0;
state.totalIterations = 0;
state.currentStatusHasSteps = false;
state.statusTranslationKey = 'common.statusPreparing';
},
setIsCancelable: (state, action: PayloadAction<boolean>) => { setIsCancelable: (state, action: PayloadAction<boolean>) => {
state.isCancelable = action.payload; state.isCancelable = action.payload;
}, },
modelChangeRequested: (state) => {
state.statusTranslationKey = 'common.statusLoadingModel';
state.isCancelable = false;
state.isProcessing = true;
state.currentStatusHasSteps = false;
},
modelConvertRequested: (state) => {
state.statusTranslationKey = 'common.statusConvertingModel';
state.isCancelable = false;
state.isProcessing = true;
state.currentStatusHasSteps = false;
},
modelMergingRequested: (state) => {
state.statusTranslationKey = 'common.statusMergingModels';
state.isCancelable = false;
state.isProcessing = true;
state.currentStatusHasSteps = false;
},
setEnableImageDebugging: (state, action: PayloadAction<boolean>) => { setEnableImageDebugging: (state, action: PayloadAction<boolean>) => {
state.enableImageDebugging = action.payload; state.enableImageDebugging = action.payload;
}, },
@ -219,14 +161,6 @@ export const systemSlice = createSlice({
clearToastQueue: (state) => { clearToastQueue: (state) => {
state.toastQueue = []; state.toastQueue = [];
}, },
setProcessingIndeterminateTask: (
state,
action: PayloadAction<TFuncKey>
) => {
state.isProcessing = true;
state.statusTranslationKey = action.payload;
state.currentStatusHasSteps = false;
},
setSearchFolder: (state, action: PayloadAction<string | null>) => { setSearchFolder: (state, action: PayloadAction<string | null>) => {
state.searchFolder = action.payload; state.searchFolder = action.payload;
}, },
@ -485,21 +419,13 @@ export const systemSlice = createSlice({
export const { export const {
setIsProcessing, setIsProcessing,
setIsConnected,
setShouldConfirmOnDelete, setShouldConfirmOnDelete,
setCurrentStatus, setCurrentStatus,
setShouldDisplayGuides, setShouldDisplayGuides,
processingCanceled,
errorOccurred,
setIsCancelable, setIsCancelable,
modelChangeRequested,
modelConvertRequested,
modelMergingRequested,
setEnableImageDebugging, setEnableImageDebugging,
generationRequested,
addToast, addToast,
clearToastQueue, clearToastQueue,
setProcessingIndeterminateTask,
setSearchFolder, setSearchFolder,
setFoundModels, setFoundModels,
setOpenModel, setOpenModel,

View File

@ -21,11 +21,7 @@ import UnifiedCanvasParameters from './tabs/UnifiedCanvas/UnifiedCanvasParameter
const selector = createSelector( const selector = createSelector(
[uiSelector, activeTabNameSelector, lightboxSelector], [uiSelector, activeTabNameSelector, lightboxSelector],
(ui, activeTabName, lightbox) => { (ui, activeTabName, lightbox) => {
const { const { shouldPinParametersPanel, shouldShowParametersPanel } = ui;
shouldPinParametersPanel,
shouldShowParametersPanel,
shouldShowImageParameters,
} = ui;
const { isLightboxOpen } = lightbox; const { isLightboxOpen } = lightbox;
@ -33,7 +29,6 @@ const selector = createSelector(
activeTabName, activeTabName,
shouldPinParametersPanel, shouldPinParametersPanel,
shouldShowParametersPanel, shouldShowParametersPanel,
shouldShowImageParameters,
}; };
}, },
defaultSelectorOptions defaultSelectorOptions

View File

@ -3,11 +3,4 @@ import { UIState } from './uiTypes';
/** /**
* UI slice persist denylist * UI slice persist denylist
*/ */
const itemsToDenylist: (keyof UIState)[] = ['floatingProgressImageRect']; export const uiPersistDenylist: (keyof UIState)[] = [];
export const uiPersistDenylist: (keyof UIState)[] = [
'floatingProgressImageRect',
];
export const uiDenylist = itemsToDenylist.map(
(denylistItem) => `ui.${denylistItem}`
);

View File

@ -1,16 +1,14 @@
import type { PayloadAction } from '@reduxjs/toolkit'; import type { PayloadAction } from '@reduxjs/toolkit';
import { createSlice } from '@reduxjs/toolkit'; import { createSlice } from '@reduxjs/toolkit';
import { setActiveTabReducer } from './extraReducers'; import { setActiveTabReducer } from './extraReducers';
import { InvokeTabName, tabMap } from './tabMap'; import { InvokeTabName } from './tabMap';
import { AddNewModelType, Coordinates, Rect, UIState } from './uiTypes'; import { AddNewModelType, UIState } from './uiTypes';
import { initialImageSelected } from 'features/parameters/store/actions';
import { initialImageChanged } from 'features/parameters/store/generationSlice'; import { initialImageChanged } from 'features/parameters/store/generationSlice';
import { SCHEDULERS } from 'app/constants'; import { SCHEDULERS } from 'app/constants';
export const initialUIState: UIState = { export const initialUIState: UIState = {
activeTab: 0, activeTab: 0,
currentTheme: 'dark', currentTheme: 'dark',
parametersPanelScrollPosition: 0,
shouldPinParametersPanel: true, shouldPinParametersPanel: true,
shouldShowParametersPanel: true, shouldShowParametersPanel: true,
shouldShowImageDetails: false, shouldShowImageDetails: false,
@ -21,13 +19,7 @@ export const initialUIState: UIState = {
shouldPinGallery: true, shouldPinGallery: true,
shouldShowGallery: true, shouldShowGallery: true,
shouldHidePreview: false, shouldHidePreview: false,
textTabAccordionState: [],
imageTabAccordionState: [],
canvasTabAccordionState: [],
floatingProgressImageRect: { x: 0, y: 0, width: 0, height: 0 },
shouldShowProgressImages: false,
shouldShowProgressInViewer: false, shouldShowProgressInViewer: false,
shouldShowImageParameters: false,
schedulers: SCHEDULERS, schedulers: SCHEDULERS,
}; };
@ -41,12 +33,6 @@ export const uiSlice = createSlice({
setCurrentTheme: (state, action: PayloadAction<string>) => { setCurrentTheme: (state, action: PayloadAction<string>) => {
state.currentTheme = action.payload; state.currentTheme = action.payload;
}, },
setParametersPanelScrollPosition: (
state,
action: PayloadAction<number>
) => {
state.parametersPanelScrollPosition = action.payload;
},
setShouldPinParametersPanel: (state, action: PayloadAction<boolean>) => { setShouldPinParametersPanel: (state, action: PayloadAction<boolean>) => {
state.shouldPinParametersPanel = action.payload; state.shouldPinParametersPanel = action.payload;
state.shouldShowParametersPanel = true; state.shouldShowParametersPanel = true;
@ -75,9 +61,6 @@ export const uiSlice = createSlice({
setAddNewModelUIOption: (state, action: PayloadAction<AddNewModelType>) => { setAddNewModelUIOption: (state, action: PayloadAction<AddNewModelType>) => {
state.addNewModelUIOption = action.payload; state.addNewModelUIOption = action.payload;
}, },
setShouldPinGallery: (state, action: PayloadAction<boolean>) => {
state.shouldPinGallery = action.payload;
},
setShouldShowGallery: (state, action: PayloadAction<boolean>) => { setShouldShowGallery: (state, action: PayloadAction<boolean>) => {
state.shouldShowGallery = action.payload; state.shouldShowGallery = action.payload;
}, },
@ -108,46 +91,9 @@ export const uiSlice = createSlice({
state.shouldShowParametersPanel = true; state.shouldShowParametersPanel = true;
} }
}, },
openAccordionItemsChanged: (state, action: PayloadAction<number[]>) => {
if (tabMap[state.activeTab] === 'txt2img') {
state.textTabAccordionState = action.payload;
}
if (tabMap[state.activeTab] === 'img2img') {
state.imageTabAccordionState = action.payload;
}
if (tabMap[state.activeTab] === 'unifiedCanvas') {
state.canvasTabAccordionState = action.payload;
}
},
floatingProgressImageMoved: (state, action: PayloadAction<Coordinates>) => {
state.floatingProgressImageRect = {
...state.floatingProgressImageRect,
...action.payload,
};
},
floatingProgressImageResized: (
state,
action: PayloadAction<Partial<Rect>>
) => {
state.floatingProgressImageRect = {
...state.floatingProgressImageRect,
...action.payload,
};
},
setShouldShowProgressImages: (state, action: PayloadAction<boolean>) => {
state.shouldShowProgressImages = action.payload;
},
setShouldShowProgressInViewer: (state, action: PayloadAction<boolean>) => { setShouldShowProgressInViewer: (state, action: PayloadAction<boolean>) => {
state.shouldShowProgressInViewer = action.payload; state.shouldShowProgressInViewer = action.payload;
}, },
shouldShowImageParametersChanged: (
state,
action: PayloadAction<boolean>
) => {
state.shouldShowImageParameters = action.payload;
},
setSchedulers: (state, action: PayloadAction<string[]>) => { setSchedulers: (state, action: PayloadAction<string[]>) => {
state.schedulers = []; state.schedulers = [];
state.schedulers = action.payload; state.schedulers = action.payload;
@ -163,7 +109,6 @@ export const uiSlice = createSlice({
export const { export const {
setActiveTab, setActiveTab,
setCurrentTheme, setCurrentTheme,
setParametersPanelScrollPosition,
setShouldPinParametersPanel, setShouldPinParametersPanel,
setShouldShowParametersPanel, setShouldShowParametersPanel,
setShouldShowImageDetails, setShouldShowImageDetails,
@ -172,19 +117,13 @@ export const {
setShouldUseSliders, setShouldUseSliders,
setAddNewModelUIOption, setAddNewModelUIOption,
setShouldHidePreview, setShouldHidePreview,
setShouldPinGallery,
setShouldShowGallery, setShouldShowGallery,
togglePanels, togglePanels,
togglePinGalleryPanel, togglePinGalleryPanel,
togglePinParametersPanel, togglePinParametersPanel,
toggleParametersPanel, toggleParametersPanel,
toggleGalleryPanel, toggleGalleryPanel,
openAccordionItemsChanged,
floatingProgressImageMoved,
floatingProgressImageResized,
setShouldShowProgressImages,
setShouldShowProgressInViewer, setShouldShowProgressInViewer,
shouldShowImageParametersChanged,
setSchedulers, setSchedulers,
} = uiSlice.actions; } = uiSlice.actions;

View File

@ -15,7 +15,6 @@ export type Rect = Coordinates & Dimensions;
export interface UIState { export interface UIState {
activeTab: number; activeTab: number;
currentTheme: string; currentTheme: string;
parametersPanelScrollPosition: number;
shouldPinParametersPanel: boolean; shouldPinParametersPanel: boolean;
shouldShowParametersPanel: boolean; shouldShowParametersPanel: boolean;
shouldShowImageDetails: boolean; shouldShowImageDetails: boolean;
@ -26,12 +25,6 @@ export interface UIState {
shouldHidePreview: boolean; shouldHidePreview: boolean;
shouldPinGallery: boolean; shouldPinGallery: boolean;
shouldShowGallery: boolean; shouldShowGallery: boolean;
textTabAccordionState: number[];
imageTabAccordionState: number[];
canvasTabAccordionState: number[];
floatingProgressImageRect: Rect;
shouldShowProgressImages: boolean;
shouldShowProgressInViewer: boolean; shouldShowProgressInViewer: boolean;
shouldShowImageParameters: boolean;
schedulers: string[]; schedulers: string[];
} }

View File

@ -3,6 +3,8 @@
/* eslint-disable */ /* eslint-disable */
/** /**
* DO NOT DELETE EVEN THOUGH IT IS NOT USED!
*
* Custom `request.ts` file for OpenAPI code generator. * Custom `request.ts` file for OpenAPI code generator.
* *
* Patches the request logic in such a way that we can extract headers from requests. * Patches the request logic in such a way that we can extract headers from requests.

View File

@ -65,6 +65,7 @@ export type { PaginatedResults_ImageResponse_ } from './models/PaginatedResults_
export type { ParamIntInvocation } from './models/ParamIntInvocation'; export type { ParamIntInvocation } from './models/ParamIntInvocation';
export type { PasteImageInvocation } from './models/PasteImageInvocation'; export type { PasteImageInvocation } from './models/PasteImageInvocation';
export type { PromptOutput } from './models/PromptOutput'; export type { PromptOutput } from './models/PromptOutput';
export type { RandomIntInvocation } from './models/RandomIntInvocation';
export type { RandomRangeInvocation } from './models/RandomRangeInvocation'; export type { RandomRangeInvocation } from './models/RandomRangeInvocation';
export type { RangeInvocation } from './models/RangeInvocation'; export type { RangeInvocation } from './models/RangeInvocation';
export type { ResizeLatentsInvocation } from './models/ResizeLatentsInvocation'; export type { ResizeLatentsInvocation } from './models/ResizeLatentsInvocation';
@ -137,6 +138,7 @@ export { $PaginatedResults_ImageResponse_ } from './schemas/$PaginatedResults_Im
export { $ParamIntInvocation } from './schemas/$ParamIntInvocation'; export { $ParamIntInvocation } from './schemas/$ParamIntInvocation';
export { $PasteImageInvocation } from './schemas/$PasteImageInvocation'; export { $PasteImageInvocation } from './schemas/$PasteImageInvocation';
export { $PromptOutput } from './schemas/$PromptOutput'; export { $PromptOutput } from './schemas/$PromptOutput';
export { $RandomIntInvocation } from './schemas/$RandomIntInvocation';
export { $RandomRangeInvocation } from './schemas/$RandomRangeInvocation'; export { $RandomRangeInvocation } from './schemas/$RandomRangeInvocation';
export { $RangeInvocation } from './schemas/$RangeInvocation'; export { $RangeInvocation } from './schemas/$RangeInvocation';
export { $ResizeLatentsInvocation } from './schemas/$ResizeLatentsInvocation'; export { $ResizeLatentsInvocation } from './schemas/$ResizeLatentsInvocation';

View File

@ -28,6 +28,7 @@ import type { MultiplyInvocation } from './MultiplyInvocation';
import type { NoiseInvocation } from './NoiseInvocation'; import type { NoiseInvocation } from './NoiseInvocation';
import type { ParamIntInvocation } from './ParamIntInvocation'; import type { ParamIntInvocation } from './ParamIntInvocation';
import type { PasteImageInvocation } from './PasteImageInvocation'; import type { PasteImageInvocation } from './PasteImageInvocation';
import type { RandomIntInvocation } from './RandomIntInvocation';
import type { RandomRangeInvocation } from './RandomRangeInvocation'; import type { RandomRangeInvocation } from './RandomRangeInvocation';
import type { RangeInvocation } from './RangeInvocation'; import type { RangeInvocation } from './RangeInvocation';
import type { ResizeLatentsInvocation } from './ResizeLatentsInvocation'; import type { ResizeLatentsInvocation } from './ResizeLatentsInvocation';
@ -47,7 +48,7 @@ export type Graph = {
/** /**
* The nodes in this graph * The nodes in this graph
*/ */
nodes?: Record<string, (LoadImageInvocation | ShowImageInvocation | CropImageInvocation | PasteImageInvocation | MaskFromAlphaInvocation | BlurInvocation | LerpInvocation | InverseLerpInvocation | CompelInvocation | NoiseInvocation | TextToLatentsInvocation | LatentsToImageInvocation | ResizeLatentsInvocation | ScaleLatentsInvocation | ImageToLatentsInvocation | AddInvocation | SubtractInvocation | MultiplyInvocation | DivideInvocation | ParamIntInvocation | CvInpaintInvocation | RangeInvocation | RandomRangeInvocation | UpscaleInvocation | RestoreFaceInvocation | TextToImageInvocation | InfillColorInvocation | InfillTileInvocation | InfillPatchMatchInvocation | GraphInvocation | IterateInvocation | CollectInvocation | LatentsToLatentsInvocation | ImageToImageInvocation | InpaintInvocation)>; nodes?: Record<string, (LoadImageInvocation | ShowImageInvocation | CropImageInvocation | PasteImageInvocation | MaskFromAlphaInvocation | BlurInvocation | LerpInvocation | InverseLerpInvocation | CompelInvocation | NoiseInvocation | TextToLatentsInvocation | LatentsToImageInvocation | ResizeLatentsInvocation | ScaleLatentsInvocation | ImageToLatentsInvocation | AddInvocation | SubtractInvocation | MultiplyInvocation | DivideInvocation | RandomIntInvocation | ParamIntInvocation | CvInpaintInvocation | RangeInvocation | RandomRangeInvocation | UpscaleInvocation | RestoreFaceInvocation | TextToImageInvocation | InfillColorInvocation | InfillTileInvocation | InfillPatchMatchInvocation | GraphInvocation | IterateInvocation | CollectInvocation | LatentsToLatentsInvocation | ImageToImageInvocation | InpaintInvocation)>;
/** /**
* The connections between nodes and their fields in this graph * The connections between nodes and their fields in this graph
*/ */

View File

@ -40,7 +40,7 @@ export type ImageToImageInvocation = {
/** /**
* The scheduler to use * The scheduler to use
*/ */
scheduler?: 'ddim' | 'ddpm' | 'deis' | 'lms' | 'pndm' | 'heun' | 'euler' | 'euler_k' | 'euler_a' | 'kdpm_2' | 'kdpm_2_a' | 'dpmpp_2s' | 'dpmpp_2m' | 'dpmpp_2m_k' | 'unipc'; scheduler?: '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' | 'unipc';
/** /**
* The model to use (currently ignored) * The model to use (currently ignored)
*/ */

View File

@ -41,7 +41,7 @@ export type InpaintInvocation = {
/** /**
* The scheduler to use * The scheduler to use
*/ */
scheduler?: 'ddim' | 'ddpm' | 'deis' | 'lms' | 'pndm' | 'heun' | 'euler' | 'euler_k' | 'euler_a' | 'kdpm_2' | 'kdpm_2_a' | 'dpmpp_2s' | 'dpmpp_2m' | 'dpmpp_2m_k' | 'unipc'; scheduler?: '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' | 'unipc';
/** /**
* The model to use (currently ignored) * The model to use (currently ignored)
*/ */

View File

@ -8,10 +8,18 @@ import type { LatentsField } from './LatentsField';
* Base class for invocations that output latents * Base class for invocations that output latents
*/ */
export type LatentsOutput = { export type LatentsOutput = {
type?: 'latent_output'; type?: 'latents_output';
/** /**
* The output latents * The output latents
*/ */
latents?: LatentsField; latents?: LatentsField;
/**
* The width of the latents in pixels
*/
width: number;
/**
* The height of the latents in pixels
*/
height: number;
}; };

View File

@ -37,7 +37,7 @@ export type LatentsToLatentsInvocation = {
/** /**
* The scheduler to use * The scheduler to use
*/ */
scheduler?: 'ddim' | 'ddpm' | 'deis' | 'lms' | 'pndm' | 'heun' | 'euler' | 'euler_k' | 'euler_a' | 'kdpm_2' | 'kdpm_2_a' | 'dpmpp_2s' | 'dpmpp_2m' | 'dpmpp_2m_k' | 'unipc'; scheduler?: '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' | 'unipc';
/** /**
* The model to use (currently ignored) * The model to use (currently ignored)
*/ */

View File

@ -13,5 +13,13 @@ export type NoiseOutput = {
* The output noise * The output noise
*/ */
noise?: LatentsField; noise?: LatentsField;
/**
* The width of the noise in pixels
*/
width: number;
/**
* The height of the noise in pixels
*/
height: number;
}; };

View File

@ -0,0 +1,15 @@
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
/**
* Outputs a single random integer.
*/
export type RandomIntInvocation = {
/**
* The id of this node. Must be unique among all nodes.
*/
id: string;
type?: 'rand_int';
};

View File

@ -38,7 +38,7 @@ export type TextToImageInvocation = {
/** /**
* The scheduler to use * The scheduler to use
*/ */
scheduler?: 'ddim' | 'ddpm' | 'deis' | 'lms' | 'pndm' | 'heun' | 'euler' | 'euler_k' | 'euler_a' | 'kdpm_2' | 'kdpm_2_a' | 'dpmpp_2s' | 'dpmpp_2m' | 'dpmpp_2m_k' | 'unipc'; scheduler?: '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' | 'unipc';
/** /**
* The model to use (currently ignored) * The model to use (currently ignored)
*/ */

View File

@ -37,7 +37,7 @@ export type TextToLatentsInvocation = {
/** /**
* The scheduler to use * The scheduler to use
*/ */
scheduler?: 'ddim' | 'ddpm' | 'deis' | 'lms' | 'pndm' | 'heun' | 'euler' | 'euler_k' | 'euler_a' | 'kdpm_2' | 'kdpm_2_a' | 'dpmpp_2s' | 'dpmpp_2m' | 'dpmpp_2m_k' | 'unipc'; scheduler?: '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' | 'unipc';
/** /**
* The model to use (currently ignored) * The model to use (currently ignored)
*/ */

View File

@ -49,6 +49,8 @@ export const $Graph = {
type: 'MultiplyInvocation', type: 'MultiplyInvocation',
}, { }, {
type: 'DivideInvocation', type: 'DivideInvocation',
}, {
type: 'RandomIntInvocation',
}, { }, {
type: 'ParamIntInvocation', type: 'ParamIntInvocation',
}, { }, {

View File

@ -14,5 +14,15 @@ export const $LatentsOutput = {
type: 'LatentsField', type: 'LatentsField',
}], }],
}, },
width: {
type: 'number',
description: `The width of the latents in pixels`,
isRequired: true,
},
height: {
type: 'number',
description: `The height of the latents in pixels`,
isRequired: true,
},
}, },
} as const; } as const;

View File

@ -14,5 +14,15 @@ export const $NoiseOutput = {
type: 'LatentsField', type: 'LatentsField',
}], }],
}, },
width: {
type: 'number',
description: `The width of the noise in pixels`,
isRequired: true,
},
height: {
type: 'number',
description: `The height of the noise in pixels`,
isRequired: true,
},
}, },
} as const; } as const;

View File

@ -0,0 +1,16 @@
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export const $RandomIntInvocation = {
description: `Outputs a single random integer.`,
properties: {
id: {
type: 'string',
description: `The id of this node. Must be unique among all nodes.`,
isRequired: true,
},
type: {
type: 'Enum',
},
},
} as const;

View File

@ -30,6 +30,7 @@ import type { NoiseInvocation } from '../models/NoiseInvocation';
import type { PaginatedResults_GraphExecutionState_ } from '../models/PaginatedResults_GraphExecutionState_'; import type { PaginatedResults_GraphExecutionState_ } from '../models/PaginatedResults_GraphExecutionState_';
import type { ParamIntInvocation } from '../models/ParamIntInvocation'; import type { ParamIntInvocation } from '../models/ParamIntInvocation';
import type { PasteImageInvocation } from '../models/PasteImageInvocation'; import type { PasteImageInvocation } from '../models/PasteImageInvocation';
import type { RandomIntInvocation } from '../models/RandomIntInvocation';
import type { RandomRangeInvocation } from '../models/RandomRangeInvocation'; import type { RandomRangeInvocation } from '../models/RandomRangeInvocation';
import type { RangeInvocation } from '../models/RangeInvocation'; import type { RangeInvocation } from '../models/RangeInvocation';
import type { ResizeLatentsInvocation } from '../models/ResizeLatentsInvocation'; import type { ResizeLatentsInvocation } from '../models/ResizeLatentsInvocation';
@ -149,7 +150,7 @@ export class SessionsService {
* The id of the session * The id of the session
*/ */
sessionId: string, sessionId: string,
requestBody: (LoadImageInvocation | ShowImageInvocation | CropImageInvocation | PasteImageInvocation | MaskFromAlphaInvocation | BlurInvocation | LerpInvocation | InverseLerpInvocation | CompelInvocation | NoiseInvocation | TextToLatentsInvocation | LatentsToImageInvocation | ResizeLatentsInvocation | ScaleLatentsInvocation | ImageToLatentsInvocation | AddInvocation | SubtractInvocation | MultiplyInvocation | DivideInvocation | ParamIntInvocation | CvInpaintInvocation | RangeInvocation | RandomRangeInvocation | UpscaleInvocation | RestoreFaceInvocation | TextToImageInvocation | InfillColorInvocation | InfillTileInvocation | InfillPatchMatchInvocation | GraphInvocation | IterateInvocation | CollectInvocation | LatentsToLatentsInvocation | ImageToImageInvocation | InpaintInvocation), requestBody: (LoadImageInvocation | ShowImageInvocation | CropImageInvocation | PasteImageInvocation | MaskFromAlphaInvocation | BlurInvocation | LerpInvocation | InverseLerpInvocation | CompelInvocation | NoiseInvocation | TextToLatentsInvocation | LatentsToImageInvocation | ResizeLatentsInvocation | ScaleLatentsInvocation | ImageToLatentsInvocation | AddInvocation | SubtractInvocation | MultiplyInvocation | DivideInvocation | RandomIntInvocation | ParamIntInvocation | CvInpaintInvocation | RangeInvocation | RandomRangeInvocation | UpscaleInvocation | RestoreFaceInvocation | TextToImageInvocation | InfillColorInvocation | InfillTileInvocation | InfillPatchMatchInvocation | GraphInvocation | IterateInvocation | CollectInvocation | LatentsToLatentsInvocation | ImageToImageInvocation | InpaintInvocation),
}): CancelablePromise<string> { }): CancelablePromise<string> {
return __request(OpenAPI, { return __request(OpenAPI, {
method: 'POST', method: 'POST',
@ -186,7 +187,7 @@ export class SessionsService {
* The path to the node in the graph * The path to the node in the graph
*/ */
nodePath: string, nodePath: string,
requestBody: (LoadImageInvocation | ShowImageInvocation | CropImageInvocation | PasteImageInvocation | MaskFromAlphaInvocation | BlurInvocation | LerpInvocation | InverseLerpInvocation | CompelInvocation | NoiseInvocation | TextToLatentsInvocation | LatentsToImageInvocation | ResizeLatentsInvocation | ScaleLatentsInvocation | ImageToLatentsInvocation | AddInvocation | SubtractInvocation | MultiplyInvocation | DivideInvocation | ParamIntInvocation | CvInpaintInvocation | RangeInvocation | RandomRangeInvocation | UpscaleInvocation | RestoreFaceInvocation | TextToImageInvocation | InfillColorInvocation | InfillTileInvocation | InfillPatchMatchInvocation | GraphInvocation | IterateInvocation | CollectInvocation | LatentsToLatentsInvocation | ImageToImageInvocation | InpaintInvocation), requestBody: (LoadImageInvocation | ShowImageInvocation | CropImageInvocation | PasteImageInvocation | MaskFromAlphaInvocation | BlurInvocation | LerpInvocation | InverseLerpInvocation | CompelInvocation | NoiseInvocation | TextToLatentsInvocation | LatentsToImageInvocation | ResizeLatentsInvocation | ScaleLatentsInvocation | ImageToLatentsInvocation | AddInvocation | SubtractInvocation | MultiplyInvocation | DivideInvocation | RandomIntInvocation | ParamIntInvocation | CvInpaintInvocation | RangeInvocation | RandomRangeInvocation | UpscaleInvocation | RestoreFaceInvocation | TextToImageInvocation | InfillColorInvocation | InfillTileInvocation | InfillPatchMatchInvocation | GraphInvocation | IterateInvocation | CollectInvocation | LatentsToLatentsInvocation | ImageToImageInvocation | InpaintInvocation),
}): CancelablePromise<GraphExecutionState> { }): CancelablePromise<GraphExecutionState> {
return __request(OpenAPI, { return __request(OpenAPI, {
method: 'PUT', method: 'PUT',