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 IAIButton from 'common/components/IAIButton';
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 { FaArrowRotateLeft } from 'react-icons/fa6';
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,
extendTheme,
} from '@chakra-ui/react';
import { ReactNode, useEffect, useMemo } from 'react';
import { ReactNode, memo, useEffect, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
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 { addToast, clearToastQueue } from 'features/system/store/systemSlice';
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.
@ -44,4 +44,4 @@ export const useAppToaster = () => {
return toaster;
};
export default Toaster;
export default memo(Toaster);

View File

@ -1,4 +1,5 @@
import { Box, Flex, Icon } from '@chakra-ui/react';
import { memo } from 'react';
import { FaExclamation } from 'react-icons/fa';
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 { memo } from 'react';
const IAIFillSkeleton = () => {
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 { memo } from 'react';
import { ImageDTO } from 'services/api/types';
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 { memo } from 'react';
import { useHotkeys } from 'react-hotkeys-hook';
type ImageUploadOverlayProps = {
@ -87,4 +88,4 @@ const ImageUploadOverlay = (props: ImageUploadOverlayProps) => {
</Box>
);
};
export default ImageUploadOverlay;
export default memo(ImageUploadOverlay);

View File

@ -1,4 +1,5 @@
import { Flex, Icon } from '@chakra-ui/react';
import { memo } from 'react';
import { FaImage } from 'react-icons/fa';
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 { memo } from 'react';
type Props = {
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 { FaTrash } from 'react-icons/fa';
import { isStagingSelector } from '../store/canvasSelectors';
import { memo } from 'react';
const ClearCanvasHistoryButtonModal = () => {
const isStaging = useAppSelector(isStagingSelector);
@ -28,4 +29,4 @@ const ClearCanvasHistoryButtonModal = () => {
</IAIAlertDialog>
);
};
export default ClearCanvasHistoryButtonModal;
export default memo(ClearCanvasHistoryButtonModal);

View File

@ -9,7 +9,7 @@ import {
import Konva from 'konva';
import { KonvaEventObject } from 'konva/lib/Node';
import { Vector2d } from 'konva/lib/types';
import { useCallback, useRef } from 'react';
import { memo, useCallback, useRef } from 'react';
import { Layer, Stage } from 'react-konva';
import useCanvasDragMove from '../hooks/useCanvasDragMove';
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 { canvasSelector } from '../store/canvasSelectors';
import { memo } from 'react';
const selector = createSelector(
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 { 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';
const selector = createSelector(
@ -117,4 +117,4 @@ const IAICanvasGrid = () => {
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 { CanvasImage } from '../store/canvasTypes';
import { $authToken } from 'services/api/client';
import { memo } from 'react';
type IAICanvasImageProps = {
canvasImage: CanvasImage;
@ -25,4 +26,4 @@ const IAICanvasImage = (props: IAICanvasImageProps) => {
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 { isEqual } from 'lodash-es';
import { useEffect, useState } from 'react';
import { memo, useEffect, useState } from 'react';
import { Image as KonvaImage } from 'react-konva';
import { canvasSelector } from '../store/canvasSelectors';
@ -66,4 +66,4 @@ const IAICanvasIntermediateImage = (props: Props) => {
) : 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 Konva from 'konva';
import { isNumber } from 'lodash-es';
import { useCallback, useEffect, useRef, useState } from 'react';
import { memo, useCallback, useEffect, useRef, useState } from 'react';
export const canvasMaskCompositerSelector = createSelector(
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 { isCanvasMaskLine } from '../store/canvasTypes';
import { memo } from 'react';
export const canvasLinesSelector = createSelector(
[canvasSelector],
@ -52,4 +53,4 @@ const IAICanvasLines = (props: InpaintingCanvasLinesProps) => {
);
};
export default IAICanvasLines;
export default memo(IAICanvasLines);

View File

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

View File

@ -12,7 +12,7 @@ import {
setDoesCanvasNeedScaling,
} from 'features/canvas/store/canvasSlice';
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
import { useLayoutEffect, useRef } from 'react';
import { memo, useLayoutEffect, useRef } from 'react';
const canvasResizerSelector = createSelector(
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 IAICanvasImage from './IAICanvasImage';
import { memo } from 'react';
const selector = createSelector(
[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';
import { isEqual } from 'lodash-es';
import { useCallback } from 'react';
import { memo, useCallback } from 'react';
import { useHotkeys } from 'react-hotkeys-hook';
import { useTranslation } from 'react-i18next';
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 roundToHundreth from '../util/roundToHundreth';
import IAICanvasStatusTextCursorPos from './IAICanvasStatusText/IAICanvasStatusTextCursorPos';
import { memo } from 'react';
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_STROKE_RADIUS,
} from '../util/constants';
import { memo } from 'react';
const canvasBrushPreviewSelector = createSelector(
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 { 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 { 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';
import { rgbaColorToString } from 'features/canvas/util/colorToString';
import { isEqual } from 'lodash-es';
import { memo } from 'react';
import { useHotkeys } from 'react-hotkeys-hook';
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';
import { isEqual } from 'lodash-es';
import { ChangeEvent } from 'react';
import { ChangeEvent, memo } from 'react';
import { useHotkeys } from 'react-hotkeys-hook';
import { useTranslation } from 'react-i18next';
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';
import { systemSelector } from 'features/system/store/systemSelectors';
import { clamp, isEqual } from 'lodash-es';
import { memo } from 'react';
import { useHotkeys } from 'react-hotkeys-hook';
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 IAICanvasToolChooserOptions from './IAICanvasToolChooserOptions';
import IAICanvasUndoButton from './IAICanvasUndoButton';
import { memo } from 'react';
export const selector = createSelector(
[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 IAISwitch from 'common/components/IAISwitch';
import { isControlNetEnabledToggled } from 'features/controlNet/store/controlNetSlice';
import { useCallback } from 'react';
import { memo, useCallback } from 'react';
const selector = createSelector(
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 ParamDynamicPromptsMaxPrompts from './ParamDynamicPromptsMaxPrompts';
import { useFeatureStatus } from '../../system/hooks/useFeatureStatus';
import { memo } from 'react';
const selector = createSelector(
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 { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
import IAISwitch from 'common/components/IAISwitch';
import { useCallback } from 'react';
import { memo, useCallback } from 'react';
import { combinatorialToggled } from '../store/dynamicPromptsSlice';
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 { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
import IAISwitch from 'common/components/IAISwitch';
import { useCallback } from 'react';
import { memo, useCallback } from 'react';
import { isEnabledToggled } from '../store/dynamicPromptsSlice';
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 { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
import IAISlider from 'common/components/IAISlider';
import { useCallback } from 'react';
import { memo, useCallback } from 'react';
import {
maxPromptsChanged,
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 { MODEL_TYPE_MAP } from 'features/parameters/types/constants';
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 { 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 { memo } from 'react';
const AutoAddIcon = () => {
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 IAIMantineSelectItemWithTooltip from 'common/components/IAIMantineSelectItemWithTooltip';
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';
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;
};
const BoardContextMenu = memo(
({ board, board_id, setBoardToDelete, children }: Props) => {
const dispatch = useAppDispatch();
const BoardContextMenu = ({
board,
board_id,
setBoardToDelete,
children,
}: Props) => {
const dispatch = useAppDispatch();
const selector = useMemo(
() =>
createSelector(stateSelector, ({ gallery, system }) => {
const isAutoAdd = gallery.autoAddBoardId === board_id;
const isProcessing = system.isProcessing;
const autoAssignBoardOnClick = gallery.autoAssignBoardOnClick;
return { isAutoAdd, isProcessing, autoAssignBoardOnClick };
}),
[board_id]
);
const selector = useMemo(
() =>
createSelector(stateSelector, ({ gallery, system }) => {
const isAutoAdd = gallery.autoAddBoardId === board_id;
const isProcessing = system.isProcessing;
const autoAssignBoardOnClick = gallery.autoAssignBoardOnClick;
return { isAutoAdd, isProcessing, autoAssignBoardOnClick };
}),
[board_id]
);
const { isAutoAdd, isProcessing, autoAssignBoardOnClick } =
useAppSelector(selector);
const boardName = useBoardName(board_id);
const { isAutoAdd, isProcessing, autoAssignBoardOnClick } =
useAppSelector(selector);
const boardName = useBoardName(board_id);
const handleSetAutoAdd = useCallback(() => {
dispatch(autoAddBoardIdChanged(board_id));
}, [board_id, dispatch]);
const handleSetAutoAdd = useCallback(() => {
dispatch(autoAddBoardIdChanged(board_id));
}, [board_id, dispatch]);
const skipEvent = useCallback((e: MouseEvent<HTMLDivElement>) => {
e.preventDefault();
}, []);
const skipEvent = useCallback((e: MouseEvent<HTMLDivElement>) => {
e.preventDefault();
}, []);
return (
<IAIContextMenu<HTMLDivElement>
menuProps={{ size: 'sm', isLazy: true }}
menuButtonProps={{
bg: 'transparent',
_hover: { bg: 'transparent' },
}}
renderMenu={() => (
<MenuList
sx={{ visibility: 'visible !important' }}
motionProps={menuListMotionProps}
onContextMenu={skipEvent}
>
<MenuGroup title={boardName}>
<MenuItem
icon={<FaPlus />}
isDisabled={isAutoAdd || isProcessing || autoAssignBoardOnClick}
onClick={handleSetAutoAdd}
>
Auto-add to this Board
</MenuItem>
{!board && <NoBoardContextMenuItems />}
{board && (
<GalleryBoardContextMenuItems
board={board}
setBoardToDelete={setBoardToDelete}
/>
)}
</MenuGroup>
</MenuList>
)}
>
{children}
</IAIContextMenu>
);
}
);
return (
<IAIContextMenu<HTMLDivElement>
menuProps={{ size: 'sm', isLazy: true }}
menuButtonProps={{
bg: 'transparent',
_hover: { bg: 'transparent' },
}}
renderMenu={() => (
<MenuList
sx={{ visibility: 'visible !important' }}
motionProps={menuListMotionProps}
onContextMenu={skipEvent}
>
<MenuGroup title={boardName}>
<MenuItem
icon={<FaPlus />}
isDisabled={isAutoAdd || isProcessing || autoAssignBoardOnClick}
onClick={handleSetAutoAdd}
>
Auto-add to this Board
</MenuItem>
{!board && <NoBoardContextMenuItems />}
{board && (
<GalleryBoardContextMenuItems
board={board}
setBoardToDelete={setBoardToDelete}
/>
)}
</MenuGroup>
</MenuList>
)}
>
{children}
</IAIContextMenu>
);
};
BoardContextMenu.displayName = 'HoverableBoard';
export default BoardContextMenu;
export default memo(BoardContextMenu);

View File

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

View File

@ -26,7 +26,7 @@ import {
setShouldShowImageDetails,
setShouldShowProgressInViewer,
} from 'features/ui/store/uiSlice';
import { useCallback } from 'react';
import { memo, useCallback } from 'react';
import { useHotkeys } from 'react-hotkeys-hook';
import { useTranslation } from 'react-i18next';
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 CurrentImagePreview from './CurrentImagePreview';
import { memo } from 'react';
const CurrentImageDisplay = () => {
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 { memo } from 'react';
import { FaEyeSlash } from 'react-icons/fa';
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 { requestCanvasRescale } from 'features/canvas/store/thunks/requestCanvasScale';
import { togglePinGalleryPanel } from 'features/ui/store/uiSlice';
import { memo } from 'react';
import { useTranslation } from 'react-i18next';
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,
shouldAutoSwitchChanged,
} from 'features/gallery/store/gallerySlice';
import { ChangeEvent, useCallback } from 'react';
import { ChangeEvent, memo, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { FaWrench } from 'react-icons/fa';
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,
} from 'features/changeBoardModal/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 { MdStar, MdStarBorder } from 'react-icons/md';
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 { memo } from 'react';
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 { PropsWithChildren } from 'react';
import { PropsWithChildren, memo } from 'react';
type ItemContainerProps = PropsWithChildren & FlexProps;
const ItemContainer = forwardRef((props: ItemContainerProps, ref) => (
@ -8,4 +8,4 @@ const ItemContainer = forwardRef((props: ItemContainerProps, ref) => (
</Box>
));
export default ItemContainer;
export default memo(ItemContainer);

View File

@ -1,7 +1,7 @@
import { FlexProps, Grid, forwardRef } from '@chakra-ui/react';
import { RootState } from 'app/store/store';
import { useAppSelector } from 'app/store/storeHooks';
import { PropsWithChildren } from 'react';
import { PropsWithChildren, memo } from 'react';
type ListContainerProps = PropsWithChildren & FlexProps;
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 { isString } from 'lodash-es';
import { OverlayScrollbarsComponent } from 'overlayscrollbars-react';
import { useCallback, useMemo } from 'react';
import { memo, useCallback, useMemo } from 'react';
import { FaCopy, FaSave } from 'react-icons/fa';
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 { useCallback } from 'react';
import { memo, useCallback } from 'react';
import { UnsafeImageMetadata } from 'services/api/types';
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 { Flex, IconButton, Link, Text, Tooltip } from '@chakra-ui/react';
import { memo } from 'react';
import { useTranslation } from 'react-i18next';
import { FaCopy } from 'react-icons/fa';
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 { map } from 'lodash-es';
import ParamLora from './ParamLora';
import { memo } from 'react';
const selector = createSelector(
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 { MODEL_TYPE_MAP } from 'features/parameters/types/constants';
import { forEach } from 'lodash-es';
import { useCallback, useMemo } from 'react';
import { memo, useCallback, useMemo } from 'react';
import { useGetLoRAModelsQuery } from 'services/api/endpoints/models';
const selector = createSelector(
@ -102,4 +102,4 @@ const ParamLoRASelect = () => {
);
};
export default ParamLoRASelect;
export default memo(ParamLoRASelect);

View File

@ -7,7 +7,7 @@ import {
isInputFieldValue,
} from 'features/nodes/types/types';
import { startCase } from 'lodash-es';
import { useMemo } from 'react';
import { memo, useMemo } from 'react';
interface Props {
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<{
shouldDim: boolean;

View File

@ -1,6 +1,6 @@
import { Box, Flex } from '@chakra-ui/react';
import { OverlayScrollbarsComponent } from 'overlayscrollbars-react';
import { PropsWithChildren } from 'react';
import { PropsWithChildren, memo } from 'react';
const ScrollableContent = (props: PropsWithChildren) => {
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 { useCanvasGenerationMode } from 'features/canvas/hooks/useCanvasGenerationMode';
import { memo } from 'react';
const GENERATION_MODE_NAME_MAP = {
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 ParamEmbeddingPopover from 'features/embedding/components/ParamEmbeddingPopover';
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 { useTranslation } from 'react-i18next';
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 { stateSelector } from 'app/store/store';
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 {
@ -159,4 +159,4 @@ const ParamPositiveConditioning = () => {
);
};
export default ParamPositiveConditioning;
export default memo(ParamPositiveConditioning);

View File

@ -9,7 +9,7 @@ import {
TypesafeDraggableData,
TypesafeDroppableData,
} from 'features/dnd/types';
import { useMemo } from 'react';
import { memo, useMemo } from 'react';
import { useGetImageDTOQuery } from 'services/api/endpoints/images';
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 { useImageUploadButton } from 'common/hooks/useImageUploadButton';
import { clearInitialImage } from 'features/parameters/store/generationSlice';
import { useCallback } from 'react';
import { memo, useCallback } from 'react';
import { FaUndo, FaUpload } from 'react-icons/fa';
import InitialImage from './InitialImage';
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 IAIPopover from 'common/components/IAIPopover';
import { selectIsBusy } from 'features/system/store/systemSelectors';
import { useCallback } from 'react';
import { memo, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { FaExpandArrowsAlt } from 'react-icons/fa';
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 CancelButton from './CancelButton';
import InvokeButton from './InvokeButton';
import { memo } from 'react';
/**
* 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 { stateSelector } from 'app/store/store';
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 { 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 { stateSelector } from 'app/store/store';
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 { 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 ParamSDXLRefinerSteps from './SDXLRefiner/ParamSDXLRefinerSteps';
import ParamUseSDXLRefiner from './SDXLRefiner/ParamUseSDXLRefiner';
import { memo } from 'react';
const selector = createSelector(
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 ParamSDXLRefinerCollapse from './ParamSDXLRefinerCollapse';
import SDXLImageToImageTabCoreParameters from './SDXLImageToImageTabCoreParameters';
import { memo } from 'react';
const SDXLImageToImageTabParameters = () => {
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 ParamSDXLPromptArea from './ParamSDXLPromptArea';
import ParamSDXLRefinerCollapse from './ParamSDXLRefinerCollapse';
import { memo } from 'react';
const SDXLTextToImageTabParameters = () => {
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 InvokeAILogoImage from 'assets/images/logo.png';
import { AnimatePresence, motion } from 'framer-motion';
import { useRef } from 'react';
import { memo, useRef } from 'react';
import { useHoverDirty } from 'react-use';
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,
ReactElement,
cloneElement,
memo,
useCallback,
useEffect,
} 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 { PropsWithChildren } from 'react';
import { PropsWithChildren, memo } from 'react';
const StyledFlex = (props: PropsWithChildren) => {
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 { AnimatePresence, motion } from 'framer-motion';
import { ResourceKey } from 'i18next';
import { useMemo, useRef } from 'react';
import { memo, useMemo, useRef } from 'react';
import { useTranslation } from 'react-i18next';
import { FaCircle } from 'react-icons/fa';
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 { BsPinAngle, BsPinAngleFill } from 'react-icons/bs';
import { setShouldPinParametersPanel } from '../store/uiSlice';
import { memo } from 'react';
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,
ResizeStartCallback,
} 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 {
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 ProcessButtons from 'features/parameters/components/ProcessButtons/ProcessButtons';
import ImageToImageTabCoreParameters from './ImageToImageTabCoreParameters';
import { memo } from 'react';
const ImageToImageTabParameters = () => {
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 IAIInput from 'common/components/IAIInput';
import { forEach } from 'lodash-es';
import type { ChangeEvent, PropsWithChildren } from 'react';
import { ChangeEvent, PropsWithChildren, memo } from 'react';
import { useCallback, useState } from 'react';
import { useTranslation } from 'react-i18next';
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 = <
T extends
@ -266,7 +266,7 @@ const modelsFilter = <
return filteredModels;
};
const StyledModelContainer = (props: PropsWithChildren) => {
const StyledModelContainer = memo((props: PropsWithChildren) => {
return (
<Flex
flexDirection="column"
@ -283,7 +283,9 @@ const StyledModelContainer = (props: PropsWithChildren) => {
{props.children}
</Flex>
);
};
});
StyledModelContainer.displayName = 'StyledModelContainer';
type ModelListWrapperProps = {
title: string;
@ -294,7 +296,7 @@ type ModelListWrapperProps = {
selected: ModelListProps;
};
function ModelListWrapper(props: ModelListWrapperProps) {
const ModelListWrapper = memo((props: ModelListWrapperProps) => {
const { title, modelList, selected } = props;
return (
<StyledModelContainer>
@ -313,23 +315,29 @@ function ModelListWrapper(props: ModelListWrapperProps) {
</Flex>
</StyledModelContainer>
);
}
});
function FetchingModelsLoader({ loadingMessage }: { loadingMessage?: string }) {
return (
<StyledModelContainer>
<Flex
justifyContent="center"
alignItems="center"
flexDirection="column"
p={4}
gap={8}
>
<Spinner />
<Text variant="subtext">
{loadingMessage ? loadingMessage : 'Fetching...'}
</Text>
</Flex>
</StyledModelContainer>
);
}
ModelListWrapper.displayName = 'ModelListWrapper';
const FetchingModelsLoader = memo(
({ loadingMessage }: { loadingMessage?: string }) => {
return (
<StyledModelContainer>
<Flex
justifyContent="center"
alignItems="center"
flexDirection="column"
p={4}
gap={8}
>
<Spinner />
<Text variant="subtext">
{loadingMessage ? loadingMessage : 'Fetching...'}
</Text>
</Flex>
</StyledModelContainer>
);
}
);
FetchingModelsLoader.displayName = 'FetchingModelsLoader';

View File

@ -1,5 +1,6 @@
import { Box, Flex } from '@chakra-ui/react';
import CurrentImageDisplay from 'features/gallery/components/CurrentImage/CurrentImageDisplay';
import { memo } from 'react';
const TextToImageTabMain = () => {
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 ParamPromptArea from '../../../../parameters/components/Parameters/Prompt/ParamPromptArea';
import TextToImageTabCoreParameters from './TextToImageTabCoreParameters';
import { memo } from 'react';
const TextToImageTabParameters = () => {
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 { isEqual } from 'lodash-es';
import { useTranslation } from 'react-i18next';
import { memo } from 'react';
export const canvasControlsSelector = createSelector(
[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';
import { systemSelector } from 'features/system/store/systemSelectors';
import { isEqual } from 'lodash-es';
import { memo } from 'react';
import { useHotkeys } from 'react-hotkeys-hook';
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 UnifiedCanvasSaveToGallery from './UnifiedCanvasToolbar/UnifiedCanvasSaveToGallery';
import UnifiedCanvasToolSelect from './UnifiedCanvasToolbar/UnifiedCanvasToolSelect';
import { memo } from 'react';
const UnifiedCanvasToolbarBeta = () => {
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 ProcessButtons from 'features/parameters/components/ProcessButtons/ProcessButtons';
import UnifiedCanvasCoreParameters from './UnifiedCanvasCoreParameters';
import { memo } from 'react';
const UnifiedCanvasParameters = () => {
return (
@ -30,4 +31,4 @@ const UnifiedCanvasParameters = () => {
);
};
export default UnifiedCanvasParameters;
export default memo(UnifiedCanvasParameters);