From d52a096607895fdd6e53102d830e198e3b3171db Mon Sep 17 00:00:00 2001 From: Mary Hipp Date: Thu, 24 Aug 2023 13:29:53 -0400 Subject: [PATCH 1/2] enable preselected image actions --- .../frontend/web/src/app/components/App.tsx | 18 ++++- .../web/src/app/components/InvokeAIUI.tsx | 11 ++- .../parameters/hooks/usePreselectedImage.ts | 81 +++++++++++++++++++ 3 files changed, 107 insertions(+), 3 deletions(-) create mode 100644 invokeai/frontend/web/src/features/parameters/hooks/usePreselectedImage.ts diff --git a/invokeai/frontend/web/src/app/components/App.tsx b/invokeai/frontend/web/src/app/components/App.tsx index c2cc4645b8..a4a0997443 100644 --- a/invokeai/frontend/web/src/app/components/App.tsx +++ b/invokeai/frontend/web/src/app/components/App.tsx @@ -12,24 +12,34 @@ import { languageSelector } from 'features/system/store/systemSelectors'; import InvokeTabs from 'features/ui/components/InvokeTabs'; import i18n from 'i18n'; import { size } from 'lodash-es'; -import { ReactNode, memo, useCallback, useEffect } from 'react'; +import { ReactNode, memo, useCallback, useEffect, useMemo } from 'react'; import { ErrorBoundary } from 'react-error-boundary'; import AppErrorBoundaryFallback from './AppErrorBoundaryFallback'; import GlobalHotkeys from './GlobalHotkeys'; import Toaster from './Toaster'; +import { usePreselectedImage } from '../../features/parameters/hooks/usePreselectedImage'; const DEFAULT_CONFIG = {}; interface Props { config?: PartialAppConfig; headerComponent?: ReactNode; + selectedImage?: { + imageName: string; + action: 'sendToImg2Img' | 'sendToCanvas' | 'useAllParameters'; + }; } -const App = ({ config = DEFAULT_CONFIG, headerComponent }: Props) => { +const App = ({ + config = DEFAULT_CONFIG, + headerComponent, + selectedImage, +}: Props) => { const language = useAppSelector(languageSelector); const logger = useLogger('system'); const dispatch = useAppDispatch(); + const { handlePreselectedImage } = usePreselectedImage(); const handleReset = useCallback(() => { localStorage.clear(); location.reload(); @@ -51,6 +61,10 @@ const App = ({ config = DEFAULT_CONFIG, headerComponent }: Props) => { dispatch(appStarted()); }, [dispatch]); + useEffect(() => { + handlePreselectedImage(selectedImage); + }, [handlePreselectedImage, selectedImage]); + return ( { useEffect(() => { // configure API client token @@ -81,7 +86,11 @@ const InvokeAIUI = ({ }> - + diff --git a/invokeai/frontend/web/src/features/parameters/hooks/usePreselectedImage.ts b/invokeai/frontend/web/src/features/parameters/hooks/usePreselectedImage.ts new file mode 100644 index 0000000000..fa310a66ad --- /dev/null +++ b/invokeai/frontend/web/src/features/parameters/hooks/usePreselectedImage.ts @@ -0,0 +1,81 @@ +import { skipToken } from '@reduxjs/toolkit/dist/query'; +import { useCallback, useMemo, useState } from 'react'; +import { + useGetImageDTOQuery, + useGetImageMetadataQuery, +} from '../../../services/api/endpoints/images'; +import { useAppDispatch } from '../../../app/store/storeHooks'; +import { setInitialCanvasImage } from '../../canvas/store/canvasSlice'; +import { setActiveTab } from '../../ui/store/uiSlice'; +import { useRecallParameters } from './useRecallParameters'; +import { initialImageSelected } from '../store/actions'; +import { useAppToaster } from '../../../app/components/Toaster'; +import { t } from 'i18next'; + +type SelectedImage = { + imageName: string; + action: 'sendToImg2Img' | 'sendToCanvas' | 'useAllParameters'; +}; + +export const usePreselectedImage = () => { + const dispatch = useAppDispatch(); + const [imageNameForDto, setImageNameForDto] = useState(); + const [imageNameForMetadata, setImageNameForMetadata] = useState< + string | undefined + >(); + const { recallAllParameters } = useRecallParameters(); + const toaster = useAppToaster(); + + const { currentData: selectedImageDto, isError } = useGetImageDTOQuery( + imageNameForDto ?? skipToken + ); + + const { currentData: selectedImageMetadata } = useGetImageMetadataQuery( + imageNameForMetadata ?? skipToken + ); + + const handlePreselectedImage = useCallback( + (selectedImage?: SelectedImage) => { + if (!selectedImage) { +return; +} + + if (selectedImage.action === 'sendToCanvas') { + setImageNameForDto(selectedImage?.imageName); + if (selectedImageDto) { + dispatch(setInitialCanvasImage(selectedImageDto)); + dispatch(setActiveTab('unifiedCanvas')); + toaster({ + title: t('toast.sentToUnifiedCanvas'), + status: 'info', + duration: 2500, + isClosable: true, + }); + } + } + + if (selectedImage.action === 'sendToImg2Img') { + setImageNameForDto(selectedImage?.imageName); + if (selectedImageDto) { + dispatch(initialImageSelected(selectedImageDto)); + } + } + + if (selectedImage.action === 'useAllParameters') { + setImageNameForMetadata(selectedImage?.imageName); + if (selectedImageMetadata) { + recallAllParameters(selectedImageMetadata.metadata); + } + } + }, + [ + dispatch, + selectedImageDto, + selectedImageMetadata, + recallAllParameters, + toaster, + ] + ); + + return { handlePreselectedImage }; +}; From e60af40c8d2af363ffdfbb0c62ad33bc47c266e7 Mon Sep 17 00:00:00 2001 From: blessedcoolant <54517381+blessedcoolant@users.noreply.github.com> Date: Tue, 29 Aug 2023 01:11:55 +1200 Subject: [PATCH 2/2] chore: lint fixes --- invokeai/frontend/web/src/app/components/App.tsx | 4 ++-- .../parameters/hooks/usePreselectedImage.ts | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/invokeai/frontend/web/src/app/components/App.tsx b/invokeai/frontend/web/src/app/components/App.tsx index a4a0997443..a70ed03fda 100644 --- a/invokeai/frontend/web/src/app/components/App.tsx +++ b/invokeai/frontend/web/src/app/components/App.tsx @@ -12,12 +12,12 @@ import { languageSelector } from 'features/system/store/systemSelectors'; import InvokeTabs from 'features/ui/components/InvokeTabs'; import i18n from 'i18n'; import { size } from 'lodash-es'; -import { ReactNode, memo, useCallback, useEffect, useMemo } from 'react'; +import { ReactNode, memo, useCallback, useEffect } from 'react'; import { ErrorBoundary } from 'react-error-boundary'; +import { usePreselectedImage } from '../../features/parameters/hooks/usePreselectedImage'; import AppErrorBoundaryFallback from './AppErrorBoundaryFallback'; import GlobalHotkeys from './GlobalHotkeys'; import Toaster from './Toaster'; -import { usePreselectedImage } from '../../features/parameters/hooks/usePreselectedImage'; const DEFAULT_CONFIG = {}; diff --git a/invokeai/frontend/web/src/features/parameters/hooks/usePreselectedImage.ts b/invokeai/frontend/web/src/features/parameters/hooks/usePreselectedImage.ts index fa310a66ad..6f7ac46f25 100644 --- a/invokeai/frontend/web/src/features/parameters/hooks/usePreselectedImage.ts +++ b/invokeai/frontend/web/src/features/parameters/hooks/usePreselectedImage.ts @@ -1,16 +1,16 @@ import { skipToken } from '@reduxjs/toolkit/dist/query'; -import { useCallback, useMemo, useState } from 'react'; +import { t } from 'i18next'; +import { useCallback, useState } from 'react'; +import { useAppToaster } from '../../../app/components/Toaster'; +import { useAppDispatch } from '../../../app/store/storeHooks'; import { useGetImageDTOQuery, useGetImageMetadataQuery, } from '../../../services/api/endpoints/images'; -import { useAppDispatch } from '../../../app/store/storeHooks'; import { setInitialCanvasImage } from '../../canvas/store/canvasSlice'; import { setActiveTab } from '../../ui/store/uiSlice'; -import { useRecallParameters } from './useRecallParameters'; import { initialImageSelected } from '../store/actions'; -import { useAppToaster } from '../../../app/components/Toaster'; -import { t } from 'i18next'; +import { useRecallParameters } from './useRecallParameters'; type SelectedImage = { imageName: string; @@ -26,7 +26,7 @@ export const usePreselectedImage = () => { const { recallAllParameters } = useRecallParameters(); const toaster = useAppToaster(); - const { currentData: selectedImageDto, isError } = useGetImageDTOQuery( + const { currentData: selectedImageDto } = useGetImageDTOQuery( imageNameForDto ?? skipToken ); @@ -37,8 +37,8 @@ export const usePreselectedImage = () => { const handlePreselectedImage = useCallback( (selectedImage?: SelectedImage) => { if (!selectedImage) { -return; -} + return; + } if (selectedImage.action === 'sendToCanvas') { setImageNameForDto(selectedImage?.imageName);