feishin/src/renderer/features/playlists/components/playlist-list-grid-view.tsx

163 lines
5.9 KiB
TypeScript
Raw Normal View History

2023-07-15 11:21:44 -07:00
import { useQueryClient } from '@tanstack/react-query';
import { MutableRefObject, useCallback, useMemo } from 'react';
2023-07-29 10:56:19 -07:00
import AutoSizer, { Size } from 'react-virtualized-auto-sizer';
2023-07-15 11:21:44 -07:00
import { ListOnScrollProps } from 'react-window';
2023-07-19 17:14:00 -07:00
import { useListContext } from '../../../context/list-context';
import { useListStoreActions } from '../../../store/list.store';
2023-07-15 11:21:44 -07:00
import { controller } from '/@/renderer/api/controller';
import { queryKeys } from '/@/renderer/api/query-keys';
import { LibraryItem, Playlist, PlaylistListQuery, PlaylistListSort } from '/@/renderer/api/types';
import { PLAYLIST_CARD_ROWS } from '/@/renderer/components';
import {
VirtualGridAutoSizerContainer,
VirtualInfiniteGrid,
VirtualInfiniteGridRef,
} from '/@/renderer/components/virtual-grid';
import { usePlayQueueAdd } from '/@/renderer/features/player';
import { useCreateFavorite, useDeleteFavorite } from '/@/renderer/features/shared';
import { AppRoute } from '/@/renderer/router/routes';
2023-07-19 17:14:00 -07:00
import { useCurrentServer, useGeneralSettings, useListStoreByKey } from '/@/renderer/store';
2023-07-15 11:21:44 -07:00
import { CardRow, ListDisplayType } from '/@/renderer/types';
interface PlaylistListGridViewProps {
gridRef: MutableRefObject<VirtualInfiniteGridRef | null>;
itemCount?: number;
}
export const PlaylistListGridView = ({ gridRef, itemCount }: PlaylistListGridViewProps) => {
2023-07-19 17:14:00 -07:00
const { pageKey } = useListContext();
2023-07-15 11:21:44 -07:00
const queryClient = useQueryClient();
const server = useCurrentServer();
const handlePlayQueueAdd = usePlayQueueAdd();
2023-07-19 17:14:00 -07:00
const { display, grid, filter } = useListStoreByKey({ key: pageKey });
const { setGrid } = useListStoreActions();
const { defaultFullPlaylist } = useGeneralSettings();
2023-07-15 11:21:44 -07:00
const createFavoriteMutation = useCreateFavorite({});
const deleteFavoriteMutation = useDeleteFavorite({});
const handleFavorite = (options: {
id: string[];
isFavorite: boolean;
itemType: LibraryItem;
}) => {
const { id, itemType, isFavorite } = options;
if (isFavorite) {
deleteFavoriteMutation.mutate({
query: {
id,
type: itemType,
},
serverId: server?.id,
});
} else {
createFavoriteMutation.mutate({
query: {
id,
type: itemType,
},
serverId: server?.id,
});
}
};
const cardRows = useMemo(() => {
const rows: CardRow<Playlist>[] = defaultFullPlaylist
? [PLAYLIST_CARD_ROWS.nameFull]
: [PLAYLIST_CARD_ROWS.name];
2023-07-15 11:21:44 -07:00
2023-07-19 17:14:00 -07:00
switch (filter.sortBy) {
2023-07-15 11:21:44 -07:00
case PlaylistListSort.DURATION:
rows.push(PLAYLIST_CARD_ROWS.duration);
break;
case PlaylistListSort.NAME:
rows.push(PLAYLIST_CARD_ROWS.songCount);
break;
case PlaylistListSort.SONG_COUNT:
rows.push(PLAYLIST_CARD_ROWS.songCount);
break;
case PlaylistListSort.OWNER:
rows.push(PLAYLIST_CARD_ROWS.owner);
break;
case PlaylistListSort.PUBLIC:
rows.push(PLAYLIST_CARD_ROWS.public);
break;
case PlaylistListSort.UPDATED_AT:
break;
}
return rows;
2023-07-19 17:14:00 -07:00
}, [defaultFullPlaylist, filter.sortBy]);
2023-07-15 11:21:44 -07:00
const handleGridScroll = useCallback(
(e: ListOnScrollProps) => {
2023-07-19 17:14:00 -07:00
setGrid({ data: { scrollOffset: e.scrollOffset }, key: pageKey });
2023-07-15 11:21:44 -07:00
},
2023-07-19 17:14:00 -07:00
[pageKey, setGrid],
2023-07-15 11:21:44 -07:00
);
const fetch = useCallback(
async ({ skip, take }: { skip: number; take: number }) => {
if (!server) {
return [];
}
const query: PlaylistListQuery = {
limit: take,
startIndex: skip,
2023-07-19 17:14:00 -07:00
...filter,
2023-07-15 11:21:44 -07:00
_custom: {},
};
const queryKey = queryKeys.playlists.list(server?.id || '', query);
const playlists = await queryClient.fetchQuery(queryKey, async ({ signal }) =>
controller.getPlaylistList({
apiClientProps: {
server,
signal,
},
query,
}),
);
return playlists;
},
2023-07-19 17:14:00 -07:00
[filter, queryClient, server],
2023-07-15 11:21:44 -07:00
);
return (
<VirtualGridAutoSizerContainer>
<AutoSizer>
2023-07-29 10:56:19 -07:00
{({ height, width }: Size) => (
2023-07-15 11:21:44 -07:00
<VirtualInfiniteGrid
key={`playlist-list-${server?.id}`}
ref={gridRef}
cardRows={cardRows}
display={display || ListDisplayType.CARD}
fetchFn={fetch}
handleFavorite={handleFavorite}
handlePlayQueueAdd={handlePlayQueueAdd}
height={height}
initialScrollOffset={grid?.scrollOffset || 0}
itemCount={itemCount || 0}
itemGap={20}
itemSize={grid?.itemsPerRow || 5}
itemType={LibraryItem.PLAYLIST}
loading={itemCount === undefined || itemCount === null}
minimumBatchSize={40}
route={{
route: defaultFullPlaylist
? AppRoute.PLAYLISTS_DETAIL_SONGS
: AppRoute.PLAYLISTS_DETAIL,
2023-07-15 11:21:44 -07:00
slugs: [{ idProperty: 'id', slugProperty: 'playlistId' }],
}}
width={width}
onScroll={handleGridScroll}
/>
)}
</AutoSizer>
</VirtualGridAutoSizerContainer>
);
};