diff --git a/invokeai/frontend/web/src/features/controlAdapters/components/ControlAdapterImagePreview.tsx b/invokeai/frontend/web/src/features/controlAdapters/components/ControlAdapterImagePreview.tsx index e12abf4830..b3b584d07e 100644 --- a/invokeai/frontend/web/src/features/controlAdapters/components/ControlAdapterImagePreview.tsx +++ b/invokeai/frontend/web/src/features/controlAdapters/components/ControlAdapterImagePreview.tsx @@ -5,14 +5,19 @@ import { stateSelector } from 'app/store/store'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; import IAIDndImage from 'common/components/IAIDndImage'; +import IAIDndImageIcon from 'common/components/IAIDndImageIcon'; import { setBoundingBoxDimensions } from 'features/canvas/store/canvasSlice'; +import { useControlAdapterControlImage } from 'features/controlAdapters/hooks/useControlAdapterControlImage'; +import { useControlAdapterProcessedControlImage } from 'features/controlAdapters/hooks/useControlAdapterProcessedControlImage'; +import { useControlAdapterProcessorType } from 'features/controlAdapters/hooks/useControlAdapterProcessorType'; +import { controlAdapterImageChanged } from 'features/controlAdapters/store/controlAdaptersSlice'; import { TypesafeDraggableData, TypesafeDroppableData, } from 'features/dnd/types'; import { setHeight, setWidth } from 'features/parameters/store/generationSlice'; import { activeTabNameSelector } from 'features/ui/store/uiSelectors'; -import { memo, useCallback, useMemo, useState } from 'react'; +import { memo, useCallback, useEffect, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { FaRulerVertical, FaSave, FaUndo } from 'react-icons/fa'; import { @@ -22,11 +27,6 @@ import { useRemoveImageFromBoardMutation, } from 'services/api/endpoints/images'; import { PostUploadAction } from 'services/api/types'; -import IAIDndImageIcon from 'common/components/IAIDndImageIcon'; -import { controlAdapterImageChanged } from 'features/controlAdapters/store/controlAdaptersSlice'; -import { useControlAdapterControlImage } from 'features/controlAdapters/hooks/useControlAdapterControlImage'; -import { useControlAdapterProcessedControlImage } from 'features/controlAdapters/hooks/useControlAdapterProcessedControlImage'; -import { useControlAdapterProcessorType } from 'features/controlAdapters/hooks/useControlAdapterProcessorType'; type Props = { id: string; @@ -35,13 +35,15 @@ type Props = { const selector = createSelector( stateSelector, - ({ controlAdapters, gallery }) => { + ({ controlAdapters, gallery, system }) => { const { pendingControlImages } = controlAdapters; const { autoAddBoardId } = gallery; + const { isConnected } = system; return { pendingControlImages, autoAddBoardId, + isConnected, }; }, defaultSelectorOptions @@ -55,18 +57,19 @@ const ControlAdapterImagePreview = ({ isSmall, id }: Props) => { const dispatch = useAppDispatch(); const { t } = useTranslation(); - const { pendingControlImages, autoAddBoardId } = useAppSelector(selector); + const { pendingControlImages, autoAddBoardId, isConnected } = + useAppSelector(selector); const activeTabName = useAppSelector(activeTabNameSelector); const [isMouseOverImage, setIsMouseOverImage] = useState(false); - const { currentData: controlImage } = useGetImageDTOQuery( - controlImageName ?? skipToken - ); + const { currentData: controlImage, isError: isErrorControlImage } = + useGetImageDTOQuery(controlImageName ?? skipToken); - const { currentData: processedControlImage } = useGetImageDTOQuery( - processedControlImageName ?? skipToken - ); + const { + currentData: processedControlImage, + isError: isErrorProcessedControlImage, + } = useGetImageDTOQuery(processedControlImageName ?? skipToken); const [changeIsIntermediate] = useChangeImageIsIntermediateMutation(); const [addToBoard] = useAddImageToBoardMutation(); @@ -158,6 +161,17 @@ const ControlAdapterImagePreview = ({ isSmall, id }: Props) => { !pendingControlImages.includes(id) && processorType !== 'none'; + useEffect(() => { + if (isConnected && (isErrorControlImage || isErrorProcessedControlImage)) { + handleResetControlImage(); + } + }, [ + handleResetControlImage, + isConnected, + isErrorControlImage, + isErrorProcessedControlImage, + ]); + return ( { const { nodeId, field } = props; const dispatch = useAppDispatch(); - - const { currentData: imageDTO } = useGetImageDTOQuery( + const isConnected = useAppSelector((state) => state.system.isConnected); + const { currentData: imageDTO, isError } = useGetImageDTOQuery( field.value?.image_name ?? skipToken ); @@ -67,6 +67,12 @@ const ImageFieldInputComponent = ( [nodeId, field.name] ); + useEffect(() => { + if (isConnected && isError) { + handleReset(); + } + }, [handleReset, isConnected, isError]); + return ( { const { initialImage } = state.generation; + const { isConnected } = state.system; + return { initialImage, isResetButtonDisabled: !initialImage, + isConnected, }; }, defaultSelectorOptions ); const InitialImage = () => { - const { initialImage } = useAppSelector(selector); + const dispatch = useAppDispatch(); + const { initialImage, isConnected } = useAppSelector(selector); - const { currentData: imageDTO } = useGetImageDTOQuery( + const { currentData: imageDTO, isError } = useGetImageDTOQuery( initialImage?.imageName ?? skipToken ); @@ -49,6 +54,13 @@ const InitialImage = () => { [] ); + useEffect(() => { + if (isError && isConnected) { + // The image doesn't exist, reset init image + dispatch(clearInitialImage()); + } + }, [dispatch, isConnected, isError]); + return (