feat(ui): wip canvas migration, createListenerMiddleware

This commit is contained in:
psychedelicious
2023-05-03 19:27:29 +10:00
parent a75148cb16
commit 6ab5d28cf3
29 changed files with 352 additions and 175 deletions

View File

@@ -5,9 +5,9 @@ import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import SelectImagePlaceholder from 'common/components/SelectImagePlaceholder';
import { useGetUrl } from 'common/util/getUrl';
import useGetImageByNameAndType from 'features/gallery/hooks/useGetImageByName';
import {
import generationSlice, {
clearInitialImage,
initialImageSelected,
initialImageChanged,
} from 'features/parameters/store/generationSlice';
import { addToast } from 'features/system/store/systemSlice';
import { isEqual } from 'lodash-es';
@@ -15,23 +15,26 @@ import { DragEvent, useCallback, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { ImageType } from 'services/api';
import ImageToImageOverlay from 'common/components/ImageToImageOverlay';
import { initialImageSelector } from 'features/parameters/store/generationSelectors';
import {
generationSelector,
initialImageSelector,
} from 'features/parameters/store/generationSelectors';
import { initialImageSelected } from 'features/parameters/store/actions';
const selector = createSelector(
[initialImageSelector],
(initialImage) => {
[generationSelector],
(generation) => {
const { initialImage, isImageToImageEnabled } = generation;
return {
initialImage,
isImageToImageEnabled,
};
},
{ memoizeOptions: { resultEqualityCheck: isEqual } }
);
const InitialImagePreview = () => {
const isImageToImageEnabled = useAppSelector(
(state: RootState) => state.generation.isImageToImageEnabled
);
const { initialImage } = useAppSelector(selector);
const { initialImage, isImageToImageEnabled } = useAppSelector(selector);
const { getUrl } = useGetUrl();
const dispatch = useAppDispatch();
const { t } = useTranslation();
@@ -55,22 +58,13 @@ const InitialImagePreview = () => {
const handleDrop = useCallback(
(e: DragEvent<HTMLDivElement>) => {
setIsLoaded(false);
const name = e.dataTransfer.getData('invokeai/imageName');
const type = e.dataTransfer.getData('invokeai/imageType') as ImageType;
if (!name || !type) {
return;
}
const image = getImageByNameAndType(name, type);
if (!image) {
return;
}
dispatch(initialImageSelected({ name, type }));
},
[getImageByNameAndType, dispatch]
[dispatch]
);
return (

View File

@@ -4,9 +4,11 @@ import { isFinite, isString } from 'lodash-es';
import { useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import useSetBothPrompts from './usePrompt';
import { initialImageSelected, setSeed } from '../store/generationSlice';
import { initialImageChanged, setSeed } from '../store/generationSlice';
import { isImage, isImageField } from 'services/types/guards';
import { NUMPY_RAND_MAX } from 'app/constants';
import { initialImageSelected } from '../store/actions';
import { Image } from 'app/types/invokeai';
export const useParameters = () => {
const dispatch = useAppDispatch();
@@ -86,7 +88,7 @@ export const useParameters = () => {
}
dispatch(
initialImageSelected({ name: image.image_name, type: image.image_type })
initialImageChanged({ name: image.image_name, type: image.image_type })
);
toast({
title: t('toast.initialImageSet'),
@@ -102,27 +104,10 @@ export const useParameters = () => {
* Sets image as initial image with toast
*/
const sendToImageToImage = useCallback(
(image: unknown) => {
if (!isImage(image)) {
toast({
title: t('toast.imageNotLoaded'),
description: t('toast.imageNotLoadedDesc'),
status: 'warning',
duration: 2500,
isClosable: true,
});
return;
}
(image: Image) => {
dispatch(initialImageSelected({ name: image.name, type: image.type }));
toast({
title: t('toast.sentToImageToImage'),
status: 'info',
duration: 2500,
isClosable: true,
});
},
[t, toast, dispatch]
[dispatch]
);
return { recallPrompt, recallSeed, recallInitialImage, sendToImageToImage };

View File

@@ -0,0 +1,12 @@
import { createAction } from '@reduxjs/toolkit';
import { Image } from 'app/types/invokeai';
import { ImageType } from 'services/api';
export type SelectedImage = {
name: string;
type: ImageType;
};
export const initialImageSelected = createAction<
Image | SelectedImage | undefined
>('generation/initialImageSelected');

View File

@@ -7,17 +7,12 @@ import { seedWeightsToString } from 'common/util/seedWeightPairs';
import { clamp } from 'lodash-es';
import { ImageField, ImageType } from 'services/api';
export type SelectedImage = {
name: string;
type: ImageType;
};
export interface GenerationState {
cfgScale: number;
height: number;
img2imgStrength: number;
infillMethod: string;
initialImage?: SelectedImage; // can be an Image or url
initialImage?: InvokeAI.Image; // can be an Image or url
iterations: number;
maskPath: string;
perlin: number;
@@ -351,7 +346,7 @@ export const generationSlice = createSlice({
setVerticalSymmetrySteps: (state, action: PayloadAction<number>) => {
state.verticalSymmetrySteps = action.payload;
},
initialImageSelected: (state, action: PayloadAction<SelectedImage>) => {
initialImageChanged: (state, action: PayloadAction<InvokeAI.Image>) => {
state.initialImage = action.payload;
state.isImageToImageEnabled = true;
},
@@ -399,7 +394,7 @@ export const {
setShouldUseSymmetry,
setHorizontalSymmetrySteps,
setVerticalSymmetrySteps,
initialImageSelected,
initialImageChanged,
isImageToImageEnabledChanged,
} = generationSlice.actions;