Floating panel re-render fix

This commit is contained in:
blessedcoolant 2022-11-22 19:26:32 +13:00
parent 3ea732365c
commit 7b76b79887
3 changed files with 61 additions and 81 deletions

View File

@ -4,78 +4,15 @@ import Console from 'features/system/components/Console';
import { keepGUIAlive } from './utils'; import { keepGUIAlive } from './utils';
import InvokeTabs from 'features/tabs/components/InvokeTabs'; import InvokeTabs from 'features/tabs/components/InvokeTabs';
import ImageUploader from 'common/components/ImageUploader'; import ImageUploader from 'common/components/ImageUploader';
import { RootState, useAppSelector } from 'app/store';
import FloatingGalleryButton from 'features/tabs/components/FloatingGalleryButton';
import FloatingOptionsPanelButtons from 'features/tabs/components/FloatingOptionsPanelButtons';
import { createSelector } from '@reduxjs/toolkit';
import { GalleryState } from 'features/gallery/store/gallerySlice';
import { OptionsState } from 'features/options/store/optionsSlice';
import { activeTabNameSelector } from 'features/options/store/optionsSelectors';
import { SystemState } from 'features/system/store/systemSlice';
import _ from 'lodash';
import { Model } from './invokeai';
import useToastWatcher from 'features/system/hooks/useToastWatcher'; import useToastWatcher from 'features/system/hooks/useToastWatcher';
import FloatingOptionsPanelButtons from 'features/tabs/components/FloatingOptionsPanelButtons';
import FloatingGalleryButton from 'features/tabs/components/FloatingGalleryButton';
keepGUIAlive(); keepGUIAlive();
const appSelector = createSelector(
[
(state: RootState) => state.gallery,
(state: RootState) => state.options,
(state: RootState) => state.system,
activeTabNameSelector,
],
(
gallery: GalleryState,
options: OptionsState,
system: SystemState,
activeTabName
) => {
const { shouldShowGallery, shouldHoldGalleryOpen, shouldPinGallery } =
gallery;
const {
shouldShowOptionsPanel,
shouldHoldOptionsPanelOpen,
shouldPinOptionsPanel,
} = options;
const modelStatusText = _.reduce(
system.model_list,
(acc: string, cur: Model, key: string) => {
if (cur.status === 'active') acc = key;
return acc;
},
''
);
const shouldShowGalleryButton =
!(shouldShowGallery || (shouldHoldGalleryOpen && !shouldPinGallery)) &&
['txt2img', 'img2img', 'unifiedCanvas'].includes(activeTabName);
const shouldShowOptionsPanelButton =
!(
shouldShowOptionsPanel ||
(shouldHoldOptionsPanelOpen && !shouldPinOptionsPanel)
) && ['txt2img', 'img2img', 'unifiedCanvas'].includes(activeTabName);
return {
modelStatusText,
shouldShowGalleryButton,
shouldShowOptionsPanelButton,
};
},
{
memoizeOptions: {
resultEqualityCheck: _.isEqual,
},
}
);
const App = () => { const App = () => {
const { shouldShowGalleryButton, shouldShowOptionsPanelButton } =
useAppSelector(appSelector);
useToastWatcher(); useToastWatcher();
return ( return (
@ -89,9 +26,9 @@ const App = () => {
<div className="app-console"> <div className="app-console">
<Console /> <Console />
</div> </div>
{shouldShowGalleryButton && <FloatingGalleryButton />}
{shouldShowOptionsPanelButton && <FloatingOptionsPanelButtons />}
</ImageUploader> </ImageUploader>
<FloatingOptionsPanelButtons />
<FloatingGalleryButton />
</div> </div>
); );
}; };

View File

@ -1,13 +1,41 @@
import { MdPhotoLibrary } from 'react-icons/md'; import { MdPhotoLibrary } from 'react-icons/md';
import { RootState, 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 { setShouldShowGallery } from 'features/gallery/store/gallerySlice'; import {
GalleryState,
setShouldShowGallery,
} from 'features/gallery/store/gallerySlice';
import { setDoesCanvasNeedScaling } from 'features/canvas/store/canvasSlice'; import { setDoesCanvasNeedScaling } from 'features/canvas/store/canvasSlice';
import { createSelector } from '@reduxjs/toolkit';
import { activeTabNameSelector } from 'features/options/store/optionsSelectors';
import _ from 'lodash';
const floatingGallerySelcetor = createSelector(
[(state: RootState) => state.gallery, activeTabNameSelector],
(gallery: GalleryState, activeTabName) => {
const { shouldShowGallery, shouldHoldGalleryOpen, shouldPinGallery } =
gallery;
const shouldShowGalleryButton =
!(shouldShowGallery || (shouldHoldGalleryOpen && !shouldPinGallery)) &&
['txt2img', 'img2img', 'unifiedCanvas'].includes(activeTabName);
return {
shouldPinGallery,
shouldShowGalleryButton,
};
},
{
memoizeOptions: {
resultEqualityCheck: _.isEqual,
},
}
);
const FloatingGalleryButton = () => { const FloatingGalleryButton = () => {
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const shouldPinGallery = useAppSelector( const { shouldShowGalleryButton, shouldPinGallery } = useAppSelector(
(state: RootState) => state.gallery.shouldPinGallery floatingGallerySelcetor
); );
const handleShowGallery = () => { const handleShowGallery = () => {
@ -17,7 +45,7 @@ const FloatingGalleryButton = () => {
} }
}; };
return ( return shouldShowGalleryButton ? (
<IAIIconButton <IAIIconButton
tooltip="Show Gallery (G)" tooltip="Show Gallery (G)"
tooltipProps={{ placement: 'top' }} tooltipProps={{ placement: 'top' }}
@ -27,7 +55,7 @@ const FloatingGalleryButton = () => {
> >
<MdPhotoLibrary /> <MdPhotoLibrary />
</IAIIconButton> </IAIIconButton>
); ) : null;
}; };
export default FloatingGalleryButton; export default FloatingGalleryButton;

View File

@ -10,16 +10,28 @@ import InvokeButton from 'features/options/components/ProcessButtons/InvokeButto
import _ from 'lodash'; import _ from 'lodash';
import { setDoesCanvasNeedScaling } from 'features/canvas/store/canvasSlice'; import { setDoesCanvasNeedScaling } from 'features/canvas/store/canvasSlice';
import { FaSlidersH } from 'react-icons/fa'; import { FaSlidersH } from 'react-icons/fa';
import { activeTabNameSelector } from 'features/options/store/optionsSelectors';
const canInvokeSelector = createSelector( const floatingOptionsSelector = createSelector(
(state: RootState) => state.options, [(state: RootState) => state.options, activeTabNameSelector],
(options: OptionsState, activeTabName) => {
const {
shouldPinOptionsPanel,
shouldShowOptionsPanel,
shouldHoldOptionsPanelOpen,
} = options;
const shouldShowOptionsPanelButton =
!(
shouldShowOptionsPanel ||
(shouldHoldOptionsPanelOpen && !shouldPinOptionsPanel)
) && ['txt2img', 'img2img', 'unifiedCanvas'].includes(activeTabName);
(options: OptionsState) => {
const { shouldPinOptionsPanel, shouldShowOptionsPanel } = options;
return { return {
shouldPinOptionsPanel, shouldPinOptionsPanel,
shouldShowProcessButtons: shouldShowProcessButtons:
!shouldPinOptionsPanel || !shouldShowOptionsPanel, !shouldPinOptionsPanel || !shouldShowOptionsPanel,
shouldShowOptionsPanelButton,
}; };
}, },
{ memoizeOptions: { resultEqualityCheck: _.isEqual } } { memoizeOptions: { resultEqualityCheck: _.isEqual } }
@ -27,8 +39,11 @@ const canInvokeSelector = createSelector(
const FloatingOptionsPanelButtons = () => { const FloatingOptionsPanelButtons = () => {
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const { shouldShowProcessButtons, shouldPinOptionsPanel } = const {
useAppSelector(canInvokeSelector); shouldShowOptionsPanelButton,
shouldShowProcessButtons,
shouldPinOptionsPanel,
} = useAppSelector(floatingOptionsSelector);
const handleShowOptionsPanel = () => { const handleShowOptionsPanel = () => {
dispatch(setShouldShowOptionsPanel(true)); dispatch(setShouldShowOptionsPanel(true));
@ -37,7 +52,7 @@ const FloatingOptionsPanelButtons = () => {
} }
}; };
return ( return shouldShowOptionsPanelButton ? (
<div className="show-hide-button-options"> <div className="show-hide-button-options">
<IAIIconButton <IAIIconButton
tooltip="Show Options Panel (O)" tooltip="Show Options Panel (O)"
@ -54,7 +69,7 @@ const FloatingOptionsPanelButtons = () => {
</> </>
)} )}
</div> </div>
); ) : null;
}; };
export default FloatingOptionsPanelButtons; export default FloatingOptionsPanelButtons;