perf(ui): improved gallery perf

This commit is contained in:
psychedelicious
2024-10-27 19:22:07 +10:00
parent b6b9ea9d70
commit 8c8e7102c2
3 changed files with 14 additions and 25 deletions

View File

@@ -9,14 +9,12 @@ import { $customStarUI } from 'app/store/nanostores/customStarUI';
import { useAppStore } from 'app/store/nanostores/store';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import IAIDndImageIcon from 'common/components/IAIDndImageIcon';
import IAIFillSkeleton from 'common/components/IAIFillSkeleton';
import { useBoolean } from 'common/hooks/useBoolean';
import { imagesToDeleteSelected } from 'features/deleteImageModal/store/slice';
import { multipleImageDndSource, singleImageDndSource } from 'features/dnd2/types';
import { useImageContextMenu } from 'features/gallery/components/ImageContextMenu/ImageContextMenu';
import { getGalleryImageDataTestId } from 'features/gallery/components/ImageGrid/getGalleryImageDataTestId';
import { useImageViewer } from 'features/gallery/components/ImageViewer/useImageViewer';
import { useScrollIntoView } from 'features/gallery/hooks/useScrollIntoView';
import { imageToCompareChanged, selectGallerySlice } from 'features/gallery/store/gallerySlice';
import type { MouseEvent, MouseEventHandler } from 'react';
import { memo, useCallback, useEffect, useMemo, useState } from 'react';
@@ -81,7 +79,6 @@ const galleryImageContainerSX = {
interface HoverableImageProps {
imageDTO: ImageDTO;
index: number;
}
const selectAlwaysShouldImageSizeBadge = createSelector(
@@ -89,17 +86,7 @@ const selectAlwaysShouldImageSizeBadge = createSelector(
(gallery) => gallery.alwaysShowImageSizeBadge
);
export const GalleryImage = memo(({ index, imageDTO }: HoverableImageProps) => {
if (!imageDTO) {
return <IAIFillSkeleton />;
}
return <GalleryImageContent index={index} imageDTO={imageDTO} />;
});
GalleryImage.displayName = 'GalleryImage';
const GalleryImageContent = memo(({ index, imageDTO }: HoverableImageProps) => {
export const GalleryImage = memo(({ imageDTO }: HoverableImageProps) => {
const store = useAppStore();
const [isDragging, setIsDragging] = useState(false);
const [element, ref] = useState<HTMLImageElement | null>(null);
@@ -118,8 +105,6 @@ const GalleryImageContent = memo(({ index, imageDTO }: HoverableImageProps) => {
);
const isSelected = useAppSelector(selectIsSelected);
useScrollIntoView(element, isSelected, index);
useEffect(() => {
if (!element) {
return;
@@ -224,7 +209,7 @@ const GalleryImageContent = memo(({ index, imageDTO }: HoverableImageProps) => {
);
});
GalleryImageContent.displayName = 'GalleryImageContent';
GalleryImage.displayName = 'GalleryImage';
const HoverIcons = memo(({ imageDTO, isHovered }: { imageDTO: ImageDTO; isHovered: boolean }) => {
const alwaysShowImageSizeBadge = useAppSelector(selectAlwaysShouldImageSizeBadge);

View File

@@ -20,9 +20,9 @@ const GalleryImageGrid = () => {
useGalleryHotkeys();
const { t } = useTranslation();
const queryArgs = useAppSelector(selectListImagesQueryArgs);
const { imageDTOs, isLoading, isError } = useListImagesQuery(queryArgs, {
const { hasImages, isLoading, isError } = useListImagesQuery(queryArgs, {
selectFromResult: ({ data, isLoading, isSuccess, isError }) => ({
imageDTOs: data?.items ?? EMPTY_ARRAY,
hasImages: data && data.items.length > 0,
isLoading,
isSuccess,
isError,
@@ -45,7 +45,7 @@ const GalleryImageGrid = () => {
);
}
if (imageDTOs.length === 0) {
if (!hasImages) {
return (
<Flex w="full" h="full" alignItems="center" justifyContent="center">
<IAINoContentFallback label={t('gallery.noImagesInGallery')} icon={PiImageBold} />
@@ -53,12 +53,12 @@ const GalleryImageGrid = () => {
);
}
return <Content />;
return <GalleryImageGridContent />;
};
export default memo(GalleryImageGrid);
const Content = () => {
const GalleryImageGridContent = memo(() => {
const dispatch = useAppDispatch();
const galleryImageMinimumWidth = useAppSelector(selectGalleryImageMinimumWidth);
@@ -178,12 +178,14 @@ const Content = () => {
gridTemplateColumns={`repeat(auto-fill, minmax(${galleryImageMinimumWidth}px, 1fr))`}
gap={1}
>
{imageDTOs.map((imageDTO, index) => (
<GalleryImage key={imageDTO.image_name} imageDTO={imageDTO} index={index} />
{imageDTOs.map((imageDTO) => (
<GalleryImage key={imageDTO.image_name} imageDTO={imageDTO} />
))}
</Grid>
</Box>
<GallerySelectionCountTag />
</Box>
);
};
});
GalleryImageGridContent.displayName = 'GalleryImageGridContent';

View File

@@ -17,6 +17,8 @@ import { useEffect } from 'react';
* @param isSelected Whether the image is selected.
* @param index The index of the image in the gallery.
* @returns
*
* @knip-ignore
*/
export const useScrollIntoView = (imageContainerRef: HTMLElement | null, isSelected: boolean, index: number) => {
const areMultiplesSelected = useAppSelector(selectHasMultipleImagesSelected);