Fixes invoke button working when only eraser strokes

This commit is contained in:
psychedelicious 2022-10-27 22:19:36 +11:00
parent 47106eeeea
commit 219da47576
3 changed files with 52 additions and 72 deletions

View File

@ -1,9 +1,8 @@
import { createSelector } from '@reduxjs/toolkit'; import { createSelector } from '@reduxjs/toolkit';
import { isEqual } from 'lodash'; import _ from 'lodash';
import { useMemo } from 'react'; import { useMemo } from 'react';
import { useAppSelector } from '../../app/store'; import { useAppSelector } from '../../app/store';
import { RootState } from '../../app/store'; import { RootState } from '../../app/store';
import { GalleryState } from '../../features/gallery/gallerySlice';
import { OptionsState } from '../../features/options/optionsSlice'; import { OptionsState } from '../../features/options/optionsSlice';
import { SystemState } from '../../features/system/systemSlice'; import { SystemState } from '../../features/system/systemSlice';
@ -11,10 +10,15 @@ import { InpaintingState } from '../../features/tabs/Inpainting/inpaintingSlice'
import { tabMap } from '../../features/tabs/InvokeTabs'; import { tabMap } from '../../features/tabs/InvokeTabs';
import { validateSeedWeights } from '../util/seedWeightPairs'; import { validateSeedWeights } from '../util/seedWeightPairs';
export const optionsSelector = createSelector( export const useCheckParametersSelector = createSelector(
[
(state: RootState) => state.options, (state: RootState) => state.options,
(options: OptionsState) => { (state: RootState) => state.system,
(state: RootState) => state.inpainting,
],
(options: OptionsState, system: SystemState, inpainting: InpaintingState) => {
return { return {
// options
prompt: options.prompt, prompt: options.prompt,
shouldGenerateVariations: options.shouldGenerateVariations, shouldGenerateVariations: options.shouldGenerateVariations,
seedWeights: options.seedWeights, seedWeights: options.seedWeights,
@ -22,58 +26,21 @@ export const optionsSelector = createSelector(
initialImagePath: options.initialImagePath, initialImagePath: options.initialImagePath,
seed: options.seed, seed: options.seed,
activeTabName: tabMap[options.activeTab], activeTabName: tabMap[options.activeTab],
}; // system
},
{
memoizeOptions: {
resultEqualityCheck: isEqual,
},
}
);
export const systemSelector = createSelector(
(state: RootState) => state.system,
(system: SystemState) => {
return {
isProcessing: system.isProcessing, isProcessing: system.isProcessing,
isConnected: system.isConnected, isConnected: system.isConnected,
// inpainting
isMaskEmpty:
inpainting.lines.filter((line) => line.tool === 'brush').length === 0,
hasInpaintingImage: Boolean(inpainting.imageToInpaint),
}; };
}, },
{ {
memoizeOptions: { 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. * Checks relevant pieces of state to confirm generation will not deterministically fail.
* This is used to prevent the 'Generate' button from being clicked. * This is used to prevent the 'Generate' button from being clicked.
@ -87,13 +54,11 @@ const useCheckParameters = (): boolean => {
initialImagePath, initialImagePath,
seed, seed,
activeTabName, activeTabName,
} = useAppSelector(optionsSelector); isProcessing,
isConnected,
const { isProcessing, isConnected } = useAppSelector(systemSelector); isMaskEmpty,
hasInpaintingImage,
const { isMaskEmpty } = useAppSelector(inpaintingSelector); } = useAppSelector(useCheckParametersSelector);
const { hasCurrentImage } = useAppSelector(gallerySelector);
return useMemo(() => { return useMemo(() => {
// Cannot generate without a prompt // Cannot generate without a prompt
@ -105,7 +70,10 @@ const useCheckParameters = (): boolean => {
return false; return false;
} }
if (activeTabName === 'inpainting' && (!hasCurrentImage || isMaskEmpty)) { if (
activeTabName === 'inpainting' &&
(!hasInpaintingImage || isMaskEmpty)
) {
return false; return false;
} }
@ -145,8 +113,8 @@ const useCheckParameters = (): boolean => {
seedWeights, seedWeights,
seed, seed,
activeTabName, activeTabName,
hasCurrentImage,
isMaskEmpty, isMaskEmpty,
hasInpaintingImage,
]); ]);
}; };

View File

@ -1,14 +1,30 @@
import React from 'react';
import { MdCancel } from 'react-icons/md'; import { MdCancel } from 'react-icons/md';
import { cancelProcessing } from '../../../app/socketio/actions'; 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 IAIIconButton from '../../../common/components/IAIIconButton';
import { systemSelector } from '../../../common/hooks/useCheckParameters';
import { useHotkeys } from 'react-hotkeys-hook'; 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() { export default function CancelButton() {
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const { isProcessing, isConnected } = useAppSelector(systemSelector); const { isProcessing, isConnected } = useAppSelector(cancelButtonSelector);
const handleClickCancel = () => dispatch(cancelProcessing()); const handleClickCancel = () => dispatch(cancelProcessing());
useHotkeys( useHotkeys(

View File

@ -5,25 +5,22 @@ import { generateImage } from '../../../app/socketio/actions';
import { OptionsState, setPrompt } from '../optionsSlice'; import { OptionsState, setPrompt } from '../optionsSlice';
import { createSelector } from '@reduxjs/toolkit'; import { createSelector } from '@reduxjs/toolkit';
import { isEqual } from 'lodash'; import _ from 'lodash';
import useCheckParameters, { import useCheckParameters from '../../../common/hooks/useCheckParameters';
systemSelector,
} from '../../../common/hooks/useCheckParameters';
import { useHotkeys } from 'react-hotkeys-hook'; import { useHotkeys } from 'react-hotkeys-hook';
import { tabMap } from '../../tabs/InvokeTabs'; import { tabMap } from '../../tabs/InvokeTabs';
export const optionsSelector = createSelector( const promptInputSelector = createSelector(
(state: RootState) => state.options, (state: RootState) => state.options,
(options: OptionsState) => { (options: OptionsState) => {
const { prompt, activeTab } = options;
return { return {
prompt, prompt: options.prompt,
activeTabName: tabMap[activeTab], activeTabName: tabMap[options.activeTab],
}; };
}, },
{ {
memoizeOptions: { memoizeOptions: {
resultEqualityCheck: isEqual, resultEqualityCheck: _.isEqual,
}, },
} }
); );
@ -33,8 +30,7 @@ export const optionsSelector = createSelector(
*/ */
const PromptInput = () => { const PromptInput = () => {
const promptRef = useRef<HTMLTextAreaElement>(null); const promptRef = useRef<HTMLTextAreaElement>(null);
const { prompt, activeTabName } = useAppSelector(optionsSelector); const { prompt, activeTabName } = useAppSelector(promptInputSelector);
const { isProcessing } = useAppSelector(systemSelector);
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const isReady = useCheckParameters(); const isReady = useCheckParameters();