From 219da47576953288c098facfb29e568594705bf1 Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Thu, 27 Oct 2022 22:19:36 +1100 Subject: [PATCH] Fixes invoke button working when only eraser strokes --- .../src/common/hooks/useCheckParameters.ts | 82 ++++++------------- .../options/ProcessButtons/CancelButton.tsx | 24 +++++- .../options/PromptInput/PromptInput.tsx | 18 ++-- 3 files changed, 52 insertions(+), 72 deletions(-) diff --git a/frontend/src/common/hooks/useCheckParameters.ts b/frontend/src/common/hooks/useCheckParameters.ts index 0cc79143a5..ee38b9636a 100644 --- a/frontend/src/common/hooks/useCheckParameters.ts +++ b/frontend/src/common/hooks/useCheckParameters.ts @@ -1,9 +1,8 @@ import { createSelector } from '@reduxjs/toolkit'; -import { isEqual } from 'lodash'; +import _ from 'lodash'; import { useMemo } from 'react'; import { useAppSelector } from '../../app/store'; import { RootState } from '../../app/store'; -import { GalleryState } from '../../features/gallery/gallerySlice'; import { OptionsState } from '../../features/options/optionsSlice'; import { SystemState } from '../../features/system/systemSlice'; @@ -11,10 +10,15 @@ import { InpaintingState } from '../../features/tabs/Inpainting/inpaintingSlice' import { tabMap } from '../../features/tabs/InvokeTabs'; import { validateSeedWeights } from '../util/seedWeightPairs'; -export const optionsSelector = createSelector( - (state: RootState) => state.options, - (options: OptionsState) => { +export const useCheckParametersSelector = createSelector( + [ + (state: RootState) => state.options, + (state: RootState) => state.system, + (state: RootState) => state.inpainting, + ], + (options: OptionsState, system: SystemState, inpainting: InpaintingState) => { return { + // options prompt: options.prompt, shouldGenerateVariations: options.shouldGenerateVariations, seedWeights: options.seedWeights, @@ -22,58 +26,21 @@ export const optionsSelector = createSelector( initialImagePath: options.initialImagePath, seed: options.seed, activeTabName: tabMap[options.activeTab], - }; - }, - { - memoizeOptions: { - resultEqualityCheck: isEqual, - }, - } -); - -export const systemSelector = createSelector( - (state: RootState) => state.system, - (system: SystemState) => { - return { + // system isProcessing: system.isProcessing, isConnected: system.isConnected, + // inpainting + isMaskEmpty: + inpainting.lines.filter((line) => line.tool === 'brush').length === 0, + hasInpaintingImage: Boolean(inpainting.imageToInpaint), }; }, { memoizeOptions: { - resultEqualityCheck: isEqual, + resultEqualityCheck: _.isEqual, }, } ); - -export const inpaintingSelector = createSelector( - (state: RootState) => state.inpainting, - (inpainting: InpaintingState) => { - return { - isMaskEmpty: inpainting.lines.length === 0, - }; - }, - { - memoizeOptions: { - resultEqualityCheck: isEqual, - }, - } -); - -export const gallerySelector = createSelector( - (state: RootState) => state.gallery, - (gallery: GalleryState) => { - return { - hasCurrentImage: Boolean(gallery.currentImage), - }; - }, - { - memoizeOptions: { - resultEqualityCheck: isEqual, - }, - } -); - /** * Checks relevant pieces of state to confirm generation will not deterministically fail. * This is used to prevent the 'Generate' button from being clicked. @@ -87,13 +54,11 @@ const useCheckParameters = (): boolean => { initialImagePath, seed, activeTabName, - } = useAppSelector(optionsSelector); - - const { isProcessing, isConnected } = useAppSelector(systemSelector); - - const { isMaskEmpty } = useAppSelector(inpaintingSelector); - - const { hasCurrentImage } = useAppSelector(gallerySelector); + isProcessing, + isConnected, + isMaskEmpty, + hasInpaintingImage, + } = useAppSelector(useCheckParametersSelector); return useMemo(() => { // Cannot generate without a prompt @@ -105,7 +70,10 @@ const useCheckParameters = (): boolean => { return false; } - if (activeTabName === 'inpainting' && (!hasCurrentImage || isMaskEmpty)) { + if ( + activeTabName === 'inpainting' && + (!hasInpaintingImage || isMaskEmpty) + ) { return false; } @@ -145,8 +113,8 @@ const useCheckParameters = (): boolean => { seedWeights, seed, activeTabName, - hasCurrentImage, isMaskEmpty, + hasInpaintingImage, ]); }; diff --git a/frontend/src/features/options/ProcessButtons/CancelButton.tsx b/frontend/src/features/options/ProcessButtons/CancelButton.tsx index b44eb8ec41..f7e66cb974 100644 --- a/frontend/src/features/options/ProcessButtons/CancelButton.tsx +++ b/frontend/src/features/options/ProcessButtons/CancelButton.tsx @@ -1,14 +1,30 @@ -import React from 'react'; import { MdCancel } from 'react-icons/md'; import { cancelProcessing } from '../../../app/socketio/actions'; -import { useAppDispatch, useAppSelector } from '../../../app/store'; +import { RootState, useAppDispatch, useAppSelector } from '../../../app/store'; import IAIIconButton from '../../../common/components/IAIIconButton'; -import { systemSelector } from '../../../common/hooks/useCheckParameters'; import { useHotkeys } from 'react-hotkeys-hook'; +import { createSelector } from '@reduxjs/toolkit'; +import { SystemState } from '../../system/systemSlice'; +import _ from 'lodash'; + +const cancelButtonSelector = createSelector( + (state: RootState) => state.system, + (system: SystemState) => { + return { + isProcessing: system.isProcessing, + isConnected: system.isConnected, + }; + }, + { + memoizeOptions: { + resultEqualityCheck: _.isEqual, + }, + } +); export default function CancelButton() { const dispatch = useAppDispatch(); - const { isProcessing, isConnected } = useAppSelector(systemSelector); + const { isProcessing, isConnected } = useAppSelector(cancelButtonSelector); const handleClickCancel = () => dispatch(cancelProcessing()); useHotkeys( diff --git a/frontend/src/features/options/PromptInput/PromptInput.tsx b/frontend/src/features/options/PromptInput/PromptInput.tsx index 8dde1ce929..178bd4ff30 100644 --- a/frontend/src/features/options/PromptInput/PromptInput.tsx +++ b/frontend/src/features/options/PromptInput/PromptInput.tsx @@ -5,25 +5,22 @@ import { generateImage } from '../../../app/socketio/actions'; import { OptionsState, setPrompt } from '../optionsSlice'; import { createSelector } from '@reduxjs/toolkit'; -import { isEqual } from 'lodash'; -import useCheckParameters, { - systemSelector, -} from '../../../common/hooks/useCheckParameters'; +import _ from 'lodash'; +import useCheckParameters from '../../../common/hooks/useCheckParameters'; import { useHotkeys } from 'react-hotkeys-hook'; import { tabMap } from '../../tabs/InvokeTabs'; -export const optionsSelector = createSelector( +const promptInputSelector = createSelector( (state: RootState) => state.options, (options: OptionsState) => { - const { prompt, activeTab } = options; return { - prompt, - activeTabName: tabMap[activeTab], + prompt: options.prompt, + activeTabName: tabMap[options.activeTab], }; }, { memoizeOptions: { - resultEqualityCheck: isEqual, + resultEqualityCheck: _.isEqual, }, } ); @@ -33,8 +30,7 @@ export const optionsSelector = createSelector( */ const PromptInput = () => { const promptRef = useRef(null); - const { prompt, activeTabName } = useAppSelector(optionsSelector); - const { isProcessing } = useAppSelector(systemSelector); + const { prompt, activeTabName } = useAppSelector(promptInputSelector); const dispatch = useAppDispatch(); const isReady = useCheckParameters();