perf(ui): optimize useFeatureStatus

This commit is contained in:
psychedelicious 2024-04-15 22:25:08 +10:00
parent 7a92afc117
commit a24c9d0f7a
19 changed files with 36 additions and 45 deletions

View File

@ -9,7 +9,7 @@ import { useHotkeys } from 'react-hotkeys-hook';
export const useGlobalHotkeys = () => { export const useGlobalHotkeys = () => {
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const isModelManagerEnabled = useFeatureStatus('modelManager').isFeatureEnabled; const isModelManagerEnabled = useFeatureStatus('modelManager');
const { queueBack, isDisabled: isDisabledQueueBack, isLoading: isLoadingQueueBack } = useQueueBack(); const { queueBack, isDisabled: isDisabledQueueBack, isLoading: isLoadingQueueBack } = useQueueBack();
useHotkeys( useHotkeys(

View File

@ -32,7 +32,7 @@ const BoardContextMenu = ({ board, board_id, setBoardToDelete, children }: Props
const isSelectedForAutoAdd = useAppSelector(selectIsSelectedForAutoAdd); const isSelectedForAutoAdd = useAppSelector(selectIsSelectedForAutoAdd);
const boardName = useBoardName(board_id); const boardName = useBoardName(board_id);
const isBulkDownloadEnabled = useFeatureStatus('bulkDownload').isFeatureEnabled; const isBulkDownloadEnabled = useFeatureStatus('bulkDownload');
const [bulkDownload] = useBulkDownloadImagesMutation(); const [bulkDownload] = useBulkDownloadImagesMutation();

View File

@ -54,7 +54,7 @@ const CurrentImageButtons = () => {
const selection = useAppSelector((s) => s.gallery.selection); const selection = useAppSelector((s) => s.gallery.selection);
const shouldDisableToolbarButtons = useAppSelector(selectShouldDisableToolbarButtons); const shouldDisableToolbarButtons = useAppSelector(selectShouldDisableToolbarButtons);
const isUpscalingEnabled = useFeatureStatus('upscaling').isFeatureEnabled; const isUpscalingEnabled = useFeatureStatus('upscaling');
const isQueueMutationInProgress = useIsQueueMutationInProgress(); const isQueueMutationInProgress = useIsQueueMutationInProgress();
const toaster = useAppToaster(); const toaster = useAppToaster();
const { t } = useTranslation(); const { t } = useTranslation();

View File

@ -20,7 +20,7 @@ const MultipleSelectionMenuItems = () => {
const selection = useAppSelector((s) => s.gallery.selection); const selection = useAppSelector((s) => s.gallery.selection);
const customStarUi = useStore($customStarUI); const customStarUi = useStore($customStarUI);
const isBulkDownloadEnabled = useFeatureStatus('bulkDownload').isFeatureEnabled; const isBulkDownloadEnabled = useFeatureStatus('bulkDownload');
const [starImages] = useStarImagesMutation(); const [starImages] = useStarImagesMutation();
const [unstarImages] = useUnstarImagesMutation(); const [unstarImages] = useUnstarImagesMutation();

View File

@ -45,7 +45,7 @@ const SingleSelectionMenuItems = (props: SingleSelectionMenuItemsProps) => {
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const { t } = useTranslation(); const { t } = useTranslation();
const toaster = useAppToaster(); const toaster = useAppToaster();
const isCanvasEnabled = useFeatureStatus('unifiedCanvas').isFeatureEnabled; const isCanvasEnabled = useFeatureStatus('unifiedCanvas');
const customStarUi = useStore($customStarUI); const customStarUi = useStore($customStarUI);
const { downloadImage } = useDownloadImage(); const { downloadImage } = useDownloadImage();

View File

@ -18,7 +18,7 @@ export const useMultiselect = (imageDTO?: ImageDTO) => {
[imageDTO?.image_name] [imageDTO?.image_name]
); );
const isSelected = useAppSelector(selectIsSelected); const isSelected = useAppSelector(selectIsSelected);
const isMultiSelectEnabled = useFeatureStatus('multiselect').isFeatureEnabled; const isMultiSelectEnabled = useFeatureStatus('multiselect');
const handleClick = useCallback( const handleClick = useCallback(
(e: MouseEvent<HTMLDivElement>) => { (e: MouseEvent<HTMLDivElement>) => {

View File

@ -8,7 +8,7 @@ import ParamHrfStrength from './ParamHrfStrength';
import ParamHrfToggle from './ParamHrfToggle'; import ParamHrfToggle from './ParamHrfToggle';
export const HrfSettings = memo(() => { export const HrfSettings = memo(() => {
const isHRFFeatureEnabled = useFeatureStatus('hrf').isFeatureEnabled; const isHRFFeatureEnabled = useFeatureStatus('hrf');
const hrfEnabled = useAppSelector((s) => s.hrf.hrfEnabled); const hrfEnabled = useAppSelector((s) => s.hrf.hrfEnabled);
if (!isHRFFeatureEnabled) { if (!isHRFFeatureEnabled) {

View File

@ -10,7 +10,7 @@ const TOAST_ID = 'starterModels';
export const useStarterModelsToast = () => { export const useStarterModelsToast = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const isEnabled = useFeatureStatus('starterModels').isFeatureEnabled; const isEnabled = useFeatureStatus('starterModels');
const [didToast, setDidToast] = useState(false); const [didToast, setDidToast] = useState(false);
const [mainModels, { data }] = useMainModels(); const [mainModels, { data }] = useMainModels();
const toast = useToast(); const toast = useToast();

View File

@ -16,7 +16,7 @@ const props: ChakraProps = { w: 'unset' };
const InvocationNodeFooter = ({ nodeId }: Props) => { const InvocationNodeFooter = ({ nodeId }: Props) => {
const hasImageOutput = useHasImageOutput(nodeId); const hasImageOutput = useHasImageOutput(nodeId);
const isCacheEnabled = useFeatureStatus('invocationCache').isFeatureEnabled; const isCacheEnabled = useFeatureStatus('invocationCache');
return ( return (
<Flex <Flex
className={DRAG_HANDLE_CLASSNAME} className={DRAG_HANDLE_CLASSNAME}

View File

@ -5,8 +5,7 @@ import { useHasImageOutput } from './useHasImageOutput';
export const useWithFooter = (nodeId: string) => { export const useWithFooter = (nodeId: string) => {
const hasImageOutput = useHasImageOutput(nodeId); const hasImageOutput = useHasImageOutput(nodeId);
const isCacheEnabled = useFeatureStatus('invocationCache').isFeatureEnabled; const isCacheEnabled = useFeatureStatus('invocationCache');
const withFooter = useMemo(() => hasImageOutput || isCacheEnabled, [hasImageOutput, isCacheEnabled]); const withFooter = useMemo(() => hasImageOutput || isCacheEnabled, [hasImageOutput, isCacheEnabled]);
return withFooter; return withFooter;
}; };

View File

@ -27,8 +27,8 @@ export const QueueActionsMenuButton = memo(() => {
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const { t } = useTranslation(); const { t } = useTranslation();
const clearQueueDisclosure = useDisclosure(); const clearQueueDisclosure = useDisclosure();
const isPauseEnabled = useFeatureStatus('pauseQueue').isFeatureEnabled; const isPauseEnabled = useFeatureStatus('pauseQueue');
const isResumeEnabled = useFeatureStatus('resumeQueue').isFeatureEnabled; const isResumeEnabled = useFeatureStatus('resumeQueue');
const { queueSize } = useGetQueueStatusQuery(undefined, { const { queueSize } = useGetQueueStatusQuery(undefined, {
selectFromResult: (res) => ({ selectFromResult: (res) => ({
queueSize: res.data ? res.data.queue.pending + res.data.queue.in_progress : 0, queueSize: res.data ? res.data.queue.pending + res.data.queue.in_progress : 0,

View File

@ -9,7 +9,7 @@ import { InvokeQueueBackButton } from './InvokeQueueBackButton';
import { QueueActionsMenuButton } from './QueueActionsMenuButton'; import { QueueActionsMenuButton } from './QueueActionsMenuButton';
const QueueControls = () => { const QueueControls = () => {
const isPrependEnabled = useFeatureStatus('prependQueue').isFeatureEnabled; const isPrependEnabled = useFeatureStatus('prependQueue');
return ( return (
<Flex w="full" position="relative" borderRadius="base" gap={2} pt={2} flexDir="column"> <Flex w="full" position="relative" borderRadius="base" gap={2} pt={2} flexDir="column">
<ButtonGroup size="lg" isAttached={false}> <ButtonGroup size="lg" isAttached={false}>

View File

@ -8,7 +8,7 @@ import QueueStatus from './QueueStatus';
import QueueTabQueueControls from './QueueTabQueueControls'; import QueueTabQueueControls from './QueueTabQueueControls';
const QueueTabContent = () => { const QueueTabContent = () => {
const isInvocationCacheEnabled = useFeatureStatus('invocationCache').isFeatureEnabled; const isInvocationCacheEnabled = useFeatureStatus('invocationCache');
return ( return (
<Flex borderRadius="base" w="full" h="full" flexDir="column" gap={2}> <Flex borderRadius="base" w="full" h="full" flexDir="column" gap={2}>

View File

@ -8,8 +8,8 @@ import PruneQueueButton from './PruneQueueButton';
import ResumeProcessorButton from './ResumeProcessorButton'; import ResumeProcessorButton from './ResumeProcessorButton';
const QueueTabQueueControls = () => { const QueueTabQueueControls = () => {
const isPauseEnabled = useFeatureStatus('pauseQueue').isFeatureEnabled; const isPauseEnabled = useFeatureStatus('pauseQueue');
const isResumeEnabled = useFeatureStatus('resumeQueue').isFeatureEnabled; const isResumeEnabled = useFeatureStatus('resumeQueue');
return ( return (
<Flex layerStyle="first" borderRadius="base" p={2} gap={2}> <Flex layerStyle="first" borderRadius="base" p={2} gap={2}>
{isPauseEnabled || isResumeEnabled ? ( {isPauseEnabled || isResumeEnabled ? (

View File

@ -13,7 +13,7 @@ export const useQueueFront = () => {
const [_, { isLoading }] = useEnqueueBatchMutation({ const [_, { isLoading }] = useEnqueueBatchMutation({
fixedCacheKey: 'enqueueBatch', fixedCacheKey: 'enqueueBatch',
}); });
const prependEnabled = useFeatureStatus('prependQueue').isFeatureEnabled; const prependEnabled = useFeatureStatus('prependQueue');
const isDisabled = useMemo(() => { const isDisabled = useMemo(() => {
return !isReady || !prependEnabled; return !isReady || !prependEnabled;

View File

@ -62,7 +62,7 @@ const selector = createMemoizedSelector(selectControlAdaptersSlice, (controlAdap
export const ControlSettingsAccordion: React.FC = memo(() => { export const ControlSettingsAccordion: React.FC = memo(() => {
const { t } = useTranslation(); const { t } = useTranslation();
const { controlAdapterIds, badges } = useAppSelector(selector); const { controlAdapterIds, badges } = useAppSelector(selector);
const isControlNetDisabled = useFeatureStatus('controlNet').isFeatureDisabled; const isControlNetEnabled = useFeatureStatus('controlNet');
const { isOpen, onToggle } = useStandaloneAccordionToggle({ const { isOpen, onToggle } = useStandaloneAccordionToggle({
id: 'control-settings', id: 'control-settings',
defaultIsOpen: true, defaultIsOpen: true,
@ -71,7 +71,7 @@ export const ControlSettingsAccordion: React.FC = memo(() => {
const [addIPAdapter, isAddIPAdapterDisabled] = useAddControlAdapter('ip_adapter'); const [addIPAdapter, isAddIPAdapterDisabled] = useAddControlAdapter('ip_adapter');
const [addT2IAdapter, isAddT2IAdapterDisabled] = useAddControlAdapter('t2i_adapter'); const [addT2IAdapter, isAddT2IAdapterDisabled] = useAddControlAdapter('t2i_adapter');
if (isControlNetDisabled) { if (!isControlNetEnabled) {
return null; return null;
} }

View File

@ -40,7 +40,7 @@ export const SettingsLanguageSelect = memo(() => {
const { t } = useTranslation(); const { t } = useTranslation();
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const language = useAppSelector((s) => s.system.language); const language = useAppSelector((s) => s.system.language);
const isLocalizationEnabled = useFeatureStatus('localization').isFeatureEnabled; const isLocalizationEnabled = useFeatureStatus('localization');
const value = useMemo(() => options.find((o) => o.value === language), [language]); const value = useMemo(() => options.find((o) => o.value === language), [language]);

View File

@ -23,9 +23,9 @@ const SettingsMenu = () => {
const { isOpen, onOpen, onClose } = useDisclosure(); const { isOpen, onOpen, onClose } = useDisclosure();
useGlobalMenuClose(onClose); useGlobalMenuClose(onClose);
const isBugLinkEnabled = useFeatureStatus('bugLink').isFeatureEnabled; const isBugLinkEnabled = useFeatureStatus('bugLink');
const isDiscordLinkEnabled = useFeatureStatus('discordLink').isFeatureEnabled; const isDiscordLinkEnabled = useFeatureStatus('discordLink');
const isGithubLinkEnabled = useFeatureStatus('githubLink').isFeatureEnabled; const isGithubLinkEnabled = useFeatureStatus('githubLink');
return ( return (
<Menu isOpen={isOpen} onOpen={onOpen} onClose={onClose}> <Menu isOpen={isOpen} onOpen={onOpen} onClose={onClose}>

View File

@ -1,32 +1,24 @@
import { createSelector } from '@reduxjs/toolkit';
import { useAppSelector } from 'app/store/storeHooks'; import { useAppSelector } from 'app/store/storeHooks';
import type { AppFeature, SDFeature } from 'app/types/invokeai'; import type { AppFeature, SDFeature } from 'app/types/invokeai';
import { selectConfigSlice } from 'features/system/store/configSlice';
import type { InvokeTabName } from 'features/ui/store/tabMap'; import type { InvokeTabName } from 'features/ui/store/tabMap';
import { useMemo } from 'react'; import { useMemo } from 'react';
export const useFeatureStatus = (feature: AppFeature | SDFeature | InvokeTabName) => { export const useFeatureStatus = (feature: AppFeature | SDFeature | InvokeTabName) => {
const disabledTabs = useAppSelector((s) => s.config.disabledTabs); const selectIsFeatureEnabled = useMemo(
const disabledFeatures = useAppSelector((s) => s.config.disabledFeatures);
const disabledSDFeatures = useAppSelector((s) => s.config.disabledSDFeatures);
const isFeatureDisabled = useMemo(
() => () =>
disabledFeatures.includes(feature as AppFeature) || createSelector(selectConfigSlice, (config) => {
disabledSDFeatures.includes(feature as SDFeature) || return !(
disabledTabs.includes(feature as InvokeTabName), config.disabledFeatures.includes(feature as AppFeature) ||
[disabledFeatures, disabledSDFeatures, disabledTabs, feature] config.disabledSDFeatures.includes(feature as SDFeature) ||
config.disabledTabs.includes(feature as InvokeTabName)
);
}),
[feature]
); );
const isFeatureEnabled = useMemo( const isFeatureEnabled = useAppSelector(selectIsFeatureEnabled);
() =>
!(
disabledFeatures.includes(feature as AppFeature) ||
disabledSDFeatures.includes(feature as SDFeature) ||
disabledTabs.includes(feature as InvokeTabName)
),
[disabledFeatures, disabledSDFeatures, disabledTabs, feature]
);
return { isFeatureDisabled, isFeatureEnabled }; return isFeatureEnabled;
}; };