move mdoal state into nanostore

This commit is contained in:
Mary Hipp 2024-08-12 12:46:02 -04:00
parent 096f001634
commit 6c927a9fd4
8 changed files with 82 additions and 104 deletions

View File

@ -28,7 +28,6 @@ import { generationPersistConfig, generationSlice } from 'features/parameters/st
import { upscalePersistConfig, upscaleSlice } from 'features/parameters/store/upscaleSlice';
import { queueSlice } from 'features/queue/store/queueSlice';
import { sdxlPersistConfig, sdxlSlice } from 'features/sdxl/store/sdxlSlice';
import { stylePresetModalSlice } from 'features/stylePresets/store/stylePresetModalSlice';
import { stylePresetPersistConfig, stylePresetSlice } from 'features/stylePresets/store/stylePresetSlice';
import { configSlice } from 'features/system/store/configSlice';
import { systemPersistConfig, systemSlice } from 'features/system/store/systemSlice';
@ -71,7 +70,6 @@ const allReducers = {
[workflowSettingsSlice.name]: workflowSettingsSlice.reducer,
[api.reducerPath]: api.reducer,
[upscaleSlice.name]: upscaleSlice.reducer,
[stylePresetModalSlice.name]: stylePresetModalSlice.reducer,
[stylePresetSlice.name]: stylePresetSlice.reducer,
};

View File

@ -1,7 +1,7 @@
import { skipToken } from '@reduxjs/toolkit/query';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { useAppSelector } from 'app/store/storeHooks';
import { handlers, parseAndRecallAllMetadata, parseAndRecallPrompts } from 'features/metadata/util/handlers';
import { isModalOpenChanged, prefilledFormDataChanged } from 'features/stylePresets/store/stylePresetModalSlice';
import { $stylePresetModalState } from 'features/stylePresets/store/stylePresetModal';
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
import { useCallback, useEffect, useState } from 'react';
import { useGetImageDTOQuery } from 'services/api/endpoints/images';
@ -13,7 +13,6 @@ export const useImageActions = (image_name?: string) => {
const [hasMetadata, setHasMetadata] = useState(false);
const [hasSeed, setHasSeed] = useState(false);
const [hasPrompts, setHasPrompts] = useState(false);
const dispatch = useAppDispatch();
const { data: imageDTO } = useGetImageDTOQuery(image_name ?? skipToken);
useEffect(() => {
@ -71,17 +70,18 @@ export const useImageActions = (image_name?: string) => {
const positivePrompt = await handlers.positivePrompt.parse(metadata);
const negativePrompt = await handlers.negativePrompt.parse(metadata);
dispatch(
prefilledFormDataChanged({
$stylePresetModalState.set({
prefilledFormData: {
name: '',
positivePrompt,
negativePrompt,
imageUrl: imageDTO.image_url,
})
);
dispatch(isModalOpenChanged(true));
},
updatingStylePresetId: null,
isModalOpen: true,
});
}
}, [image_name, metadata, dispatch, imageDTO]);
}, [image_name, metadata, imageDTO]);
return {
recallAll,

View File

@ -1,10 +1,5 @@
import { Button, Flex, FormControl, FormLabel, Input, Text } from '@invoke-ai/ui-library';
import { useAppDispatch } from 'app/store/storeHooks';
import {
isModalOpenChanged,
prefilledFormDataChanged,
updatingStylePresetIdChanged,
} from 'features/stylePresets/store/stylePresetModalSlice';
import { $stylePresetModalState } from 'features/stylePresets/store/stylePresetModal';
import { toast } from 'features/toast/toast';
import { useCallback } from 'react';
import type { SubmitHandler } from 'react-hook-form';
@ -31,7 +26,6 @@ export const StylePresetForm = ({
}) => {
const [createStylePreset] = useCreateStylePresetMutation();
const [updateStylePreset] = useUpdateStylePresetMutation();
const dispatch = useAppDispatch();
const { t } = useTranslation();
const { handleSubmit, control, register, formState } = useForm<StylePresetFormData>({
@ -69,11 +63,13 @@ export const StylePresetForm = ({
});
}
dispatch(prefilledFormDataChanged(null));
dispatch(updatingStylePresetIdChanged(null));
dispatch(isModalOpenChanged(false));
$stylePresetModalState.set({
prefilledFormData: null,
updatingStylePresetId: null,
isModalOpen: false,
});
},
[dispatch, updatingStylePresetId, updateStylePreset, createStylePreset]
[updatingStylePresetId, updateStylePreset, createStylePreset]
);
return (

View File

@ -1,11 +1,7 @@
import { Badge, ConfirmationAlertDialog, Flex, IconButton, Text, useDisclosure } from '@invoke-ai/ui-library';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { $isMenuOpen } from 'features/stylePresets/store/isMenuOpen';
import {
isModalOpenChanged,
prefilledFormDataChanged,
updatingStylePresetIdChanged,
} from 'features/stylePresets/store/stylePresetModalSlice';
import { $stylePresetModalState } from 'features/stylePresets/store/stylePresetModal';
import { activeStylePresetIdChanged } from 'features/stylePresets/store/stylePresetSlice';
import { toast } from 'features/toast/toast';
import type { MouseEvent } from 'react';
@ -30,19 +26,18 @@ export const StylePresetListItem = ({ preset }: { preset: StylePresetRecordWithI
const { name, preset_data } = preset;
const { positive_prompt, negative_prompt } = preset_data;
dispatch(
prefilledFormDataChanged({
$stylePresetModalState.set({
prefilledFormData: {
name,
positivePrompt: positive_prompt || '',
negativePrompt: negative_prompt || '',
imageUrl: preset.image,
})
);
dispatch(updatingStylePresetIdChanged(preset.id));
dispatch(isModalOpenChanged(true));
},
updatingStylePresetId: preset.id,
isModalOpen: true,
});
},
[dispatch, preset]
[preset]
);
const handleClickApply = useCallback(async () => {
@ -64,19 +59,18 @@ export const StylePresetListItem = ({ preset }: { preset: StylePresetRecordWithI
const { name, preset_data } = preset;
const { positive_prompt, negative_prompt } = preset_data;
dispatch(
prefilledFormDataChanged({
$stylePresetModalState.set({
prefilledFormData: {
name: `${name} (${t('common.copy')})`,
positivePrompt: positive_prompt || '',
negativePrompt: negative_prompt || '',
imageUrl: preset.image,
})
);
dispatch(updatingStylePresetIdChanged(null));
dispatch(isModalOpenChanged(true));
},
updatingStylePresetId: null,
isModalOpen: true,
});
},
[dispatch, preset, t]
[preset, t]
);
const handleDeletePreset = useCallback(async () => {

View File

@ -1,11 +1,7 @@
import { Flex, IconButton, Text } from '@invoke-ai/ui-library';
import { EMPTY_ARRAY } from 'app/store/constants';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import {
isModalOpenChanged,
prefilledFormDataChanged,
updatingStylePresetIdChanged,
} from 'features/stylePresets/store/stylePresetModalSlice';
import { useAppSelector } from 'app/store/storeHooks';
import { $stylePresetModalState } from 'features/stylePresets/store/stylePresetModal';
import { useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { PiPlusBold } from 'react-icons/pi';
@ -40,14 +36,15 @@ export const StylePresetMenu = () => {
},
});
const dispatch = useAppDispatch();
const { t } = useTranslation();
const handleClickAddNew = useCallback(() => {
dispatch(prefilledFormDataChanged(null));
dispatch(updatingStylePresetIdChanged(null));
dispatch(isModalOpenChanged(true));
}, [dispatch]);
$stylePresetModalState.set({
prefilledFormData: null,
updatingStylePresetId: null,
isModalOpen: true,
});
}, []);
return (
<Flex flexDir="column" gap={2} padding={3} layerStyle="second" borderRadius="base">

View File

@ -8,13 +8,9 @@ import {
ModalOverlay,
Spinner,
} from '@invoke-ai/ui-library';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { useStore } from '@nanostores/react';
import { convertImageUrlToBlob } from 'common/util/convertImageUrlToBlob';
import {
isModalOpenChanged,
prefilledFormDataChanged,
updatingStylePresetIdChanged,
} from 'features/stylePresets/store/stylePresetModalSlice';
import { $stylePresetModalState } from 'features/stylePresets/store/stylePresetModal';
import type { PrefilledFormData } from 'features/stylePresets/store/types';
import { useCallback, useEffect, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
@ -24,21 +20,22 @@ import { StylePresetForm } from './StylePresetForm';
export const StylePresetModal = () => {
const [formData, setFormData] = useState<StylePresetFormData | null>(null);
const dispatch = useAppDispatch();
const { t } = useTranslation();
const isModalOpen = useAppSelector((s) => s.stylePresetModal.isModalOpen);
const updatingStylePresetId = useAppSelector((s) => s.stylePresetModal.updatingStylePresetId);
const prefilledFormData = useAppSelector((s) => s.stylePresetModal.prefilledFormData);
const stylePresetModalState = useStore($stylePresetModalState);
const modalTitle = useMemo(() => {
return updatingStylePresetId ? t('stylePresets.updatePromptTemplate') : t('stylePresets.createPromptTemplate');
}, [updatingStylePresetId, t]);
return stylePresetModalState.updatingStylePresetId
? t('stylePresets.updatePromptTemplate')
: t('stylePresets.createPromptTemplate');
}, [stylePresetModalState.updatingStylePresetId, t]);
const handleCloseModal = useCallback(() => {
dispatch(prefilledFormDataChanged(null));
dispatch(updatingStylePresetIdChanged(null));
dispatch(isModalOpenChanged(false));
}, [dispatch]);
$stylePresetModalState.set({
prefilledFormData: null,
updatingStylePresetId: null,
isModalOpen: false,
});
}, []);
useEffect(() => {
setFormData(null);
@ -62,18 +59,18 @@ export const StylePresetModal = () => {
});
}
};
convertImageToBlob(prefilledFormData);
}, [prefilledFormData]);
convertImageToBlob(stylePresetModalState.prefilledFormData);
}, [stylePresetModalState.prefilledFormData]);
return (
<Modal isOpen={isModalOpen} onClose={handleCloseModal} isCentered size="2xl">
<Modal isOpen={stylePresetModalState.isModalOpen} onClose={handleCloseModal} isCentered size="2xl">
<ModalOverlay />
<ModalContent>
<ModalHeader>{modalTitle}</ModalHeader>
<ModalCloseButton />
<ModalBody display="flex" flexDir="column" gap={4}>
{!prefilledFormData || formData ? (
<StylePresetForm updatingStylePresetId={updatingStylePresetId} formData={formData} />
{!stylePresetModalState.prefilledFormData || formData ? (
<StylePresetForm updatingStylePresetId={stylePresetModalState.updatingStylePresetId} formData={formData} />
) : (
<Spinner />
)}

View File

@ -0,0 +1,25 @@
import { atom } from 'nanostores';
const initialState: StylePresetModalState = {
isModalOpen: false,
updatingStylePresetId: null,
prefilledFormData: null,
};
/**
* Tracks the state for the style preset modal.
*/
export const $stylePresetModalState = atom<StylePresetModalState>(initialState);
export type StylePresetModalState = {
isModalOpen: boolean;
updatingStylePresetId: string | null;
prefilledFormData: PrefilledFormData | null;
};
export type PrefilledFormData = {
name: string;
positivePrompt: string;
negativePrompt: string;
imageUrl: string | null;
};

View File

@ -1,29 +0,0 @@
import type { PayloadAction } from '@reduxjs/toolkit';
import { createSlice } from '@reduxjs/toolkit';
import type { PrefilledFormData, StylePresetModalState } from './types';
const initialState: StylePresetModalState = {
isModalOpen: false,
updatingStylePresetId: null,
prefilledFormData: null,
};
export const stylePresetModalSlice = createSlice({
name: 'stylePresetModal',
initialState: initialState,
reducers: {
isModalOpenChanged: (state, action: PayloadAction<boolean>) => {
state.isModalOpen = action.payload;
},
updatingStylePresetIdChanged: (state, action: PayloadAction<string | null>) => {
state.updatingStylePresetId = action.payload;
},
prefilledFormDataChanged: (state, action: PayloadAction<PrefilledFormData | null>) => {
state.prefilledFormData = action.payload;
},
},
});
export const { isModalOpenChanged, updatingStylePresetIdChanged, prefilledFormDataChanged } =
stylePresetModalSlice.actions;