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