feishin/src/renderer/components/virtual-grid/virtual-grid-wrapper.tsx
2025-05-26 17:20:02 -07:00

139 lines
3.2 KiB
TypeScript

import type {
CardRoute,
CardRow,
ListDisplayType,
PlayQueueAddOptions,
} from '/@/shared/types/types';
import type { Ref } from 'react';
import type { FixedSizeListProps } from 'react-window';
import debounce from 'lodash/debounce';
import memoize from 'memoize-one';
import { FixedSizeList } from 'react-window';
import styled from 'styled-components';
import { GridCard } from '/@/renderer/components/virtual-grid/grid-card';
import { Album, AlbumArtist, Artist, LibraryItem } from '/@/shared/types/domain-types';
const createItemData = memoize(
(
cardRows,
columnCount,
display,
itemCount,
itemData,
itemGap,
itemHeight,
itemType,
itemWidth,
route,
handlePlayQueueAdd,
handleFavorite,
resetInfiniteLoaderCache,
) => ({
cardRows,
columnCount,
display,
handleFavorite,
handlePlayQueueAdd,
itemCount,
itemData,
itemGap,
itemHeight,
itemType,
itemWidth,
resetInfiniteLoaderCache,
route,
}),
);
const createScrollHandler = memoize((onScroll) => debounce(onScroll, 250));
export const VirtualGridWrapper = ({
cardRows,
columnCount,
display,
handleFavorite,
handlePlayQueueAdd,
height,
initialScrollOffset,
itemCount,
itemData,
itemGap,
itemHeight,
itemType,
itemWidth,
onScroll,
refInstance,
resetInfiniteLoaderCache,
route,
rowCount,
width,
...rest
}: Omit<FixedSizeListProps, 'children' | 'height' | 'itemSize' | 'ref' | 'width'> & {
cardRows: CardRow<Album | AlbumArtist | Artist>[];
columnCount: number;
display: ListDisplayType;
handleFavorite?: (options: {
id: string[];
isFavorite: boolean;
itemType: LibraryItem;
}) => void;
handlePlayQueueAdd?: (options: PlayQueueAddOptions) => void;
height?: number;
itemData: any[];
itemGap: number;
itemHeight: number;
itemType: LibraryItem;
itemWidth: number;
refInstance: Ref<any>;
resetInfiniteLoaderCache: () => void;
route?: CardRoute;
rowCount: number;
width?: number;
}) => {
const memoizedItemData = createItemData(
cardRows,
columnCount,
display,
itemCount,
itemData,
itemGap,
itemHeight,
itemType,
itemWidth,
route,
handlePlayQueueAdd,
handleFavorite,
resetInfiniteLoaderCache,
);
const memoizedOnScroll = createScrollHandler(onScroll);
return (
<FixedSizeList
ref={refInstance}
{...rest}
height={(height && Number(height)) || 0}
initialScrollOffset={initialScrollOffset}
itemCount={rowCount}
itemData={memoizedItemData}
itemSize={itemHeight}
onScroll={memoizedOnScroll}
overscanCount={5}
width={(width && Number(width)) || 0}
>
{GridCard}
</FixedSizeList>
);
};
export const VirtualGridContainer = styled.div`
display: flex;
flex-direction: column;
height: 100%;
`;
export const VirtualGridAutoSizerContainer = styled.div`
flex: 1;
`;