diff --git a/invokeai/frontend/web/src/app/selectors/readinessSelector.ts b/invokeai/frontend/web/src/common/hooks/useIsReadyToInvoke.ts similarity index 89% rename from invokeai/frontend/web/src/app/selectors/readinessSelector.ts rename to invokeai/frontend/web/src/common/hooks/useIsReadyToInvoke.ts index 2b77fe9f47..7204205216 100644 --- a/invokeai/frontend/web/src/app/selectors/readinessSelector.ts +++ b/invokeai/frontend/web/src/common/hooks/useIsReadyToInvoke.ts @@ -1,12 +1,12 @@ import { createSelector } from '@reduxjs/toolkit'; +import { useAppSelector } from 'app/store/storeHooks'; import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; import { validateSeedWeights } from 'common/util/seedWeightPairs'; import { generationSelector } from 'features/parameters/store/generationSelectors'; import { systemSelector } from 'features/system/store/systemSelectors'; import { activeTabNameSelector } from 'features/ui/store/uiSelectors'; -import { isEqual } from 'lodash-es'; -export const readinessSelector = createSelector( +const readinessSelector = createSelector( [generationSelector, systemSelector, activeTabNameSelector], (generation, system, activeTabName) => { const { @@ -60,3 +60,8 @@ export const readinessSelector = createSelector( }, defaultSelectorOptions ); + +export const useIsReadyToInvoke = () => { + const { isReady } = useAppSelector(readinessSelector); + return isReady; +}; diff --git a/invokeai/frontend/web/src/features/controlNet/components/ControlNet.tsx b/invokeai/frontend/web/src/features/controlNet/components/ControlNet.tsx index b9b8e77fcc..6095e5e956 100644 --- a/invokeai/frontend/web/src/features/controlNet/components/ControlNet.tsx +++ b/invokeai/frontend/web/src/features/controlNet/components/ControlNet.tsx @@ -1,7 +1,5 @@ import { memo, useCallback } from 'react'; -import { RequiredControlNetProcessorNode } from '../store/types'; import { ImageDTO } from 'services/api'; -import CannyProcessor from './processors/CannyProcessor'; import { ControlNet, controlNetImageChanged, @@ -23,11 +21,11 @@ import { } from '@chakra-ui/react'; import IAISelectableImage from './parameters/IAISelectableImage'; import IAIButton from 'common/components/IAIButton'; -import { controlNetImageProcessed } from '../store/actions'; import { FaUndo } from 'react-icons/fa'; -import HedProcessor from './processors/HedProcessor'; import ParamControlNetProcessorSelect from './parameters/ParamControlNetProcessorSelect'; -import ProcessorComponent from './ProcessorComponent'; +import ControlNetProcessorComponent from './ControlNetProcessorComponent'; +import { useIsApplicationReady } from 'features/system/hooks/useIsApplicationReady'; +import ControlNetPreprocessButton from './ControlNetPreprocessButton'; type ControlNetProps = { controlNet: ControlNet; @@ -47,6 +45,7 @@ const ControlNet = (props: ControlNetProps) => { processorNode, } = props.controlNet; const dispatch = useAppDispatch(); + const isReady = useIsApplicationReady(); const handleControlImageChanged = useCallback( (controlImage: ImageDTO) => { @@ -55,14 +54,6 @@ const ControlNet = (props: ControlNetProps) => { [controlNetId, dispatch] ); - const handleProcess = useCallback(() => { - dispatch( - controlNetImageProcessed({ - controlNetId, - }) - ); - }, [controlNetId, dispatch]); - const handleReset = useCallback(() => { dispatch( controlNetProcessedImageChanged({ @@ -128,17 +119,11 @@ const ControlNet = (props: ControlNetProps) => { controlNetId={controlNetId} processorNode={processorNode} /> - - - Preprocess - + } diff --git a/invokeai/frontend/web/src/features/controlNet/components/ControlNetPreprocessButton.tsx b/invokeai/frontend/web/src/features/controlNet/components/ControlNetPreprocessButton.tsx new file mode 100644 index 0000000000..94b1f86501 --- /dev/null +++ b/invokeai/frontend/web/src/features/controlNet/components/ControlNetPreprocessButton.tsx @@ -0,0 +1,36 @@ +import IAIButton from 'common/components/IAIButton'; +import { memo, useCallback } from 'react'; +import { ControlNet } from '../store/controlNetSlice'; +import { useAppDispatch } from 'app/store/storeHooks'; +import { controlNetImageProcessed } from '../store/actions'; +import { useIsReadyToInvoke } from 'common/hooks/useIsReadyToInvoke'; + +type Props = { + controlNet: ControlNet; +}; + +const ControlNetPreprocessButton = (props: Props) => { + const { controlNetId, controlImage } = props.controlNet; + const dispatch = useAppDispatch(); + const isReady = useIsReadyToInvoke(); + + const handleProcess = useCallback(() => { + dispatch( + controlNetImageProcessed({ + controlNetId, + }) + ); + }, [controlNetId, dispatch]); + + return ( + + Preprocess + + ); +}; + +export default memo(ControlNetPreprocessButton); diff --git a/invokeai/frontend/web/src/features/controlNet/components/ProcessorComponent.tsx b/invokeai/frontend/web/src/features/controlNet/components/ControlNetProcessorComponent.tsx similarity index 96% rename from invokeai/frontend/web/src/features/controlNet/components/ProcessorComponent.tsx rename to invokeai/frontend/web/src/features/controlNet/components/ControlNetProcessorComponent.tsx index 246aea70c7..4649f89b35 100644 --- a/invokeai/frontend/web/src/features/controlNet/components/ProcessorComponent.tsx +++ b/invokeai/frontend/web/src/features/controlNet/components/ControlNetProcessorComponent.tsx @@ -18,7 +18,7 @@ export type ControlNetProcessorProps = { processorNode: RequiredControlNetProcessorNode; }; -const ProcessorComponent = (props: ControlNetProcessorProps) => { +const ControlNetProcessorComponent = (props: ControlNetProcessorProps) => { const { controlNetId, processorNode } = props; if (processorNode.type === 'canny_image_processor') { return ( @@ -128,4 +128,4 @@ const ProcessorComponent = (props: ControlNetProcessorProps) => { return null; }; -export default memo(ProcessorComponent); +export default memo(ControlNetProcessorComponent); diff --git a/invokeai/frontend/web/src/features/controlNet/components/processors/common/ControlNetProcessorButtons.tsx b/invokeai/frontend/web/src/features/controlNet/components/processors/common/ControlNetProcessorButtons.tsx deleted file mode 100644 index a051990f67..0000000000 --- a/invokeai/frontend/web/src/features/controlNet/components/processors/common/ControlNetProcessorButtons.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import { Flex } from '@chakra-ui/react'; -import { memo } from 'react'; -import { FaUndo } from 'react-icons/fa'; -import IAIButton from 'common/components/IAIButton'; - -type ControlNetProcessorButtonsProps = { - handleProcess: () => void; - isProcessDisabled: boolean; - handleReset: () => void; - isResetDisabled: boolean; -}; - -const ControlNetProcessorButtons = (props: ControlNetProcessorButtonsProps) => { - const { handleProcess, isProcessDisabled, handleReset, isResetDisabled } = - props; - return ( - - ); -}; - -export default memo(ControlNetProcessorButtons); diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamPositiveConditioning.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamPositiveConditioning.tsx index 365bade0aa..0980b84ab3 100644 --- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamPositiveConditioning.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamPositiveConditioning.tsx @@ -4,7 +4,6 @@ import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { ChangeEvent, KeyboardEvent, useCallback, useRef } from 'react'; import { createSelector } from '@reduxjs/toolkit'; -import { readinessSelector } from 'app/selectors/readinessSelector'; import { GenerationState, clampSymmetrySteps, @@ -17,6 +16,7 @@ import { useHotkeys } from 'react-hotkeys-hook'; import { useTranslation } from 'react-i18next'; import { userInvoked } from 'app/store/actions'; import IAITextarea from 'common/components/IAITextarea'; +import { useIsReadyToInvoke } from 'common/hooks/useIsReadyToInvoke'; const promptInputSelector = createSelector( [(state: RootState) => state.generation, activeTabNameSelector], @@ -39,7 +39,7 @@ const promptInputSelector = createSelector( const ParamPositiveConditioning = () => { const dispatch = useAppDispatch(); const { prompt, activeTabName } = useAppSelector(promptInputSelector); - const { isReady } = useAppSelector(readinessSelector); + const isReady = useIsReadyToInvoke(); const promptRef = useRef(null); diff --git a/invokeai/frontend/web/src/features/parameters/components/ProcessButtons/InvokeButton.tsx b/invokeai/frontend/web/src/features/parameters/components/ProcessButtons/InvokeButton.tsx index 4ada615628..449280aa03 100644 --- a/invokeai/frontend/web/src/features/parameters/components/ProcessButtons/InvokeButton.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/ProcessButtons/InvokeButton.tsx @@ -1,11 +1,11 @@ import { Box } from '@chakra-ui/react'; -import { readinessSelector } from 'app/selectors/readinessSelector'; import { userInvoked } from 'app/store/actions'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIButton, { IAIButtonProps } from 'common/components/IAIButton'; import IAIIconButton, { IAIIconButtonProps, } from 'common/components/IAIIconButton'; +import { useIsReadyToInvoke } from 'common/hooks/useIsReadyToInvoke'; import { clampSymmetrySteps } from 'features/parameters/store/generationSlice'; import ProgressBar from 'features/system/components/ProgressBar'; import { activeTabNameSelector } from 'features/ui/store/uiSelectors'; @@ -22,7 +22,7 @@ interface InvokeButton export default function InvokeButton(props: InvokeButton) { const { iconButton = false, ...rest } = props; const dispatch = useAppDispatch(); - const { isReady } = useAppSelector(readinessSelector); + const isReady = useIsReadyToInvoke(); const activeTabName = useAppSelector(activeTabNameSelector); const handleInvoke = useCallback(() => { diff --git a/invokeai/frontend/web/src/features/system/hooks/useIsApplicationReady.ts b/invokeai/frontend/web/src/features/system/hooks/useIsApplicationReady.ts index 6e62c3642b..193420e29c 100644 --- a/invokeai/frontend/web/src/features/system/hooks/useIsApplicationReady.ts +++ b/invokeai/frontend/web/src/features/system/hooks/useIsApplicationReady.ts @@ -19,6 +19,9 @@ const isApplicationReadySelector = createSelector( } ); +/** + * Checks if the application is ready to be used, i.e. if the initial startup process is finished. + */ export const useIsApplicationReady = () => { const { disabledTabs, wereModelsReceived, wasSchemaParsed } = useAppSelector( isApplicationReadySelector