feat(ui): memoize all components

This commit is contained in:
psychedelicious 2023-08-21 11:26:16 +10:00
parent 5c305b1eeb
commit fbff22c94b
84 changed files with 486 additions and 440 deletions

View File

@ -1,7 +1,7 @@
import { Flex, Heading, Link, Text, useToast } from '@chakra-ui/react'; import { Flex, Heading, Link, Text, useToast } from '@chakra-ui/react';
import IAIButton from 'common/components/IAIButton'; import IAIButton from 'common/components/IAIButton';
import newGithubIssueUrl from 'new-github-issue-url'; import newGithubIssueUrl from 'new-github-issue-url';
import { useCallback, useMemo } from 'react'; import { memo, useCallback, useMemo } from 'react';
import { FaCopy, FaExternalLinkAlt } from 'react-icons/fa'; import { FaCopy, FaExternalLinkAlt } from 'react-icons/fa';
import { FaArrowRotateLeft } from 'react-icons/fa6'; import { FaArrowRotateLeft } from 'react-icons/fa6';
import { serializeError } from 'serialize-error'; import { serializeError } from 'serialize-error';
@ -94,4 +94,4 @@ const AppErrorBoundaryFallback = ({ error, resetErrorBoundary }: Props) => {
); );
}; };
export default AppErrorBoundaryFallback; export default memo(AppErrorBoundaryFallback);

View File

@ -3,7 +3,7 @@ import {
createLocalStorageManager, createLocalStorageManager,
extendTheme, extendTheme,
} from '@chakra-ui/react'; } from '@chakra-ui/react';
import { ReactNode, useEffect, useMemo } from 'react'; import { ReactNode, memo, useEffect, useMemo } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { theme as invokeAITheme } from 'theme/theme'; import { theme as invokeAITheme } from 'theme/theme';
@ -46,4 +46,4 @@ function ThemeLocaleProvider({ children }: ThemeLocaleProviderProps) {
); );
} }
export default ThemeLocaleProvider; export default memo(ThemeLocaleProvider);

View File

@ -3,7 +3,7 @@ import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { toastQueueSelector } from 'features/system/store/systemSelectors'; import { toastQueueSelector } from 'features/system/store/systemSelectors';
import { addToast, clearToastQueue } from 'features/system/store/systemSlice'; import { addToast, clearToastQueue } from 'features/system/store/systemSlice';
import { MakeToastArg, makeToast } from 'features/system/util/makeToast'; import { MakeToastArg, makeToast } from 'features/system/util/makeToast';
import { useCallback, useEffect } from 'react'; import { memo, useCallback, useEffect } from 'react';
/** /**
* Logical component. Watches the toast queue and makes toasts when the queue is not empty. * Logical component. Watches the toast queue and makes toasts when the queue is not empty.
@ -44,4 +44,4 @@ export const useAppToaster = () => {
return toaster; return toaster;
}; };
export default Toaster; export default memo(Toaster);

View File

@ -1,4 +1,5 @@
import { Box, Flex, Icon } from '@chakra-ui/react'; import { Box, Flex, Icon } from '@chakra-ui/react';
import { memo } from 'react';
import { FaExclamation } from 'react-icons/fa'; import { FaExclamation } from 'react-icons/fa';
const IAIErrorLoadingImageFallback = () => { const IAIErrorLoadingImageFallback = () => {
@ -39,4 +40,4 @@ const IAIErrorLoadingImageFallback = () => {
); );
}; };
export default IAIErrorLoadingImageFallback; export default memo(IAIErrorLoadingImageFallback);

View File

@ -1,4 +1,5 @@
import { Box, Skeleton } from '@chakra-ui/react'; import { Box, Skeleton } from '@chakra-ui/react';
import { memo } from 'react';
const IAIFillSkeleton = () => { const IAIFillSkeleton = () => {
return ( return (
@ -27,4 +28,4 @@ const IAIFillSkeleton = () => {
); );
}; };
export default IAIFillSkeleton; export default memo(IAIFillSkeleton);

View File

@ -1,4 +1,5 @@
import { Badge, Flex } from '@chakra-ui/react'; import { Badge, Flex } from '@chakra-ui/react';
import { memo } from 'react';
import { ImageDTO } from 'services/api/types'; import { ImageDTO } from 'services/api/types';
type ImageMetadataOverlayProps = { type ImageMetadataOverlayProps = {
@ -26,4 +27,4 @@ const ImageMetadataOverlay = ({ imageDTO }: ImageMetadataOverlayProps) => {
); );
}; };
export default ImageMetadataOverlay; export default memo(ImageMetadataOverlay);

View File

@ -1,4 +1,5 @@
import { Box, Flex, Heading } from '@chakra-ui/react'; import { Box, Flex, Heading } from '@chakra-ui/react';
import { memo } from 'react';
import { useHotkeys } from 'react-hotkeys-hook'; import { useHotkeys } from 'react-hotkeys-hook';
type ImageUploadOverlayProps = { type ImageUploadOverlayProps = {
@ -87,4 +88,4 @@ const ImageUploadOverlay = (props: ImageUploadOverlayProps) => {
</Box> </Box>
); );
}; };
export default ImageUploadOverlay; export default memo(ImageUploadOverlay);

View File

@ -1,4 +1,5 @@
import { Flex, Icon } from '@chakra-ui/react'; import { Flex, Icon } from '@chakra-ui/react';
import { memo } from 'react';
import { FaImage } from 'react-icons/fa'; import { FaImage } from 'react-icons/fa';
const SelectImagePlaceholder = () => { const SelectImagePlaceholder = () => {
@ -19,4 +20,4 @@ const SelectImagePlaceholder = () => {
); );
}; };
export default SelectImagePlaceholder; export default memo(SelectImagePlaceholder);

View File

@ -1,4 +1,5 @@
import { Box } from '@chakra-ui/react'; import { Box } from '@chakra-ui/react';
import { memo } from 'react';
type Props = { type Props = {
isSelected: boolean; isSelected: boolean;
@ -40,4 +41,4 @@ const SelectionOverlay = ({ isSelected, isHovered }: Props) => {
); );
}; };
export default SelectionOverlay; export default memo(SelectionOverlay);

View File

@ -5,6 +5,7 @@ import { clearCanvasHistory } from 'features/canvas/store/canvasSlice';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { FaTrash } from 'react-icons/fa'; import { FaTrash } from 'react-icons/fa';
import { isStagingSelector } from '../store/canvasSelectors'; import { isStagingSelector } from '../store/canvasSelectors';
import { memo } from 'react';
const ClearCanvasHistoryButtonModal = () => { const ClearCanvasHistoryButtonModal = () => {
const isStaging = useAppSelector(isStagingSelector); const isStaging = useAppSelector(isStagingSelector);
@ -28,4 +29,4 @@ const ClearCanvasHistoryButtonModal = () => {
</IAIAlertDialog> </IAIAlertDialog>
); );
}; };
export default ClearCanvasHistoryButtonModal; export default memo(ClearCanvasHistoryButtonModal);

View File

@ -9,7 +9,7 @@ import {
import Konva from 'konva'; import Konva from 'konva';
import { KonvaEventObject } from 'konva/lib/Node'; import { KonvaEventObject } from 'konva/lib/Node';
import { Vector2d } from 'konva/lib/types'; import { Vector2d } from 'konva/lib/types';
import { useCallback, useRef } from 'react'; import { memo, useCallback, useRef } from 'react';
import { Layer, Stage } from 'react-konva'; import { Layer, Stage } from 'react-konva';
import useCanvasDragMove from '../hooks/useCanvasDragMove'; import useCanvasDragMove from '../hooks/useCanvasDragMove';
import useCanvasHotkeys from '../hooks/useCanvasHotkeys'; import useCanvasHotkeys from '../hooks/useCanvasHotkeys';
@ -220,4 +220,4 @@ const IAICanvas = () => {
); );
}; };
export default IAICanvas; export default memo(IAICanvas);

View File

@ -4,6 +4,7 @@ import { isEqual } from 'lodash-es';
import { Group, Rect } from 'react-konva'; import { Group, Rect } from 'react-konva';
import { canvasSelector } from '../store/canvasSelectors'; import { canvasSelector } from '../store/canvasSelectors';
import { memo } from 'react';
const selector = createSelector( const selector = createSelector(
canvasSelector, canvasSelector,
@ -67,4 +68,4 @@ const IAICanvasBoundingBoxOverlay = () => {
); );
}; };
export default IAICanvasBoundingBoxOverlay; export default memo(IAICanvasBoundingBoxOverlay);

View File

@ -6,7 +6,7 @@ import { useAppSelector } from 'app/store/storeHooks';
import { canvasSelector } from 'features/canvas/store/canvasSelectors'; import { canvasSelector } from 'features/canvas/store/canvasSelectors';
import { isEqual, range } from 'lodash-es'; import { isEqual, range } from 'lodash-es';
import { ReactNode, useCallback, useLayoutEffect, useState } from 'react'; import { ReactNode, memo, useCallback, useLayoutEffect, useState } from 'react';
import { Group, Line as KonvaLine } from 'react-konva'; import { Group, Line as KonvaLine } from 'react-konva';
const selector = createSelector( const selector = createSelector(
@ -117,4 +117,4 @@ const IAICanvasGrid = () => {
return <Group>{gridLines}</Group>; return <Group>{gridLines}</Group>;
}; };
export default IAICanvasGrid; export default memo(IAICanvasGrid);

View File

@ -4,6 +4,7 @@ import { useGetImageDTOQuery } from 'services/api/endpoints/images';
import useImage from 'use-image'; import useImage from 'use-image';
import { CanvasImage } from '../store/canvasTypes'; import { CanvasImage } from '../store/canvasTypes';
import { $authToken } from 'services/api/client'; import { $authToken } from 'services/api/client';
import { memo } from 'react';
type IAICanvasImageProps = { type IAICanvasImageProps = {
canvasImage: CanvasImage; canvasImage: CanvasImage;
@ -25,4 +26,4 @@ const IAICanvasImage = (props: IAICanvasImageProps) => {
return <Image x={x} y={y} image={image} listening={false} />; return <Image x={x} y={y} image={image} listening={false} />;
}; };
export default IAICanvasImage; export default memo(IAICanvasImage);

View File

@ -4,7 +4,7 @@ import { systemSelector } from 'features/system/store/systemSelectors';
import { ImageConfig } from 'konva/lib/shapes/Image'; import { ImageConfig } from 'konva/lib/shapes/Image';
import { isEqual } from 'lodash-es'; import { isEqual } from 'lodash-es';
import { useEffect, useState } from 'react'; import { memo, useEffect, useState } from 'react';
import { Image as KonvaImage } from 'react-konva'; import { Image as KonvaImage } from 'react-konva';
import { canvasSelector } from '../store/canvasSelectors'; import { canvasSelector } from '../store/canvasSelectors';
@ -66,4 +66,4 @@ const IAICanvasIntermediateImage = (props: Props) => {
) : null; ) : null;
}; };
export default IAICanvasIntermediateImage; export default memo(IAICanvasIntermediateImage);

View File

@ -7,7 +7,7 @@ import { Rect } from 'react-konva';
import { rgbaColorToString } from 'features/canvas/util/colorToString'; import { rgbaColorToString } from 'features/canvas/util/colorToString';
import Konva from 'konva'; import Konva from 'konva';
import { isNumber } from 'lodash-es'; import { isNumber } from 'lodash-es';
import { useCallback, useEffect, useRef, useState } from 'react'; import { memo, useCallback, useEffect, useRef, useState } from 'react';
export const canvasMaskCompositerSelector = createSelector( export const canvasMaskCompositerSelector = createSelector(
canvasSelector, canvasSelector,
@ -172,4 +172,4 @@ const IAICanvasMaskCompositer = (props: IAICanvasMaskCompositerProps) => {
); );
}; };
export default IAICanvasMaskCompositer; export default memo(IAICanvasMaskCompositer);

View File

@ -6,6 +6,7 @@ import { isEqual } from 'lodash-es';
import { Group, Line } from 'react-konva'; import { Group, Line } from 'react-konva';
import { isCanvasMaskLine } from '../store/canvasTypes'; import { isCanvasMaskLine } from '../store/canvasTypes';
import { memo } from 'react';
export const canvasLinesSelector = createSelector( export const canvasLinesSelector = createSelector(
[canvasSelector], [canvasSelector],
@ -52,4 +53,4 @@ const IAICanvasLines = (props: InpaintingCanvasLinesProps) => {
); );
}; };
export default IAICanvasLines; export default memo(IAICanvasLines);

View File

@ -12,6 +12,7 @@ import {
isCanvasFillRect, isCanvasFillRect,
} from '../store/canvasTypes'; } from '../store/canvasTypes';
import IAICanvasImage from './IAICanvasImage'; import IAICanvasImage from './IAICanvasImage';
import { memo } from 'react';
const selector = createSelector( const selector = createSelector(
[canvasSelector], [canvasSelector],
@ -101,4 +102,4 @@ const IAICanvasObjectRenderer = () => {
); );
}; };
export default IAICanvasObjectRenderer; export default memo(IAICanvasObjectRenderer);

View File

@ -12,7 +12,7 @@ import {
setDoesCanvasNeedScaling, setDoesCanvasNeedScaling,
} from 'features/canvas/store/canvasSlice'; } from 'features/canvas/store/canvasSlice';
import { activeTabNameSelector } from 'features/ui/store/uiSelectors'; import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
import { useLayoutEffect, useRef } from 'react'; import { memo, useLayoutEffect, useRef } from 'react';
const canvasResizerSelector = createSelector( const canvasResizerSelector = createSelector(
canvasSelector, canvasSelector,
@ -86,4 +86,4 @@ const IAICanvasResizer = () => {
); );
}; };
export default IAICanvasResizer; export default memo(IAICanvasResizer);

View File

@ -6,6 +6,7 @@ import { isEqual } from 'lodash-es';
import { Group, Rect } from 'react-konva'; import { Group, Rect } from 'react-konva';
import IAICanvasImage from './IAICanvasImage'; import IAICanvasImage from './IAICanvasImage';
import { memo } from 'react';
const selector = createSelector( const selector = createSelector(
[canvasSelector], [canvasSelector],
@ -88,4 +89,4 @@ const IAICanvasStagingArea = (props: Props) => {
); );
}; };
export default IAICanvasStagingArea; export default memo(IAICanvasStagingArea);

View File

@ -13,7 +13,7 @@ import {
} from 'features/canvas/store/canvasSlice'; } from 'features/canvas/store/canvasSlice';
import { isEqual } from 'lodash-es'; import { isEqual } from 'lodash-es';
import { useCallback } from 'react'; import { memo, useCallback } from 'react';
import { useHotkeys } from 'react-hotkeys-hook'; import { useHotkeys } from 'react-hotkeys-hook';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { import {
@ -207,4 +207,4 @@ const IAICanvasStagingAreaToolbar = () => {
); );
}; };
export default IAICanvasStagingAreaToolbar; export default memo(IAICanvasStagingAreaToolbar);

View File

@ -7,6 +7,7 @@ import { isEqual } from 'lodash-es';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import roundToHundreth from '../util/roundToHundreth'; import roundToHundreth from '../util/roundToHundreth';
import IAICanvasStatusTextCursorPos from './IAICanvasStatusText/IAICanvasStatusTextCursorPos'; import IAICanvasStatusTextCursorPos from './IAICanvasStatusText/IAICanvasStatusTextCursorPos';
import { memo } from 'react';
const warningColor = 'var(--invokeai-colors-warning-500)'; const warningColor = 'var(--invokeai-colors-warning-500)';
@ -162,4 +163,4 @@ const IAICanvasStatusText = () => {
); );
}; };
export default IAICanvasStatusText; export default memo(IAICanvasStatusText);

View File

@ -10,6 +10,7 @@ import {
COLOR_PICKER_SIZE, COLOR_PICKER_SIZE,
COLOR_PICKER_STROKE_RADIUS, COLOR_PICKER_STROKE_RADIUS,
} from '../util/constants'; } from '../util/constants';
import { memo } from 'react';
const canvasBrushPreviewSelector = createSelector( const canvasBrushPreviewSelector = createSelector(
canvasSelector, canvasSelector,
@ -206,4 +207,4 @@ const IAICanvasToolPreview = (props: GroupConfig) => {
); );
}; };
export default IAICanvasToolPreview; export default memo(IAICanvasToolPreview);

View File

@ -19,7 +19,7 @@ import { KonvaEventObject } from 'konva/lib/Node';
import { Vector2d } from 'konva/lib/types'; import { Vector2d } from 'konva/lib/types';
import { isEqual } from 'lodash-es'; import { isEqual } from 'lodash-es';
import { useCallback, useEffect, useRef, useState } from 'react'; import { memo, useCallback, useEffect, useRef, useState } from 'react';
import { useHotkeys } from 'react-hotkeys-hook'; import { useHotkeys } from 'react-hotkeys-hook';
import { Group, Rect, Transformer } from 'react-konva'; import { Group, Rect, Transformer } from 'react-konva';
@ -313,4 +313,4 @@ const IAICanvasBoundingBox = (props: IAICanvasBoundingBoxPreviewProps) => {
); );
}; };
export default IAICanvasBoundingBox; export default memo(IAICanvasBoundingBox);

View File

@ -20,6 +20,7 @@ import {
} from 'features/canvas/store/canvasSlice'; } from 'features/canvas/store/canvasSlice';
import { rgbaColorToString } from 'features/canvas/util/colorToString'; import { rgbaColorToString } from 'features/canvas/util/colorToString';
import { isEqual } from 'lodash-es'; import { isEqual } from 'lodash-es';
import { memo } from 'react';
import { useHotkeys } from 'react-hotkeys-hook'; import { useHotkeys } from 'react-hotkeys-hook';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
@ -150,4 +151,4 @@ const IAICanvasMaskOptions = () => {
); );
}; };
export default IAICanvasMaskOptions; export default memo(IAICanvasMaskOptions);

View File

@ -18,7 +18,7 @@ import {
} from 'features/canvas/store/canvasSlice'; } from 'features/canvas/store/canvasSlice';
import { isEqual } from 'lodash-es'; import { isEqual } from 'lodash-es';
import { ChangeEvent } from 'react'; import { ChangeEvent, memo } from 'react';
import { useHotkeys } from 'react-hotkeys-hook'; import { useHotkeys } from 'react-hotkeys-hook';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { FaWrench } from 'react-icons/fa'; import { FaWrench } from 'react-icons/fa';
@ -163,4 +163,4 @@ const IAICanvasSettingsButtonPopover = () => {
); );
}; };
export default IAICanvasSettingsButtonPopover; export default memo(IAICanvasSettingsButtonPopover);

View File

@ -18,6 +18,7 @@ import {
} from 'features/canvas/store/canvasSlice'; } from 'features/canvas/store/canvasSlice';
import { systemSelector } from 'features/system/store/systemSelectors'; import { systemSelector } from 'features/system/store/systemSelectors';
import { clamp, isEqual } from 'lodash-es'; import { clamp, isEqual } from 'lodash-es';
import { memo } from 'react';
import { useHotkeys } from 'react-hotkeys-hook'; import { useHotkeys } from 'react-hotkeys-hook';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
@ -252,4 +253,4 @@ const IAICanvasToolChooserOptions = () => {
); );
}; };
export default IAICanvasToolChooserOptions; export default memo(IAICanvasToolChooserOptions);

View File

@ -48,6 +48,7 @@ import IAICanvasRedoButton from './IAICanvasRedoButton';
import IAICanvasSettingsButtonPopover from './IAICanvasSettingsButtonPopover'; import IAICanvasSettingsButtonPopover from './IAICanvasSettingsButtonPopover';
import IAICanvasToolChooserOptions from './IAICanvasToolChooserOptions'; import IAICanvasToolChooserOptions from './IAICanvasToolChooserOptions';
import IAICanvasUndoButton from './IAICanvasUndoButton'; import IAICanvasUndoButton from './IAICanvasUndoButton';
import { memo } from 'react';
export const selector = createSelector( export const selector = createSelector(
[systemSelector, canvasSelector, isStagingSelector], [systemSelector, canvasSelector, isStagingSelector],
@ -309,4 +310,4 @@ const IAICanvasToolbar = () => {
); );
}; };
export default IAICanvasToolbar; export default memo(IAICanvasToolbar);

View File

@ -4,7 +4,7 @@ import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
import IAISwitch from 'common/components/IAISwitch'; import IAISwitch from 'common/components/IAISwitch';
import { isControlNetEnabledToggled } from 'features/controlNet/store/controlNetSlice'; import { isControlNetEnabledToggled } from 'features/controlNet/store/controlNetSlice';
import { useCallback } from 'react'; import { memo, useCallback } from 'react';
const selector = createSelector( const selector = createSelector(
stateSelector, stateSelector,
@ -36,4 +36,4 @@ const ParamControlNetFeatureToggle = () => {
); );
}; };
export default ParamControlNetFeatureToggle; export default memo(ParamControlNetFeatureToggle);

View File

@ -8,6 +8,7 @@ import ParamDynamicPromptsCombinatorial from './ParamDynamicPromptsCombinatorial
import ParamDynamicPromptsToggle from './ParamDynamicPromptsEnabled'; import ParamDynamicPromptsToggle from './ParamDynamicPromptsEnabled';
import ParamDynamicPromptsMaxPrompts from './ParamDynamicPromptsMaxPrompts'; import ParamDynamicPromptsMaxPrompts from './ParamDynamicPromptsMaxPrompts';
import { useFeatureStatus } from '../../system/hooks/useFeatureStatus'; import { useFeatureStatus } from '../../system/hooks/useFeatureStatus';
import { memo } from 'react';
const selector = createSelector( const selector = createSelector(
stateSelector, stateSelector,
@ -40,4 +41,4 @@ const ParamDynamicPromptsCollapse = () => {
); );
}; };
export default ParamDynamicPromptsCollapse; export default memo(ParamDynamicPromptsCollapse);

View File

@ -3,7 +3,7 @@ import { stateSelector } from 'app/store/store';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
import IAISwitch from 'common/components/IAISwitch'; import IAISwitch from 'common/components/IAISwitch';
import { useCallback } from 'react'; import { memo, useCallback } from 'react';
import { combinatorialToggled } from '../store/dynamicPromptsSlice'; import { combinatorialToggled } from '../store/dynamicPromptsSlice';
const selector = createSelector( const selector = createSelector(
@ -34,4 +34,4 @@ const ParamDynamicPromptsCombinatorial = () => {
); );
}; };
export default ParamDynamicPromptsCombinatorial; export default memo(ParamDynamicPromptsCombinatorial);

View File

@ -3,7 +3,7 @@ import { stateSelector } from 'app/store/store';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
import IAISwitch from 'common/components/IAISwitch'; import IAISwitch from 'common/components/IAISwitch';
import { useCallback } from 'react'; import { memo, useCallback } from 'react';
import { isEnabledToggled } from '../store/dynamicPromptsSlice'; import { isEnabledToggled } from '../store/dynamicPromptsSlice';
const selector = createSelector( const selector = createSelector(
@ -33,4 +33,4 @@ const ParamDynamicPromptsToggle = () => {
); );
}; };
export default ParamDynamicPromptsToggle; export default memo(ParamDynamicPromptsToggle);

View File

@ -3,7 +3,7 @@ import { stateSelector } from 'app/store/store';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
import IAISlider from 'common/components/IAISlider'; import IAISlider from 'common/components/IAISlider';
import { useCallback } from 'react'; import { memo, useCallback } from 'react';
import { import {
maxPromptsChanged, maxPromptsChanged,
maxPromptsReset, maxPromptsReset,
@ -60,4 +60,4 @@ const ParamDynamicPromptsMaxPrompts = () => {
); );
}; };
export default ParamDynamicPromptsMaxPrompts; export default memo(ParamDynamicPromptsMaxPrompts);

View File

@ -13,7 +13,7 @@ import IAIMantineSearchableSelect from 'common/components/IAIMantineSearchableSe
import IAIMantineSelectItemWithTooltip from 'common/components/IAIMantineSelectItemWithTooltip'; import IAIMantineSelectItemWithTooltip from 'common/components/IAIMantineSelectItemWithTooltip';
import { MODEL_TYPE_MAP } from 'features/parameters/types/constants'; import { MODEL_TYPE_MAP } from 'features/parameters/types/constants';
import { forEach } from 'lodash-es'; import { forEach } from 'lodash-es';
import { PropsWithChildren, useCallback, useMemo, useRef } from 'react'; import { PropsWithChildren, memo, useCallback, useMemo, useRef } from 'react';
import { useGetTextualInversionModelsQuery } from 'services/api/endpoints/models'; import { useGetTextualInversionModelsQuery } from 'services/api/endpoints/models';
import { PARAMETERS_PANEL_WIDTH } from 'theme/util/constants'; import { PARAMETERS_PANEL_WIDTH } from 'theme/util/constants';
@ -140,4 +140,4 @@ const ParamEmbeddingPopover = (props: Props) => {
); );
}; };
export default ParamEmbeddingPopover; export default memo(ParamEmbeddingPopover);

View File

@ -1,4 +1,5 @@
import { Badge, Flex } from '@chakra-ui/react'; import { Badge, Flex } from '@chakra-ui/react';
import { memo } from 'react';
const AutoAddIcon = () => { const AutoAddIcon = () => {
return ( return (
@ -20,4 +21,4 @@ const AutoAddIcon = () => {
); );
}; };
export default AutoAddIcon; export default memo(AutoAddIcon);

View File

@ -6,7 +6,7 @@ import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
import IAIMantineSearchableSelect from 'common/components/IAIMantineSearchableSelect'; import IAIMantineSearchableSelect from 'common/components/IAIMantineSearchableSelect';
import IAIMantineSelectItemWithTooltip from 'common/components/IAIMantineSelectItemWithTooltip'; import IAIMantineSelectItemWithTooltip from 'common/components/IAIMantineSelectItemWithTooltip';
import { autoAddBoardIdChanged } from 'features/gallery/store/gallerySlice'; import { autoAddBoardIdChanged } from 'features/gallery/store/gallerySlice';
import { useCallback, useRef } from 'react'; import { memo, useCallback, useRef } from 'react';
import { useListAllBoardsQuery } from 'services/api/endpoints/boards'; import { useListAllBoardsQuery } from 'services/api/endpoints/boards';
const selector = createSelector( const selector = createSelector(
@ -81,4 +81,4 @@ const BoardAutoAddSelect = () => {
); );
}; };
export default BoardAutoAddSelect; export default memo(BoardAutoAddSelect);

View File

@ -23,71 +23,72 @@ type Props = {
setBoardToDelete?: (board?: BoardDTO) => void; setBoardToDelete?: (board?: BoardDTO) => void;
}; };
const BoardContextMenu = memo( const BoardContextMenu = ({
({ board, board_id, setBoardToDelete, children }: Props) => { board,
const dispatch = useAppDispatch(); board_id,
setBoardToDelete,
children,
}: Props) => {
const dispatch = useAppDispatch();
const selector = useMemo( const selector = useMemo(
() => () =>
createSelector(stateSelector, ({ gallery, system }) => { createSelector(stateSelector, ({ gallery, system }) => {
const isAutoAdd = gallery.autoAddBoardId === board_id; const isAutoAdd = gallery.autoAddBoardId === board_id;
const isProcessing = system.isProcessing; const isProcessing = system.isProcessing;
const autoAssignBoardOnClick = gallery.autoAssignBoardOnClick; const autoAssignBoardOnClick = gallery.autoAssignBoardOnClick;
return { isAutoAdd, isProcessing, autoAssignBoardOnClick }; return { isAutoAdd, isProcessing, autoAssignBoardOnClick };
}), }),
[board_id] [board_id]
); );
const { isAutoAdd, isProcessing, autoAssignBoardOnClick } = const { isAutoAdd, isProcessing, autoAssignBoardOnClick } =
useAppSelector(selector); useAppSelector(selector);
const boardName = useBoardName(board_id); const boardName = useBoardName(board_id);
const handleSetAutoAdd = useCallback(() => { const handleSetAutoAdd = useCallback(() => {
dispatch(autoAddBoardIdChanged(board_id)); dispatch(autoAddBoardIdChanged(board_id));
}, [board_id, dispatch]); }, [board_id, dispatch]);
const skipEvent = useCallback((e: MouseEvent<HTMLDivElement>) => { const skipEvent = useCallback((e: MouseEvent<HTMLDivElement>) => {
e.preventDefault(); e.preventDefault();
}, []); }, []);
return ( return (
<IAIContextMenu<HTMLDivElement> <IAIContextMenu<HTMLDivElement>
menuProps={{ size: 'sm', isLazy: true }} menuProps={{ size: 'sm', isLazy: true }}
menuButtonProps={{ menuButtonProps={{
bg: 'transparent', bg: 'transparent',
_hover: { bg: 'transparent' }, _hover: { bg: 'transparent' },
}} }}
renderMenu={() => ( renderMenu={() => (
<MenuList <MenuList
sx={{ visibility: 'visible !important' }} sx={{ visibility: 'visible !important' }}
motionProps={menuListMotionProps} motionProps={menuListMotionProps}
onContextMenu={skipEvent} onContextMenu={skipEvent}
> >
<MenuGroup title={boardName}> <MenuGroup title={boardName}>
<MenuItem <MenuItem
icon={<FaPlus />} icon={<FaPlus />}
isDisabled={isAutoAdd || isProcessing || autoAssignBoardOnClick} isDisabled={isAutoAdd || isProcessing || autoAssignBoardOnClick}
onClick={handleSetAutoAdd} onClick={handleSetAutoAdd}
> >
Auto-add to this Board Auto-add to this Board
</MenuItem> </MenuItem>
{!board && <NoBoardContextMenuItems />} {!board && <NoBoardContextMenuItems />}
{board && ( {board && (
<GalleryBoardContextMenuItems <GalleryBoardContextMenuItems
board={board} board={board}
setBoardToDelete={setBoardToDelete} setBoardToDelete={setBoardToDelete}
/> />
)} )}
</MenuGroup> </MenuGroup>
</MenuList> </MenuList>
)} )}
> >
{children} {children}
</IAIContextMenu> </IAIContextMenu>
); );
} };
);
BoardContextMenu.displayName = 'HoverableBoard'; export default memo(BoardContextMenu);
export default BoardContextMenu;

View File

@ -1,5 +1,5 @@
import IAIIconButton from 'common/components/IAIIconButton'; import IAIIconButton from 'common/components/IAIIconButton';
import { useCallback } from 'react'; import { memo, useCallback } from 'react';
import { FaPlus } from 'react-icons/fa'; import { FaPlus } from 'react-icons/fa';
import { useCreateBoardMutation } from 'services/api/endpoints/boards'; import { useCreateBoardMutation } from 'services/api/endpoints/boards';
@ -24,4 +24,4 @@ const AddBoardButton = () => {
); );
}; };
export default AddBoardButton; export default memo(AddBoardButton);

View File

@ -39,187 +39,188 @@ interface GalleryBoardProps {
setBoardToDelete: (board?: BoardDTO) => void; setBoardToDelete: (board?: BoardDTO) => void;
} }
const GalleryBoard = memo( const GalleryBoard = ({
({ board, isSelected, setBoardToDelete }: GalleryBoardProps) => { board,
const dispatch = useAppDispatch(); isSelected,
const selector = useMemo( setBoardToDelete,
() => }: GalleryBoardProps) => {
createSelector( const dispatch = useAppDispatch();
stateSelector, const selector = useMemo(
({ gallery, system }) => { () =>
const isSelectedForAutoAdd = createSelector(
board.board_id === gallery.autoAddBoardId; stateSelector,
const autoAssignBoardOnClick = gallery.autoAssignBoardOnClick; ({ gallery, system }) => {
const isProcessing = system.isProcessing; const isSelectedForAutoAdd =
board.board_id === gallery.autoAddBoardId;
const autoAssignBoardOnClick = gallery.autoAssignBoardOnClick;
const isProcessing = system.isProcessing;
return { return {
isSelectedForAutoAdd, isSelectedForAutoAdd,
autoAssignBoardOnClick, autoAssignBoardOnClick,
isProcessing, isProcessing,
}; };
}, },
defaultSelectorOptions defaultSelectorOptions
), ),
[board.board_id] [board.board_id]
); );
const { isSelectedForAutoAdd, autoAssignBoardOnClick, isProcessing } = const { isSelectedForAutoAdd, autoAssignBoardOnClick, isProcessing } =
useAppSelector(selector); useAppSelector(selector);
const [isHovered, setIsHovered] = useState(false); const [isHovered, setIsHovered] = useState(false);
const handleMouseOver = useCallback(() => { const handleMouseOver = useCallback(() => {
setIsHovered(true); setIsHovered(true);
}, []); }, []);
const handleMouseOut = useCallback(() => { const handleMouseOut = useCallback(() => {
setIsHovered(false); setIsHovered(false);
}, []); }, []);
const { data: imagesTotal } = useGetBoardImagesTotalQuery(board.board_id); const { data: imagesTotal } = useGetBoardImagesTotalQuery(board.board_id);
const { data: assetsTotal } = useGetBoardAssetsTotalQuery(board.board_id); const { data: assetsTotal } = useGetBoardAssetsTotalQuery(board.board_id);
const tooltip = useMemo(() => { const tooltip = useMemo(() => {
if (!imagesTotal || !assetsTotal) { if (!imagesTotal || !assetsTotal) {
return undefined; return undefined;
}
return `${imagesTotal} image${
imagesTotal > 1 ? 's' : ''
}, ${assetsTotal} asset${assetsTotal > 1 ? 's' : ''}`;
}, [assetsTotal, imagesTotal]);
const { currentData: coverImage } = useGetImageDTOQuery(
board.cover_image_name ?? skipToken
);
const { board_name, board_id } = board;
const [localBoardName, setLocalBoardName] = useState(board_name);
const handleSelectBoard = useCallback(() => {
dispatch(boardIdSelected(board_id));
if (autoAssignBoardOnClick && !isProcessing) {
dispatch(autoAddBoardIdChanged(board_id));
}
}, [board_id, autoAssignBoardOnClick, isProcessing, dispatch]);
const [updateBoard, { isLoading: isUpdateBoardLoading }] =
useUpdateBoardMutation();
const droppableData: AddToBoardDropData = useMemo(
() => ({
id: board_id,
actionType: 'ADD_TO_BOARD',
context: { boardId: board_id },
}),
[board_id]
);
const handleSubmit = useCallback(
async (newBoardName: string) => {
// empty strings are not allowed
if (!newBoardName.trim()) {
setLocalBoardName(board_name);
return;
} }
return `${imagesTotal} image${
imagesTotal > 1 ? 's' : ''
}, ${assetsTotal} asset${assetsTotal > 1 ? 's' : ''}`;
}, [assetsTotal, imagesTotal]);
const { currentData: coverImage } = useGetImageDTOQuery( // don't updated the board name if it hasn't changed
board.cover_image_name ?? skipToken if (newBoardName === board_name) {
); return;
const { board_name, board_id } = board;
const [localBoardName, setLocalBoardName] = useState(board_name);
const handleSelectBoard = useCallback(() => {
dispatch(boardIdSelected(board_id));
if (autoAssignBoardOnClick && !isProcessing) {
dispatch(autoAddBoardIdChanged(board_id));
} }
}, [board_id, autoAssignBoardOnClick, isProcessing, dispatch]);
const [updateBoard, { isLoading: isUpdateBoardLoading }] = try {
useUpdateBoardMutation(); const { board_name } = await updateBoard({
board_id,
changes: { board_name: newBoardName },
}).unwrap();
const droppableData: AddToBoardDropData = useMemo( // update local state
() => ({ setLocalBoardName(board_name);
id: board_id, } catch {
actionType: 'ADD_TO_BOARD', // revert on error
context: { boardId: board_id }, setLocalBoardName(board_name);
}), }
[board_id] },
); [board_id, board_name, updateBoard]
);
const handleSubmit = useCallback( const handleChange = useCallback((newBoardName: string) => {
async (newBoardName: string) => { setLocalBoardName(newBoardName);
// empty strings are not allowed }, []);
if (!newBoardName.trim()) {
setLocalBoardName(board_name);
return;
}
// don't updated the board name if it hasn't changed return (
if (newBoardName === board_name) { <Box sx={{ w: 'full', h: 'full', touchAction: 'none', userSelect: 'none' }}>
return; <Flex
} onMouseOver={handleMouseOver}
onMouseOut={handleMouseOut}
try { sx={{
const { board_name } = await updateBoard({ position: 'relative',
board_id, justifyContent: 'center',
changes: { board_name: newBoardName }, alignItems: 'center',
}).unwrap(); aspectRatio: '1/1',
w: 'full',
// update local state h: 'full',
setLocalBoardName(board_name); }}
} catch {
// revert on error
setLocalBoardName(board_name);
}
},
[board_id, board_name, updateBoard]
);
const handleChange = useCallback((newBoardName: string) => {
setLocalBoardName(newBoardName);
}, []);
return (
<Box
sx={{ w: 'full', h: 'full', touchAction: 'none', userSelect: 'none' }}
> >
<Flex <BoardContextMenu
onMouseOver={handleMouseOver} board={board}
onMouseOut={handleMouseOut} board_id={board_id}
sx={{ setBoardToDelete={setBoardToDelete}
position: 'relative',
justifyContent: 'center',
alignItems: 'center',
aspectRatio: '1/1',
w: 'full',
h: 'full',
}}
> >
<BoardContextMenu {(ref) => (
board={board} <Tooltip label={tooltip} openDelay={1000} hasArrow>
board_id={board_id} <Flex
setBoardToDelete={setBoardToDelete} ref={ref}
> onClick={handleSelectBoard}
{(ref) => ( sx={{
<Tooltip label={tooltip} openDelay={1000} hasArrow> w: 'full',
<Flex h: 'full',
ref={ref} position: 'relative',
onClick={handleSelectBoard} justifyContent: 'center',
sx={{ alignItems: 'center',
w: 'full', borderRadius: 'base',
h: 'full', cursor: 'pointer',
position: 'relative', bg: 'base.200',
justifyContent: 'center', _dark: {
alignItems: 'center', bg: 'base.800',
borderRadius: 'base', },
cursor: 'pointer', }}
bg: 'base.200', >
_dark: { {coverImage?.thumbnail_url ? (
bg: 'base.800', <Image
}, src={coverImage?.thumbnail_url}
}} draggable={false}
> sx={{
{coverImage?.thumbnail_url ? ( objectFit: 'cover',
<Image w: 'full',
src={coverImage?.thumbnail_url} h: 'full',
draggable={false} maxH: 'full',
borderRadius: 'base',
borderBottomRadius: 'lg',
}}
/>
) : (
<Flex
sx={{
w: 'full',
h: 'full',
justifyContent: 'center',
alignItems: 'center',
}}
>
<Icon
boxSize={12}
as={FaUser}
sx={{ sx={{
objectFit: 'cover', mt: -6,
w: 'full', opacity: 0.7,
h: 'full', color: 'base.500',
maxH: 'full', _dark: {
borderRadius: 'base', color: 'base.500',
borderBottomRadius: 'lg', },
}} }}
/> />
) : ( </Flex>
<Flex )}
sx={{ {/* <Flex
w: 'full',
h: 'full',
justifyContent: 'center',
alignItems: 'center',
}}
>
<Icon
boxSize={12}
as={FaUser}
sx={{
mt: -6,
opacity: 0.7,
color: 'base.500',
_dark: {
color: 'base.500',
},
}}
/>
</Flex>
)}
{/* <Flex
sx={{ sx={{
position: 'absolute', position: 'absolute',
insetInlineEnd: 0, insetInlineEnd: 0,
@ -231,80 +232,77 @@ const GalleryBoard = memo(
{totalImages}/{totalAssets} {totalImages}/{totalAssets}
</Badge> </Badge>
</Flex> */} </Flex> */}
{isSelectedForAutoAdd && <AutoAddIcon />} {isSelectedForAutoAdd && <AutoAddIcon />}
<SelectionOverlay <SelectionOverlay
isSelected={isSelected} isSelected={isSelected}
isHovered={isHovered} isHovered={isHovered}
/> />
<Flex <Flex
sx={{ sx={{
position: 'absolute', position: 'absolute',
bottom: 0, bottom: 0,
left: 0, left: 0,
p: 1, p: 1,
justifyContent: 'center', justifyContent: 'center',
alignItems: 'center', alignItems: 'center',
w: 'full', w: 'full',
maxW: 'full', maxW: 'full',
borderBottomRadius: 'base', borderBottomRadius: 'base',
bg: isSelected ? 'accent.400' : 'base.500', bg: isSelected ? 'accent.400' : 'base.500',
color: isSelected ? 'base.50' : 'base.100',
_dark: {
bg: isSelected ? 'accent.500' : 'base.600',
color: isSelected ? 'base.50' : 'base.100', color: isSelected ? 'base.50' : 'base.100',
_dark: { },
bg: isSelected ? 'accent.500' : 'base.600', lineHeight: 'short',
color: isSelected ? 'base.50' : 'base.100', fontSize: 'xs',
}, }}
lineHeight: 'short', >
fontSize: 'xs', <Editable
value={localBoardName}
isDisabled={isUpdateBoardLoading}
submitOnBlur={true}
onChange={handleChange}
onSubmit={handleSubmit}
sx={{
w: 'full',
}} }}
> >
<Editable <EditablePreview
value={localBoardName}
isDisabled={isUpdateBoardLoading}
submitOnBlur={true}
onChange={handleChange}
onSubmit={handleSubmit}
sx={{ sx={{
w: 'full', p: 0,
fontWeight: isSelected ? 700 : 500,
textAlign: 'center',
overflow: 'hidden',
textOverflow: 'ellipsis',
}} }}
> noOfLines={1}
<EditablePreview />
sx={{ <EditableInput
sx={{
p: 0,
_focusVisible: {
p: 0, p: 0,
fontWeight: isSelected ? 700 : 500,
textAlign: 'center', textAlign: 'center',
overflow: 'hidden', // get rid of the edit border
textOverflow: 'ellipsis', boxShadow: 'none',
}} },
noOfLines={1} }}
/> />
<EditableInput </Editable>
sx={{
p: 0,
_focusVisible: {
p: 0,
textAlign: 'center',
// get rid of the edit border
boxShadow: 'none',
},
}}
/>
</Editable>
</Flex>
<IAIDroppable
data={droppableData}
dropLabel={<Text fontSize="md">Move</Text>}
/>
</Flex> </Flex>
</Tooltip>
)}
</BoardContextMenu>
</Flex>
</Box>
);
}
);
GalleryBoard.displayName = 'HoverableBoard'; <IAIDroppable
data={droppableData}
dropLabel={<Text fontSize="md">Move</Text>}
/>
</Flex>
</Tooltip>
)}
</BoardContextMenu>
</Flex>
</Box>
);
};
export default GalleryBoard; export default memo(GalleryBoard);

View File

@ -3,7 +3,7 @@ import IAIDroppable from 'common/components/IAIDroppable';
import { IAINoContentFallback } from 'common/components/IAIImageFallback'; import { IAINoContentFallback } from 'common/components/IAIImageFallback';
import { TypesafeDroppableData } from 'features/dnd/types'; import { TypesafeDroppableData } from 'features/dnd/types';
import { BoardId } from 'features/gallery/store/types'; import { BoardId } from 'features/gallery/store/types';
import { ReactNode } from 'react'; import { ReactNode, memo } from 'react';
import BoardContextMenu from '../BoardContextMenu'; import BoardContextMenu from '../BoardContextMenu';
type GenericBoardProps = { type GenericBoardProps = {
@ -105,4 +105,4 @@ const GenericBoard = (props: GenericBoardProps) => {
); );
}; };
export default GenericBoard; export default memo(GenericBoard);

View File

@ -156,4 +156,4 @@ const NoBoardBoard = memo(({ isSelected }: Props) => {
NoBoardBoard.displayName = 'HoverableBoard'; NoBoardBoard.displayName = 'HoverableBoard';
export default NoBoardBoard; export default memo(NoBoardBoard);

View File

@ -26,7 +26,7 @@ import {
setShouldShowImageDetails, setShouldShowImageDetails,
setShouldShowProgressInViewer, setShouldShowProgressInViewer,
} from 'features/ui/store/uiSlice'; } from 'features/ui/store/uiSlice';
import { useCallback } from 'react'; import { memo, useCallback } from 'react';
import { useHotkeys } from 'react-hotkeys-hook'; import { useHotkeys } from 'react-hotkeys-hook';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { import {
@ -323,4 +323,4 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => {
); );
}; };
export default CurrentImageButtons; export default memo(CurrentImageButtons);

View File

@ -2,6 +2,7 @@ import { Flex } from '@chakra-ui/react';
import CurrentImageButtons from './CurrentImageButtons'; import CurrentImageButtons from './CurrentImageButtons';
import CurrentImagePreview from './CurrentImagePreview'; import CurrentImagePreview from './CurrentImagePreview';
import { memo } from 'react';
const CurrentImageDisplay = () => { const CurrentImageDisplay = () => {
return ( return (
@ -22,4 +23,4 @@ const CurrentImageDisplay = () => {
); );
}; };
export default CurrentImageDisplay; export default memo(CurrentImageDisplay);

View File

@ -1,4 +1,5 @@
import { Flex } from '@chakra-ui/react'; import { Flex } from '@chakra-ui/react';
import { memo } from 'react';
import { FaEyeSlash } from 'react-icons/fa'; import { FaEyeSlash } from 'react-icons/fa';
const CurrentImageHidden = () => { const CurrentImageHidden = () => {
@ -18,4 +19,4 @@ const CurrentImageHidden = () => {
); );
}; };
export default CurrentImageHidden; export default memo(CurrentImageHidden);

View File

@ -5,6 +5,7 @@ import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
import IAIIconButton from 'common/components/IAIIconButton'; import IAIIconButton from 'common/components/IAIIconButton';
import { requestCanvasRescale } from 'features/canvas/store/thunks/requestCanvasScale'; import { requestCanvasRescale } from 'features/canvas/store/thunks/requestCanvasScale';
import { togglePinGalleryPanel } from 'features/ui/store/uiSlice'; import { togglePinGalleryPanel } from 'features/ui/store/uiSlice';
import { memo } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { BsPinAngle, BsPinAngleFill } from 'react-icons/bs'; import { BsPinAngle, BsPinAngleFill } from 'react-icons/bs';
@ -41,4 +42,4 @@ const GalleryPinButton = () => {
); );
}; };
export default GalleryPinButton; export default memo(GalleryPinButton);

View File

@ -12,7 +12,7 @@ import {
setGalleryImageMinimumWidth, setGalleryImageMinimumWidth,
shouldAutoSwitchChanged, shouldAutoSwitchChanged,
} from 'features/gallery/store/gallerySlice'; } from 'features/gallery/store/gallerySlice';
import { ChangeEvent, useCallback } from 'react'; import { ChangeEvent, memo, useCallback } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { FaWrench } from 'react-icons/fa'; import { FaWrench } from 'react-icons/fa';
import BoardAutoAddSelect from './Boards/BoardAutoAddSelect'; import BoardAutoAddSelect from './Boards/BoardAutoAddSelect';
@ -101,4 +101,4 @@ const GallerySettingsPopover = () => {
); );
}; };
export default GallerySettingsPopover; export default memo(GallerySettingsPopover);

View File

@ -5,7 +5,7 @@ import {
isModalOpenChanged, isModalOpenChanged,
} from 'features/changeBoardModal/store/slice'; } from 'features/changeBoardModal/store/slice';
import { imagesToDeleteSelected } from 'features/deleteImageModal/store/slice'; import { imagesToDeleteSelected } from 'features/deleteImageModal/store/slice';
import { useCallback, useMemo } from 'react'; import { memo, useCallback, useMemo } from 'react';
import { FaFolder, FaTrash } from 'react-icons/fa'; import { FaFolder, FaTrash } from 'react-icons/fa';
import { MdStar, MdStarBorder } from 'react-icons/md'; import { MdStar, MdStarBorder } from 'react-icons/md';
import { import {
@ -74,4 +74,4 @@ const MultipleSelectionMenuItems = () => {
); );
}; };
export default MultipleSelectionMenuItems; export default memo(MultipleSelectionMenuItems);

View File

@ -1,4 +1,5 @@
import { Flex, Spinner, SpinnerProps } from '@chakra-ui/react'; import { Flex, Spinner, SpinnerProps } from '@chakra-ui/react';
import { memo } from 'react';
type ImageFallbackSpinnerProps = SpinnerProps; type ImageFallbackSpinnerProps = SpinnerProps;
@ -23,4 +24,4 @@ const ImageFallbackSpinner = (props: ImageFallbackSpinnerProps) => {
); );
}; };
export default ImageFallbackSpinner; export default memo(ImageFallbackSpinner);

View File

@ -1,5 +1,5 @@
import { Box, FlexProps, forwardRef } from '@chakra-ui/react'; import { Box, FlexProps, forwardRef } from '@chakra-ui/react';
import { PropsWithChildren } from 'react'; import { PropsWithChildren, memo } from 'react';
type ItemContainerProps = PropsWithChildren & FlexProps; type ItemContainerProps = PropsWithChildren & FlexProps;
const ItemContainer = forwardRef((props: ItemContainerProps, ref) => ( const ItemContainer = forwardRef((props: ItemContainerProps, ref) => (
@ -8,4 +8,4 @@ const ItemContainer = forwardRef((props: ItemContainerProps, ref) => (
</Box> </Box>
)); ));
export default ItemContainer; export default memo(ItemContainer);

View File

@ -1,7 +1,7 @@
import { FlexProps, Grid, forwardRef } from '@chakra-ui/react'; import { FlexProps, Grid, forwardRef } from '@chakra-ui/react';
import { RootState } from 'app/store/store'; import { RootState } from 'app/store/store';
import { useAppSelector } from 'app/store/storeHooks'; import { useAppSelector } from 'app/store/storeHooks';
import { PropsWithChildren } from 'react'; import { PropsWithChildren, memo } from 'react';
type ListContainerProps = PropsWithChildren & FlexProps; type ListContainerProps = PropsWithChildren & FlexProps;
const ListContainer = forwardRef((props: ListContainerProps, ref) => { const ListContainer = forwardRef((props: ListContainerProps, ref) => {
@ -23,4 +23,4 @@ const ListContainer = forwardRef((props: ListContainerProps, ref) => {
); );
}); });
export default ListContainer; export default memo(ListContainer);

View File

@ -1,7 +1,7 @@
import { Box, Flex, IconButton, Tooltip } from '@chakra-ui/react'; import { Box, Flex, IconButton, Tooltip } from '@chakra-ui/react';
import { isString } from 'lodash-es'; import { isString } from 'lodash-es';
import { OverlayScrollbarsComponent } from 'overlayscrollbars-react'; import { OverlayScrollbarsComponent } from 'overlayscrollbars-react';
import { useCallback, useMemo } from 'react'; import { memo, useCallback, useMemo } from 'react';
import { FaCopy, FaSave } from 'react-icons/fa'; import { FaCopy, FaSave } from 'react-icons/fa';
type Props = { type Props = {
@ -93,4 +93,4 @@ const DataViewer = (props: Props) => {
); );
}; };
export default DataViewer; export default memo(DataViewer);

View File

@ -1,5 +1,5 @@
import { useRecallParameters } from 'features/parameters/hooks/useRecallParameters'; import { useRecallParameters } from 'features/parameters/hooks/useRecallParameters';
import { useCallback } from 'react'; import { memo, useCallback } from 'react';
import { UnsafeImageMetadata } from 'services/api/types'; import { UnsafeImageMetadata } from 'services/api/types';
import ImageMetadataItem from './ImageMetadataItem'; import ImageMetadataItem from './ImageMetadataItem';
@ -206,4 +206,4 @@ const ImageMetadataActions = (props: Props) => {
); );
}; };
export default ImageMetadataActions; export default memo(ImageMetadataActions);

View File

@ -1,5 +1,6 @@
import { ExternalLinkIcon } from '@chakra-ui/icons'; import { ExternalLinkIcon } from '@chakra-ui/icons';
import { Flex, IconButton, Link, Text, Tooltip } from '@chakra-ui/react'; import { Flex, IconButton, Link, Text, Tooltip } from '@chakra-ui/react';
import { memo } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { FaCopy } from 'react-icons/fa'; import { FaCopy } from 'react-icons/fa';
import { IoArrowUndoCircleOutline } from 'react-icons/io5'; import { IoArrowUndoCircleOutline } from 'react-icons/io5';
@ -74,4 +75,4 @@ const ImageMetadataItem = ({
); );
}; };
export default ImageMetadataItem; export default memo(ImageMetadataItem);

View File

@ -5,6 +5,7 @@ import { useAppSelector } from 'app/store/storeHooks';
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
import { map } from 'lodash-es'; import { map } from 'lodash-es';
import ParamLora from './ParamLora'; import ParamLora from './ParamLora';
import { memo } from 'react';
const selector = createSelector( const selector = createSelector(
stateSelector, stateSelector,
@ -29,4 +30,4 @@ const ParamLoraList = () => {
); );
}; };
export default ParamLoraList; export default memo(ParamLoraList);

View File

@ -9,7 +9,7 @@ import IAIMantineSelectItemWithTooltip from 'common/components/IAIMantineSelectI
import { loraAdded } from 'features/lora/store/loraSlice'; import { loraAdded } from 'features/lora/store/loraSlice';
import { MODEL_TYPE_MAP } from 'features/parameters/types/constants'; import { MODEL_TYPE_MAP } from 'features/parameters/types/constants';
import { forEach } from 'lodash-es'; import { forEach } from 'lodash-es';
import { useCallback, useMemo } from 'react'; import { memo, useCallback, useMemo } from 'react';
import { useGetLoRAModelsQuery } from 'services/api/endpoints/models'; import { useGetLoRAModelsQuery } from 'services/api/endpoints/models';
const selector = createSelector( const selector = createSelector(
@ -102,4 +102,4 @@ const ParamLoRASelect = () => {
); );
}; };
export default ParamLoRASelect; export default memo(ParamLoRASelect);

View File

@ -7,7 +7,7 @@ import {
isInputFieldValue, isInputFieldValue,
} from 'features/nodes/types/types'; } from 'features/nodes/types/types';
import { startCase } from 'lodash-es'; import { startCase } from 'lodash-es';
import { useMemo } from 'react'; import { memo, useMemo } from 'react';
interface Props { interface Props {
nodeId: string; nodeId: string;
@ -51,4 +51,4 @@ const FieldTooltipContent = ({ nodeId, fieldName, kind }: Props) => {
); );
}; };
export default FieldTooltipContent; export default memo(FieldTooltipContent);

View File

@ -139,7 +139,7 @@ const InputField = ({ nodeId, fieldName }: Props) => {
); );
}; };
export default InputField; export default memo(InputField);
type InputFieldWrapperProps = PropsWithChildren<{ type InputFieldWrapperProps = PropsWithChildren<{
shouldDim: boolean; shouldDim: boolean;

View File

@ -1,6 +1,6 @@
import { Box, Flex } from '@chakra-ui/react'; import { Box, Flex } from '@chakra-ui/react';
import { OverlayScrollbarsComponent } from 'overlayscrollbars-react'; import { OverlayScrollbarsComponent } from 'overlayscrollbars-react';
import { PropsWithChildren } from 'react'; import { PropsWithChildren, memo } from 'react';
const ScrollableContent = (props: PropsWithChildren) => { const ScrollableContent = (props: PropsWithChildren) => {
return ( return (
@ -42,4 +42,4 @@ const ScrollableContent = (props: PropsWithChildren) => {
); );
}; };
export default ScrollableContent; export default memo(ScrollableContent);

View File

@ -1,5 +1,6 @@
import { Box } from '@chakra-ui/react'; import { Box } from '@chakra-ui/react';
import { useCanvasGenerationMode } from 'features/canvas/hooks/useCanvasGenerationMode'; import { useCanvasGenerationMode } from 'features/canvas/hooks/useCanvasGenerationMode';
import { memo } from 'react';
const GENERATION_MODE_NAME_MAP = { const GENERATION_MODE_NAME_MAP = {
txt2img: 'Text to Image', txt2img: 'Text to Image',
@ -18,4 +19,4 @@ const GenerationModeStatusText = () => {
); );
}; };
export default GenerationModeStatusText; export default memo(GenerationModeStatusText);

View File

@ -5,7 +5,7 @@ import IAITextarea from 'common/components/IAITextarea';
import AddEmbeddingButton from 'features/embedding/components/AddEmbeddingButton'; import AddEmbeddingButton from 'features/embedding/components/AddEmbeddingButton';
import ParamEmbeddingPopover from 'features/embedding/components/ParamEmbeddingPopover'; import ParamEmbeddingPopover from 'features/embedding/components/ParamEmbeddingPopover';
import { setNegativePrompt } from 'features/parameters/store/generationSlice'; import { setNegativePrompt } from 'features/parameters/store/generationSlice';
import { ChangeEvent, KeyboardEvent, useCallback, useRef } from 'react'; import { ChangeEvent, KeyboardEvent, memo, useCallback, useRef } from 'react';
import { flushSync } from 'react-dom'; import { flushSync } from 'react-dom';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useFeatureStatus } from '../../../../system/hooks/useFeatureStatus'; import { useFeatureStatus } from '../../../../system/hooks/useFeatureStatus';
@ -109,4 +109,4 @@ const ParamNegativeConditioning = () => {
); );
}; };
export default ParamNegativeConditioning; export default memo(ParamNegativeConditioning);

View File

@ -1,7 +1,7 @@
import { Box, FormControl, useDisclosure } from '@chakra-ui/react'; import { Box, FormControl, useDisclosure } from '@chakra-ui/react';
import { stateSelector } from 'app/store/store'; import { stateSelector } from 'app/store/store';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { ChangeEvent, KeyboardEvent, useCallback, useRef } from 'react'; import { ChangeEvent, KeyboardEvent, memo, useCallback, useRef } from 'react';
import { createSelector } from '@reduxjs/toolkit'; import { createSelector } from '@reduxjs/toolkit';
import { import {
@ -159,4 +159,4 @@ const ParamPositiveConditioning = () => {
); );
}; };
export default ParamPositiveConditioning; export default memo(ParamPositiveConditioning);

View File

@ -9,7 +9,7 @@ import {
TypesafeDraggableData, TypesafeDraggableData,
TypesafeDroppableData, TypesafeDroppableData,
} from 'features/dnd/types'; } from 'features/dnd/types';
import { useMemo } from 'react'; import { memo, useMemo } from 'react';
import { useGetImageDTOQuery } from 'services/api/endpoints/images'; import { useGetImageDTOQuery } from 'services/api/endpoints/images';
const selector = createSelector( const selector = createSelector(
@ -64,4 +64,4 @@ const InitialImage = () => {
); );
}; };
export default InitialImage; export default memo(InitialImage);

View File

@ -6,7 +6,7 @@ import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
import IAIIconButton from 'common/components/IAIIconButton'; import IAIIconButton from 'common/components/IAIIconButton';
import { useImageUploadButton } from 'common/hooks/useImageUploadButton'; import { useImageUploadButton } from 'common/hooks/useImageUploadButton';
import { clearInitialImage } from 'features/parameters/store/generationSlice'; import { clearInitialImage } from 'features/parameters/store/generationSlice';
import { useCallback } from 'react'; import { memo, useCallback } from 'react';
import { FaUndo, FaUpload } from 'react-icons/fa'; import { FaUndo, FaUpload } from 'react-icons/fa';
import InitialImage from './InitialImage'; import InitialImage from './InitialImage';
import { PostUploadAction } from 'services/api/types'; import { PostUploadAction } from 'services/api/types';
@ -95,4 +95,4 @@ const InitialImageDisplay = () => {
); );
}; };
export default InitialImageDisplay; export default memo(InitialImageDisplay);

View File

@ -5,7 +5,7 @@ import IAIButton from 'common/components/IAIButton';
import IAIIconButton from 'common/components/IAIIconButton'; import IAIIconButton from 'common/components/IAIIconButton';
import IAIPopover from 'common/components/IAIPopover'; import IAIPopover from 'common/components/IAIPopover';
import { selectIsBusy } from 'features/system/store/systemSelectors'; import { selectIsBusy } from 'features/system/store/systemSelectors';
import { useCallback } from 'react'; import { memo, useCallback } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { FaExpandArrowsAlt } from 'react-icons/fa'; import { FaExpandArrowsAlt } from 'react-icons/fa';
import { ImageDTO } from 'services/api/types'; import { ImageDTO } from 'services/api/types';
@ -59,4 +59,4 @@ const ParamUpscalePopover = (props: Props) => {
); );
}; };
export default ParamUpscalePopover; export default memo(ParamUpscalePopover);

View File

@ -1,6 +1,7 @@
import { Flex } from '@chakra-ui/react'; import { Flex } from '@chakra-ui/react';
import CancelButton from './CancelButton'; import CancelButton from './CancelButton';
import InvokeButton from './InvokeButton'; import InvokeButton from './InvokeButton';
import { memo } from 'react';
/** /**
* Buttons to start and cancel image generation. * Buttons to start and cancel image generation.
@ -14,4 +15,4 @@ const ProcessButtons = () => {
); );
}; };
export default ProcessButtons; export default memo(ProcessButtons);

View File

@ -1,7 +1,7 @@
import { Box, FormControl, useDisclosure } from '@chakra-ui/react'; import { Box, FormControl, useDisclosure } from '@chakra-ui/react';
import { stateSelector } from 'app/store/store'; import { stateSelector } from 'app/store/store';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { ChangeEvent, KeyboardEvent, useCallback, useRef } from 'react'; import { ChangeEvent, KeyboardEvent, memo, useCallback, useRef } from 'react';
import { createSelector } from '@reduxjs/toolkit'; import { createSelector } from '@reduxjs/toolkit';
import { clampSymmetrySteps } from 'features/parameters/store/generationSlice'; import { clampSymmetrySteps } from 'features/parameters/store/generationSlice';
@ -167,4 +167,4 @@ const ParamSDXLNegativeStyleConditioning = () => {
); );
}; };
export default ParamSDXLNegativeStyleConditioning; export default memo(ParamSDXLNegativeStyleConditioning);

View File

@ -1,7 +1,7 @@
import { Box, FormControl, useDisclosure } from '@chakra-ui/react'; import { Box, FormControl, useDisclosure } from '@chakra-ui/react';
import { stateSelector } from 'app/store/store'; import { stateSelector } from 'app/store/store';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { ChangeEvent, KeyboardEvent, useCallback, useRef } from 'react'; import { ChangeEvent, KeyboardEvent, memo, useCallback, useRef } from 'react';
import { createSelector } from '@reduxjs/toolkit'; import { createSelector } from '@reduxjs/toolkit';
import { clampSymmetrySteps } from 'features/parameters/store/generationSlice'; import { clampSymmetrySteps } from 'features/parameters/store/generationSlice';
@ -166,4 +166,4 @@ const ParamSDXLPositiveStyleConditioning = () => {
); );
}; };
export default ParamSDXLPositiveStyleConditioning; export default memo(ParamSDXLPositiveStyleConditioning);

View File

@ -12,6 +12,7 @@ import ParamSDXLRefinerScheduler from './SDXLRefiner/ParamSDXLRefinerScheduler';
import ParamSDXLRefinerStart from './SDXLRefiner/ParamSDXLRefinerStart'; import ParamSDXLRefinerStart from './SDXLRefiner/ParamSDXLRefinerStart';
import ParamSDXLRefinerSteps from './SDXLRefiner/ParamSDXLRefinerSteps'; import ParamSDXLRefinerSteps from './SDXLRefiner/ParamSDXLRefinerSteps';
import ParamUseSDXLRefiner from './SDXLRefiner/ParamUseSDXLRefiner'; import ParamUseSDXLRefiner from './SDXLRefiner/ParamUseSDXLRefiner';
import { memo } from 'react';
const selector = createSelector( const selector = createSelector(
stateSelector, stateSelector,
@ -47,4 +48,4 @@ const ParamSDXLRefinerCollapse = () => {
); );
}; };
export default ParamSDXLRefinerCollapse; export default memo(ParamSDXLRefinerCollapse);

View File

@ -6,6 +6,7 @@ import ProcessButtons from 'features/parameters/components/ProcessButtons/Proces
import ParamSDXLPromptArea from './ParamSDXLPromptArea'; import ParamSDXLPromptArea from './ParamSDXLPromptArea';
import ParamSDXLRefinerCollapse from './ParamSDXLRefinerCollapse'; import ParamSDXLRefinerCollapse from './ParamSDXLRefinerCollapse';
import SDXLImageToImageTabCoreParameters from './SDXLImageToImageTabCoreParameters'; import SDXLImageToImageTabCoreParameters from './SDXLImageToImageTabCoreParameters';
import { memo } from 'react';
const SDXLImageToImageTabParameters = () => { const SDXLImageToImageTabParameters = () => {
return ( return (
@ -22,4 +23,4 @@ const SDXLImageToImageTabParameters = () => {
); );
}; };
export default SDXLImageToImageTabParameters; export default memo(SDXLImageToImageTabParameters);

View File

@ -6,6 +6,7 @@ import ProcessButtons from 'features/parameters/components/ProcessButtons/Proces
import TextToImageTabCoreParameters from 'features/ui/components/tabs/TextToImage/TextToImageTabCoreParameters'; import TextToImageTabCoreParameters from 'features/ui/components/tabs/TextToImage/TextToImageTabCoreParameters';
import ParamSDXLPromptArea from './ParamSDXLPromptArea'; import ParamSDXLPromptArea from './ParamSDXLPromptArea';
import ParamSDXLRefinerCollapse from './ParamSDXLRefinerCollapse'; import ParamSDXLRefinerCollapse from './ParamSDXLRefinerCollapse';
import { memo } from 'react';
const SDXLTextToImageTabParameters = () => { const SDXLTextToImageTabParameters = () => {
return ( return (
@ -22,4 +23,4 @@ const SDXLTextToImageTabParameters = () => {
); );
}; };
export default SDXLTextToImageTabParameters; export default memo(SDXLTextToImageTabParameters);

View File

@ -1,7 +1,7 @@
import { Flex, Image, Text } from '@chakra-ui/react'; import { Flex, Image, Text } from '@chakra-ui/react';
import InvokeAILogoImage from 'assets/images/logo.png'; import InvokeAILogoImage from 'assets/images/logo.png';
import { AnimatePresence, motion } from 'framer-motion'; import { AnimatePresence, motion } from 'framer-motion';
import { useRef } from 'react'; import { memo, useRef } from 'react';
import { useHoverDirty } from 'react-use'; import { useHoverDirty } from 'react-use';
import { useGetAppVersionQuery } from 'services/api/endpoints/appInfo'; import { useGetAppVersionQuery } from 'services/api/endpoints/appInfo';
@ -66,4 +66,4 @@ const InvokeAILogoComponent = ({ showVersion = true }: Props) => {
); );
}; };
export default InvokeAILogoComponent; export default memo(InvokeAILogoComponent);

View File

@ -39,6 +39,7 @@ import {
ChangeEvent, ChangeEvent,
ReactElement, ReactElement,
cloneElement, cloneElement,
memo,
useCallback, useCallback,
useEffect, useEffect,
} from 'react'; } from 'react';
@ -398,4 +399,4 @@ const SettingsModal = ({ children, config }: SettingsModalProps) => {
); );
}; };
export default SettingsModal; export default memo(SettingsModal);

View File

@ -1,5 +1,5 @@
import { Flex } from '@chakra-ui/react'; import { Flex } from '@chakra-ui/react';
import { PropsWithChildren } from 'react'; import { PropsWithChildren, memo } from 'react';
const StyledFlex = (props: PropsWithChildren) => { const StyledFlex = (props: PropsWithChildren) => {
return ( return (
@ -20,4 +20,4 @@ const StyledFlex = (props: PropsWithChildren) => {
); );
}; };
export default StyledFlex; export default memo(StyledFlex);

View File

@ -4,7 +4,7 @@ import { useAppSelector } from 'app/store/storeHooks';
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
import { AnimatePresence, motion } from 'framer-motion'; import { AnimatePresence, motion } from 'framer-motion';
import { ResourceKey } from 'i18next'; import { ResourceKey } from 'i18next';
import { useMemo, useRef } from 'react'; import { memo, useMemo, useRef } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { FaCircle } from 'react-icons/fa'; import { FaCircle } from 'react-icons/fa';
import { useHoverDirty } from 'react-use'; import { useHoverDirty } from 'react-use';
@ -125,4 +125,4 @@ const StatusIndicator = () => {
); );
}; };
export default StatusIndicator; export default memo(StatusIndicator);

View File

@ -6,6 +6,7 @@ import { requestCanvasRescale } from 'features/canvas/store/thunks/requestCanvas
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { BsPinAngle, BsPinAngleFill } from 'react-icons/bs'; import { BsPinAngle, BsPinAngleFill } from 'react-icons/bs';
import { setShouldPinParametersPanel } from '../store/uiSlice'; import { setShouldPinParametersPanel } from '../store/uiSlice';
import { memo } from 'react';
type PinParametersPanelButtonProps = Omit<IAIIconButtonProps, 'aria-label'>; type PinParametersPanelButtonProps = Omit<IAIIconButtonProps, 'aria-label'>;
@ -55,4 +56,4 @@ const PinParametersPanelButton = (props: PinParametersPanelButtonProps) => {
); );
}; };
export default PinParametersPanelButton; export default memo(PinParametersPanelButton);

View File

@ -14,7 +14,7 @@ import {
ResizeCallback, ResizeCallback,
ResizeStartCallback, ResizeStartCallback,
} from 're-resizable'; } from 're-resizable';
import { ReactNode, useEffect, useMemo, useRef, useState } from 'react'; import { ReactNode, memo, useEffect, useMemo, useRef, useState } from 'react';
import { LangDirection } from './types'; import { LangDirection } from './types';
import { import {
getHandleEnables, getHandleEnables,
@ -193,4 +193,4 @@ const ResizableDrawer = ({
); );
}; };
export default ResizableDrawer; export default memo(ResizableDrawer);

View File

@ -9,6 +9,7 @@ import ParamSymmetryCollapse from 'features/parameters/components/Parameters/Sym
import ParamPromptArea from 'features/parameters/components/Parameters/Prompt/ParamPromptArea'; import ParamPromptArea from 'features/parameters/components/Parameters/Prompt/ParamPromptArea';
import ProcessButtons from 'features/parameters/components/ProcessButtons/ProcessButtons'; import ProcessButtons from 'features/parameters/components/ProcessButtons/ProcessButtons';
import ImageToImageTabCoreParameters from './ImageToImageTabCoreParameters'; import ImageToImageTabCoreParameters from './ImageToImageTabCoreParameters';
import { memo } from 'react';
const ImageToImageTabParameters = () => { const ImageToImageTabParameters = () => {
return ( return (
@ -28,4 +29,4 @@ const ImageToImageTabParameters = () => {
); );
}; };
export default ImageToImageTabParameters; export default memo(ImageToImageTabParameters);

View File

@ -3,7 +3,7 @@ import { EntityState } from '@reduxjs/toolkit';
import IAIButton from 'common/components/IAIButton'; import IAIButton from 'common/components/IAIButton';
import IAIInput from 'common/components/IAIInput'; import IAIInput from 'common/components/IAIInput';
import { forEach } from 'lodash-es'; import { forEach } from 'lodash-es';
import type { ChangeEvent, PropsWithChildren } from 'react'; import { ChangeEvent, PropsWithChildren, memo } from 'react';
import { useCallback, useState } from 'react'; import { useCallback, useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { ALL_BASE_MODELS } from 'services/api/constants'; import { ALL_BASE_MODELS } from 'services/api/constants';
@ -232,7 +232,7 @@ const ModelList = (props: ModelListProps) => {
); );
}; };
export default ModelList; export default memo(ModelList);
const modelsFilter = < const modelsFilter = <
T extends T extends
@ -266,7 +266,7 @@ const modelsFilter = <
return filteredModels; return filteredModels;
}; };
const StyledModelContainer = (props: PropsWithChildren) => { const StyledModelContainer = memo((props: PropsWithChildren) => {
return ( return (
<Flex <Flex
flexDirection="column" flexDirection="column"
@ -283,7 +283,9 @@ const StyledModelContainer = (props: PropsWithChildren) => {
{props.children} {props.children}
</Flex> </Flex>
); );
}; });
StyledModelContainer.displayName = 'StyledModelContainer';
type ModelListWrapperProps = { type ModelListWrapperProps = {
title: string; title: string;
@ -294,7 +296,7 @@ type ModelListWrapperProps = {
selected: ModelListProps; selected: ModelListProps;
}; };
function ModelListWrapper(props: ModelListWrapperProps) { const ModelListWrapper = memo((props: ModelListWrapperProps) => {
const { title, modelList, selected } = props; const { title, modelList, selected } = props;
return ( return (
<StyledModelContainer> <StyledModelContainer>
@ -313,23 +315,29 @@ function ModelListWrapper(props: ModelListWrapperProps) {
</Flex> </Flex>
</StyledModelContainer> </StyledModelContainer>
); );
} });
function FetchingModelsLoader({ loadingMessage }: { loadingMessage?: string }) { ModelListWrapper.displayName = 'ModelListWrapper';
return (
<StyledModelContainer> const FetchingModelsLoader = memo(
<Flex ({ loadingMessage }: { loadingMessage?: string }) => {
justifyContent="center" return (
alignItems="center" <StyledModelContainer>
flexDirection="column" <Flex
p={4} justifyContent="center"
gap={8} alignItems="center"
> flexDirection="column"
<Spinner /> p={4}
<Text variant="subtext"> gap={8}
{loadingMessage ? loadingMessage : 'Fetching...'} >
</Text> <Spinner />
</Flex> <Text variant="subtext">
</StyledModelContainer> {loadingMessage ? loadingMessage : 'Fetching...'}
); </Text>
} </Flex>
</StyledModelContainer>
);
}
);
FetchingModelsLoader.displayName = 'FetchingModelsLoader';

View File

@ -1,5 +1,6 @@
import { Box, Flex } from '@chakra-ui/react'; import { Box, Flex } from '@chakra-ui/react';
import CurrentImageDisplay from 'features/gallery/components/CurrentImage/CurrentImageDisplay'; import CurrentImageDisplay from 'features/gallery/components/CurrentImage/CurrentImageDisplay';
import { memo } from 'react';
const TextToImageTabMain = () => { const TextToImageTabMain = () => {
return ( return (
@ -25,4 +26,4 @@ const TextToImageTabMain = () => {
); );
}; };
export default TextToImageTabMain; export default memo(TextToImageTabMain);

View File

@ -9,6 +9,7 @@ import ParamSymmetryCollapse from 'features/parameters/components/Parameters/Sym
import ProcessButtons from 'features/parameters/components/ProcessButtons/ProcessButtons'; import ProcessButtons from 'features/parameters/components/ProcessButtons/ProcessButtons';
import ParamPromptArea from '../../../../parameters/components/Parameters/Prompt/ParamPromptArea'; import ParamPromptArea from '../../../../parameters/components/Parameters/Prompt/ParamPromptArea';
import TextToImageTabCoreParameters from './TextToImageTabCoreParameters'; import TextToImageTabCoreParameters from './TextToImageTabCoreParameters';
import { memo } from 'react';
const TextToImageTabParameters = () => { const TextToImageTabParameters = () => {
return ( return (
@ -28,4 +29,4 @@ const TextToImageTabParameters = () => {
); );
}; };
export default TextToImageTabParameters; export default memo(TextToImageTabParameters);

View File

@ -18,6 +18,7 @@ import { FaWrench } from 'react-icons/fa';
import ClearCanvasHistoryButtonModal from 'features/canvas/components/ClearCanvasHistoryButtonModal'; import ClearCanvasHistoryButtonModal from 'features/canvas/components/ClearCanvasHistoryButtonModal';
import { isEqual } from 'lodash-es'; import { isEqual } from 'lodash-es';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { memo } from 'react';
export const canvasControlsSelector = createSelector( export const canvasControlsSelector = createSelector(
[canvasSelector], [canvasSelector],
@ -109,4 +110,4 @@ const UnifiedCanvasSettings = () => {
); );
}; };
export default UnifiedCanvasSettings; export default memo(UnifiedCanvasSettings);

View File

@ -13,6 +13,7 @@ import {
} from 'features/canvas/store/canvasSlice'; } from 'features/canvas/store/canvasSlice';
import { systemSelector } from 'features/system/store/systemSelectors'; import { systemSelector } from 'features/system/store/systemSelectors';
import { isEqual } from 'lodash-es'; import { isEqual } from 'lodash-es';
import { memo } from 'react';
import { useHotkeys } from 'react-hotkeys-hook'; import { useHotkeys } from 'react-hotkeys-hook';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
@ -161,4 +162,4 @@ const UnifiedCanvasToolSelect = () => {
); );
}; };
export default UnifiedCanvasToolSelect; export default memo(UnifiedCanvasToolSelect);

View File

@ -14,6 +14,7 @@ import UnifiedCanvasResetCanvas from './UnifiedCanvasToolbar/UnifiedCanvasResetC
import UnifiedCanvasResetView from './UnifiedCanvasToolbar/UnifiedCanvasResetView'; import UnifiedCanvasResetView from './UnifiedCanvasToolbar/UnifiedCanvasResetView';
import UnifiedCanvasSaveToGallery from './UnifiedCanvasToolbar/UnifiedCanvasSaveToGallery'; import UnifiedCanvasSaveToGallery from './UnifiedCanvasToolbar/UnifiedCanvasSaveToGallery';
import UnifiedCanvasToolSelect from './UnifiedCanvasToolbar/UnifiedCanvasToolSelect'; import UnifiedCanvasToolSelect from './UnifiedCanvasToolbar/UnifiedCanvasToolSelect';
import { memo } from 'react';
const UnifiedCanvasToolbarBeta = () => { const UnifiedCanvasToolbarBeta = () => {
return ( return (
@ -51,4 +52,4 @@ const UnifiedCanvasToolbarBeta = () => {
); );
}; };
export default UnifiedCanvasToolbarBeta; export default memo(UnifiedCanvasToolbarBeta);

View File

@ -10,6 +10,7 @@ import ParamSeamPaintingCollapse from 'features/parameters/components/Parameters
import ParamPromptArea from 'features/parameters/components/Parameters/Prompt/ParamPromptArea'; import ParamPromptArea from 'features/parameters/components/Parameters/Prompt/ParamPromptArea';
import ProcessButtons from 'features/parameters/components/ProcessButtons/ProcessButtons'; import ProcessButtons from 'features/parameters/components/ProcessButtons/ProcessButtons';
import UnifiedCanvasCoreParameters from './UnifiedCanvasCoreParameters'; import UnifiedCanvasCoreParameters from './UnifiedCanvasCoreParameters';
import { memo } from 'react';
const UnifiedCanvasParameters = () => { const UnifiedCanvasParameters = () => {
return ( return (
@ -30,4 +31,4 @@ const UnifiedCanvasParameters = () => {
); );
}; };
export default UnifiedCanvasParameters; export default memo(UnifiedCanvasParameters);