mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
feat(ui): rerender mitigation sweep
This commit is contained in:
parent
5d8728c7ef
commit
ca1cc0e2c2
@ -28,11 +28,13 @@ import { useGlobalHotkeys } from 'common/hooks/useGlobalHotkeys';
|
||||
import { configChanged } from 'features/system/store/configSlice';
|
||||
import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
|
||||
|
||||
const DEFAULT_CONFIG = {};
|
||||
|
||||
interface Props extends PropsWithChildren {
|
||||
config?: PartialAppConfig;
|
||||
}
|
||||
|
||||
const App = ({ config = {}, children }: Props) => {
|
||||
const App = ({ config = DEFAULT_CONFIG, children }: Props) => {
|
||||
useToastWatcher();
|
||||
useGlobalHotkeys();
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { Flex, Image, Spinner } from '@chakra-ui/react';
|
||||
import InvokeAILogoImage from 'assets/images/logo.png';
|
||||
import { memo } from 'react';
|
||||
|
||||
// This component loads before the theme so we cannot use theme tokens here
|
||||
|
||||
@ -29,4 +30,4 @@ const Loading = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default Loading;
|
||||
export default memo(Loading);
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { RootState } from 'app/store/store';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { useCallback } from 'react';
|
||||
import { OpenAPI } from 'services/api';
|
||||
|
||||
export const getUrlAlt = (url: string, shouldTransformUrls: boolean) => {
|
||||
@ -15,14 +16,19 @@ export const useGetUrl = () => {
|
||||
(state: RootState) => state.config.shouldTransformUrls
|
||||
);
|
||||
|
||||
return {
|
||||
shouldTransformUrls,
|
||||
getUrl: (url?: string) => {
|
||||
const getUrl = useCallback(
|
||||
(url?: string) => {
|
||||
if (OpenAPI.BASE && shouldTransformUrls) {
|
||||
return [OpenAPI.BASE, url].join('/');
|
||||
}
|
||||
|
||||
return url;
|
||||
},
|
||||
[shouldTransformUrls]
|
||||
);
|
||||
|
||||
return {
|
||||
shouldTransformUrls,
|
||||
getUrl,
|
||||
};
|
||||
};
|
||||
|
@ -163,16 +163,16 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => {
|
||||
const { t } = useTranslation();
|
||||
const setBothPrompts = useSetBothPrompts();
|
||||
|
||||
const handleClickUseAsInitialImage = () => {
|
||||
const handleClickUseAsInitialImage = useCallback(() => {
|
||||
if (!image) return;
|
||||
if (isLightboxOpen) dispatch(setIsLightboxOpen(false));
|
||||
dispatch(initialImageSelected(image.name));
|
||||
// dispatch(setInitialImage(currentImage));
|
||||
|
||||
// dispatch(setActiveTab('img2img'));
|
||||
};
|
||||
}, [dispatch, image, isLightboxOpen]);
|
||||
|
||||
const handleCopyImage = async () => {
|
||||
const handleCopyImage = useCallback(async () => {
|
||||
if (!image?.url) {
|
||||
return;
|
||||
}
|
||||
@ -194,9 +194,9 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => {
|
||||
duration: 2500,
|
||||
isClosable: true,
|
||||
});
|
||||
};
|
||||
}, [getUrl, t, image?.url, toast]);
|
||||
|
||||
const handleCopyImageLink = () => {
|
||||
const handleCopyImageLink = useCallback(() => {
|
||||
const url = image
|
||||
? shouldTransformUrls
|
||||
? getUrl(image.url)
|
||||
@ -215,7 +215,7 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => {
|
||||
isClosable: true,
|
||||
});
|
||||
});
|
||||
};
|
||||
}, [toast, shouldTransformUrls, getUrl, t, image]);
|
||||
|
||||
useHotkeys(
|
||||
'shift+i',
|
||||
@ -241,11 +241,11 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => {
|
||||
[image]
|
||||
);
|
||||
|
||||
const handlePreviewVisibility = () => {
|
||||
const handlePreviewVisibility = useCallback(() => {
|
||||
dispatch(setShouldHidePreview(!shouldHidePreview));
|
||||
};
|
||||
}, [dispatch, shouldHidePreview]);
|
||||
|
||||
const handleClickUseAllParameters = () => {
|
||||
const handleClickUseAllParameters = useCallback(() => {
|
||||
if (!image) return;
|
||||
// selectedImage.metadata &&
|
||||
// dispatch(setAllParameters(selectedImage.metadata));
|
||||
@ -254,7 +254,7 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => {
|
||||
// } else if (selectedImage.metadata?.image.type === 'txt2img') {
|
||||
// dispatch(setActiveTab('txt2img'));
|
||||
// }
|
||||
};
|
||||
}, [image]);
|
||||
|
||||
useHotkeys(
|
||||
'a',
|
||||
@ -338,9 +338,9 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => {
|
||||
[image]
|
||||
);
|
||||
|
||||
const handleClickUpscale = () => {
|
||||
const handleClickUpscale = useCallback(() => {
|
||||
// selectedImage && dispatch(runESRGAN(selectedImage));
|
||||
};
|
||||
}, []);
|
||||
|
||||
useHotkeys(
|
||||
'Shift+U',
|
||||
@ -369,9 +369,9 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => {
|
||||
]
|
||||
);
|
||||
|
||||
const handleClickFixFaces = () => {
|
||||
const handleClickFixFaces = useCallback(() => {
|
||||
// selectedImage && dispatch(runFacetool(selectedImage));
|
||||
};
|
||||
}, []);
|
||||
|
||||
useHotkeys(
|
||||
'Shift+R',
|
||||
@ -401,10 +401,12 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => {
|
||||
]
|
||||
);
|
||||
|
||||
const handleClickShowImageDetails = () =>
|
||||
dispatch(setShouldShowImageDetails(!shouldShowImageDetails));
|
||||
const handleClickShowImageDetails = useCallback(
|
||||
() => dispatch(setShouldShowImageDetails(!shouldShowImageDetails)),
|
||||
[dispatch, shouldShowImageDetails]
|
||||
);
|
||||
|
||||
const handleSendToCanvas = () => {
|
||||
const handleSendToCanvas = useCallback(() => {
|
||||
if (!image) return;
|
||||
if (isLightboxOpen) dispatch(setIsLightboxOpen(false));
|
||||
|
||||
@ -421,7 +423,7 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => {
|
||||
duration: 2500,
|
||||
isClosable: true,
|
||||
});
|
||||
};
|
||||
}, [image, isLightboxOpen, dispatch, activeTabName, toast, t]);
|
||||
|
||||
useHotkeys(
|
||||
'i',
|
||||
@ -440,19 +442,19 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => {
|
||||
[image, shouldShowImageDetails]
|
||||
);
|
||||
|
||||
const handleInitiateDelete = () => {
|
||||
const handleDelete = useCallback(() => {
|
||||
if (canDeleteImage && image) {
|
||||
dispatch(imageDeleted({ imageType: image.type, imageName: image.name }));
|
||||
}
|
||||
}, [image, canDeleteImage, dispatch]);
|
||||
|
||||
const handleInitiateDelete = useCallback(() => {
|
||||
if (shouldConfirmOnDelete) {
|
||||
onDeleteDialogOpen();
|
||||
} else {
|
||||
handleDelete();
|
||||
}
|
||||
};
|
||||
|
||||
const handleDelete = () => {
|
||||
if (canDeleteImage && image) {
|
||||
dispatch(imageDeleted({ imageType: image.type, imageName: image.name }));
|
||||
}
|
||||
};
|
||||
}, [shouldConfirmOnDelete, onDeleteDialogOpen, handleDelete]);
|
||||
|
||||
useHotkeys('delete', handleInitiateDelete, [
|
||||
image,
|
||||
@ -461,9 +463,9 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => {
|
||||
isProcessing,
|
||||
]);
|
||||
|
||||
const handleLightBox = () => {
|
||||
const handleLightBox = useCallback(() => {
|
||||
dispatch(setIsLightboxOpen(!isLightboxOpen));
|
||||
};
|
||||
}, [dispatch, isLightboxOpen]);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -11,6 +11,7 @@ import CurrentImageFallback from './CurrentImageFallback';
|
||||
import ImageMetadataViewer from './ImageMetaDataViewer/ImageMetadataViewer';
|
||||
import NextPrevImageButtons from './NextPrevImageButtons';
|
||||
import CurrentImageHidden from './CurrentImageHidden';
|
||||
import { memo } from 'react';
|
||||
|
||||
export const imagesSelector = createSelector(
|
||||
[uiSelector, selectedImageSelector, systemSelector],
|
||||
@ -50,7 +51,7 @@ export const imagesSelector = createSelector(
|
||||
}
|
||||
);
|
||||
|
||||
export default function CurrentImagePreview() {
|
||||
const CurrentImagePreview = () => {
|
||||
const { shouldShowImageDetails, imageToDisplay, shouldHidePreview } =
|
||||
useAppSelector(imagesSelector);
|
||||
const { getUrl } = useGetUrl();
|
||||
@ -115,4 +116,6 @@ export default function CurrentImagePreview() {
|
||||
)}
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default memo(CurrentImagePreview);
|
||||
|
@ -28,6 +28,7 @@ import { requestCanvasRescale } from 'features/canvas/store/thunks/requestCanvas
|
||||
import { lightboxSelector } from 'features/lightbox/store/lightboxSelectors';
|
||||
import useResolution from 'common/hooks/useResolution';
|
||||
import { Flex } from '@chakra-ui/react';
|
||||
import { memo } from 'react';
|
||||
|
||||
const GALLERY_TAB_WIDTHS: Record<
|
||||
InvokeTabName,
|
||||
@ -72,7 +73,7 @@ const galleryPanelSelector = createSelector(
|
||||
}
|
||||
);
|
||||
|
||||
export default function ImageGalleryPanel() {
|
||||
export const ImageGalleryPanel = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
const {
|
||||
shouldPinGallery,
|
||||
@ -232,4 +233,6 @@ export default function ImageGalleryPanel() {
|
||||
};
|
||||
|
||||
return renderImageGallery();
|
||||
}
|
||||
};
|
||||
|
||||
export default memo(ImageGalleryPanel);
|
||||
|
@ -6,14 +6,12 @@ import IAIIconButton, {
|
||||
import { systemSelector } from 'features/system/store/systemSelectors';
|
||||
import {
|
||||
SystemState,
|
||||
setCancelAfter,
|
||||
setCancelType,
|
||||
cancelScheduled,
|
||||
cancelTypeChanged,
|
||||
CancelType,
|
||||
} from 'features/system/store/systemSlice';
|
||||
import { isEqual } from 'lodash-es';
|
||||
import { useEffect, useCallback, memo } from 'react';
|
||||
import { useCallback, memo } from 'react';
|
||||
import {
|
||||
ButtonSpinner,
|
||||
ButtonGroup,
|
||||
@ -27,16 +25,9 @@ import {
|
||||
|
||||
import { useHotkeys } from 'react-hotkeys-hook';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
MdArrowDropDown,
|
||||
MdArrowDropUp,
|
||||
MdCancel,
|
||||
MdCancelScheduleSend,
|
||||
} from 'react-icons/md';
|
||||
import { MdCancel, MdCancelScheduleSend } from 'react-icons/md';
|
||||
|
||||
import IAISimpleMenu from 'common/components/IAISimpleMenu';
|
||||
import { sessionCanceled } from 'services/thunks/session';
|
||||
import { FaChevronDown } from 'react-icons/fa';
|
||||
import { BiChevronDown } from 'react-icons/bi';
|
||||
|
||||
const cancelButtonSelector = createSelector(
|
||||
@ -48,8 +39,6 @@ const cancelButtonSelector = createSelector(
|
||||
isCancelable: system.isCancelable,
|
||||
currentIteration: system.currentIteration,
|
||||
totalIterations: system.totalIterations,
|
||||
// cancelType: system.cancelOptions.cancelType,
|
||||
// cancelAfter: system.cancelOptions.cancelAfter,
|
||||
sessionId: system.sessionId,
|
||||
cancelType: system.cancelType,
|
||||
isCancelScheduled: system.isCancelScheduled,
|
||||
@ -75,11 +64,8 @@ const CancelButton = (
|
||||
isProcessing,
|
||||
isConnected,
|
||||
isCancelable,
|
||||
currentIteration,
|
||||
totalIterations,
|
||||
cancelType,
|
||||
isCancelScheduled,
|
||||
// cancelAfter,
|
||||
sessionId,
|
||||
} = useAppSelector(cancelButtonSelector);
|
||||
|
||||
@ -105,7 +91,6 @@ const CancelButton = (
|
||||
},
|
||||
[dispatch]
|
||||
);
|
||||
// const isCancelScheduled = cancelAfter === null ? false : true;
|
||||
|
||||
useHotkeys(
|
||||
'shift+x',
|
||||
@ -117,23 +102,6 @@ const CancelButton = (
|
||||
[isConnected, isProcessing, isCancelable]
|
||||
);
|
||||
|
||||
// useEffect(() => {
|
||||
// if (cancelAfter !== null && cancelAfter < currentIteration) {
|
||||
// handleClickCancel();
|
||||
// }
|
||||
// }, [cancelAfter, currentIteration, handleClickCancel]);
|
||||
|
||||
// const cancelMenuItems = [
|
||||
// {
|
||||
// item: t('parameters.cancel.immediate'),
|
||||
// onClick: () => dispatch(cancelTypeChanged('immediate')),
|
||||
// },
|
||||
// {
|
||||
// item: t('parameters.cancel.schedule'),
|
||||
// onClick: () => dispatch(cancelTypeChanged('scheduled')),
|
||||
// },
|
||||
// ];
|
||||
|
||||
return (
|
||||
<ButtonGroup isAttached width={btnGroupWidth}>
|
||||
{cancelType === 'immediate' ? (
|
||||
|
@ -4,23 +4,27 @@ import * as InvokeAI from 'app/types/invokeai';
|
||||
import promptToString from 'common/util/promptToString';
|
||||
import { useAppDispatch } from 'app/store/storeHooks';
|
||||
import { setNegativePrompt, setPrompt } from '../store/generationSlice';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
// TECHDEBT: We have two metadata prompt formats and need to handle recalling either of them.
|
||||
// This hook provides a function to do that.
|
||||
const useSetBothPrompts = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
return (inputPrompt: InvokeAI.Prompt) => {
|
||||
const promptString =
|
||||
typeof inputPrompt === 'string'
|
||||
? inputPrompt
|
||||
: promptToString(inputPrompt);
|
||||
return useCallback(
|
||||
(inputPrompt: InvokeAI.Prompt) => {
|
||||
const promptString =
|
||||
typeof inputPrompt === 'string'
|
||||
? inputPrompt
|
||||
: promptToString(inputPrompt);
|
||||
|
||||
const [prompt, negativePrompt] = getPromptAndNegative(promptString);
|
||||
const [prompt, negativePrompt] = getPromptAndNegative(promptString);
|
||||
|
||||
dispatch(setPrompt(prompt));
|
||||
dispatch(setNegativePrompt(negativePrompt));
|
||||
};
|
||||
dispatch(setPrompt(prompt));
|
||||
dispatch(setNegativePrompt(negativePrompt));
|
||||
},
|
||||
[dispatch]
|
||||
);
|
||||
};
|
||||
|
||||
export default useSetBothPrompts;
|
||||
|
@ -9,7 +9,7 @@ import {
|
||||
} from 'features/system/store/systemSlice';
|
||||
import { isEqual } from 'lodash-es';
|
||||
import { Resizable } from 're-resizable';
|
||||
import { useLayoutEffect, useRef, useState } from 'react';
|
||||
import { memo, useLayoutEffect, useRef, useState } from 'react';
|
||||
import { useHotkeys } from 'react-hotkeys-hook';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { FaAngleDoubleDown, FaCode, FaMinus } from 'react-icons/fa';
|
||||
@ -194,4 +194,4 @@ const Console = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default Console;
|
||||
export default memo(Console);
|
||||
|
@ -3,6 +3,7 @@ import { createSelector } from '@reduxjs/toolkit';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { SystemState } from 'features/system/store/systemSlice';
|
||||
import { isEqual } from 'lodash-es';
|
||||
import { memo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { PROGRESS_BAR_THICKNESS } from 'theme/util/constants';
|
||||
import { systemSelector } from '../store/systemSelectors';
|
||||
@ -40,4 +41,4 @@ const ProgressBar = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default ProgressBar;
|
||||
export default memo(ProgressBar);
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Flex, Grid } from '@chakra-ui/react';
|
||||
import { useState } from 'react';
|
||||
import { memo, useState } from 'react';
|
||||
import ModelSelect from './ModelSelect';
|
||||
import StatusIndicator from './StatusIndicator';
|
||||
|
||||
@ -65,5 +65,4 @@ const SiteHeader = () => {
|
||||
);
|
||||
};
|
||||
|
||||
SiteHeader.displayName = 'SiteHeader';
|
||||
export default SiteHeader;
|
||||
export default memo(SiteHeader);
|
||||
|
@ -17,7 +17,7 @@ const itemsToDenylist: (keyof SystemState)[] = [
|
||||
'totalSteps',
|
||||
'openModel',
|
||||
'isCancelScheduled',
|
||||
'sessionId',
|
||||
// 'sessionId',
|
||||
'progressImage',
|
||||
'wereModelsReceived',
|
||||
'wasSchemaParsed',
|
||||
|
@ -89,18 +89,6 @@ export interface SystemState
|
||||
* Array of node IDs that we want to handle when events received
|
||||
*/
|
||||
subscribedNodeIds: string[];
|
||||
// /**
|
||||
// * Whether or not URLs should be transformed to use a different host
|
||||
// */
|
||||
// shouldTransformUrls: boolean;
|
||||
// /**
|
||||
// * Array of disabled tabs
|
||||
// */
|
||||
// disabledTabs: InvokeTabName[];
|
||||
// /**
|
||||
// * Array of disabled features
|
||||
// */
|
||||
// disabledFeatures: InvokeAI.AppFeature[];
|
||||
/**
|
||||
* Whether or not the available models were received
|
||||
*/
|
||||
@ -358,27 +346,6 @@ export const systemSlice = createSlice({
|
||||
subscribedNodeIdsSet: (state, action: PayloadAction<string[]>) => {
|
||||
state.subscribedNodeIds = action.payload;
|
||||
},
|
||||
// /**
|
||||
// * `shouldTransformUrls` was changed
|
||||
// */
|
||||
// shouldTransformUrlsChanged: (state, action: PayloadAction<boolean>) => {
|
||||
// state.shouldTransformUrls = action.payload;
|
||||
// },
|
||||
// /**
|
||||
// * `disabledTabs` was changed
|
||||
// */
|
||||
// disabledTabsChanged: (state, action: PayloadAction<InvokeTabName[]>) => {
|
||||
// state.disabledTabs = action.payload;
|
||||
// },
|
||||
// /**
|
||||
// * `disabledFeatures` was changed
|
||||
// */
|
||||
// disabledFeaturesChanged: (
|
||||
// state,
|
||||
// action: PayloadAction<InvokeAI.AppFeature[]>
|
||||
// ) => {
|
||||
// state.disabledFeatures = action.payload;
|
||||
// },
|
||||
},
|
||||
extraReducers(builder) {
|
||||
/**
|
||||
@ -386,6 +353,7 @@ export const systemSlice = createSlice({
|
||||
*/
|
||||
builder.addCase(socketSubscribed, (state, action) => {
|
||||
state.sessionId = action.payload.sessionId;
|
||||
console.log(`Subscribed to session ${action.payload.sessionId}`);
|
||||
});
|
||||
|
||||
/**
|
||||
@ -594,9 +562,6 @@ export const {
|
||||
scheduledCancelAborted,
|
||||
cancelTypeChanged,
|
||||
subscribedNodeIdsSet,
|
||||
// shouldTransformUrlsChanged,
|
||||
// disabledTabsChanged,
|
||||
// disabledFeaturesChanged,
|
||||
} = systemSlice.actions;
|
||||
|
||||
export default systemSlice.reducer;
|
||||
|
@ -7,6 +7,7 @@ import { setShouldShowGallery } from 'features/ui/store/uiSlice';
|
||||
import { isEqual } from 'lodash-es';
|
||||
import { MdPhotoLibrary } from 'react-icons/md';
|
||||
import { activeTabNameSelector, uiSelector } from '../store/uiSelectors';
|
||||
import { memo } from 'react';
|
||||
|
||||
const floatingGalleryButtonSelector = createSelector(
|
||||
[activeTabNameSelector, uiSelector],
|
||||
@ -58,4 +59,4 @@ const FloatingGalleryButton = () => {
|
||||
) : null;
|
||||
};
|
||||
|
||||
export default FloatingGalleryButton;
|
||||
export default memo(FloatingGalleryButton);
|
||||
|
@ -11,6 +11,7 @@ import {
|
||||
} from 'features/ui/store/uiSelectors';
|
||||
import { setShouldShowParametersPanel } from 'features/ui/store/uiSlice';
|
||||
import { isEqual } from 'lodash-es';
|
||||
import { memo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { FaSlidersH } from 'react-icons/fa';
|
||||
@ -94,4 +95,4 @@ const FloatingParametersPanelButtons = () => {
|
||||
) : null;
|
||||
};
|
||||
|
||||
export default FloatingParametersPanelButtons;
|
||||
export default memo(FloatingParametersPanelButtons);
|
||||
|
@ -14,7 +14,7 @@ import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { setIsLightboxOpen } from 'features/lightbox/store/lightboxSlice';
|
||||
import { InvokeTabName } from 'features/ui/store/tabMap';
|
||||
import { setActiveTab, togglePanels } from 'features/ui/store/uiSlice';
|
||||
import { ReactNode, useMemo } from 'react';
|
||||
import { memo, ReactNode, useMemo } from 'react';
|
||||
import { useHotkeys } from 'react-hotkeys-hook';
|
||||
import { MdDeviceHub, MdGridOn } from 'react-icons/md';
|
||||
import { activeTabIndexSelector } from '../store/uiSelectors';
|
||||
@ -24,10 +24,10 @@ import { ResourceKey } from 'i18next';
|
||||
import { requestCanvasRescale } from 'features/canvas/store/thunks/requestCanvasScale';
|
||||
import NodeEditor from 'features/nodes/components/NodeEditor';
|
||||
import GenerateWorkspace from './tabs/Generate/GenerateWorkspace';
|
||||
import { FaImage } from 'react-icons/fa';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { BsLightningChargeFill, BsLightningFill } from 'react-icons/bs';
|
||||
import { BsLightningChargeFill } from 'react-icons/bs';
|
||||
import { configSelector } from 'features/system/store/configSelectors';
|
||||
import { isEqual } from 'lodash';
|
||||
|
||||
export interface InvokeTabInfo {
|
||||
id: InvokeTabName;
|
||||
@ -35,10 +35,6 @@ export interface InvokeTabInfo {
|
||||
workarea: ReactNode;
|
||||
}
|
||||
|
||||
const tabIconStyles: ChakraProps['sx'] = {
|
||||
boxSize: 6,
|
||||
};
|
||||
|
||||
const tabs: InvokeTabInfo[] = [
|
||||
{
|
||||
id: 'generate',
|
||||
@ -57,13 +53,19 @@ const tabs: InvokeTabInfo[] = [
|
||||
},
|
||||
];
|
||||
|
||||
const enabledTabsSelector = createSelector(configSelector, (config) => {
|
||||
const { disabledTabs } = config;
|
||||
const enabledTabsSelector = createSelector(
|
||||
configSelector,
|
||||
(config) => {
|
||||
const { disabledTabs } = config;
|
||||
|
||||
return tabs.filter((tab) => !disabledTabs.includes(tab.id));
|
||||
});
|
||||
return tabs.filter((tab) => !disabledTabs.includes(tab.id));
|
||||
},
|
||||
{
|
||||
memoizeOptions: { resultEqualityCheck: isEqual },
|
||||
}
|
||||
);
|
||||
|
||||
export default function InvokeTabs() {
|
||||
const InvokeTabs = () => {
|
||||
const activeTab = useAppSelector(activeTabIndexSelector);
|
||||
const enabledTabs = useAppSelector(enabledTabsSelector);
|
||||
const isLightBoxOpen = useAppSelector(
|
||||
@ -160,4 +162,6 @@ export default function InvokeTabs() {
|
||||
<TabPanels>{tabPanels}</TabPanels>
|
||||
</Tabs>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default memo(InvokeTabs);
|
||||
|
Loading…
Reference in New Issue
Block a user