Use memoized carousel component for pages

This commit is contained in:
jeffvli 2023-07-21 18:03:19 -07:00
parent 74384639de
commit a8dfc7bcd6
3 changed files with 148 additions and 145 deletions

View file

@ -1,40 +1,36 @@
import { MutableRefObject, useCallback, useMemo } from 'react';
import { Button } from '/@/renderer/components';
import { ColDef, RowDoubleClickedEvent, RowHeightParams, RowNode } from '@ag-grid-community/core'; import { ColDef, RowDoubleClickedEvent, RowHeightParams, RowNode } from '@ag-grid-community/core';
import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact'; import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact';
import { Box, Group, Stack } from '@mantine/core'; import { Box, Group, Stack } from '@mantine/core';
import { useSetState } from '@mantine/hooks'; import { useSetState } from '@mantine/hooks';
import { MutableRefObject, useCallback, useMemo } from 'react';
import { RiHeartFill, RiHeartLine, RiMoreFill } from 'react-icons/ri'; import { RiHeartFill, RiHeartLine, RiMoreFill } from 'react-icons/ri';
import { generatePath, useParams } from 'react-router'; import { generatePath, useParams } from 'react-router';
import { useAlbumDetail } from '/@/renderer/features/albums/queries/album-detail-query';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import styled from 'styled-components'; import styled from 'styled-components';
import { AppRoute } from '/@/renderer/router/routes'; import { AlbumListSort, LibraryItem, QueueSong, SortOrder } from '/@/renderer/api/types';
import { useContainerQuery } from '/@/renderer/hooks'; import { Button } from '/@/renderer/components';
import { PersistedTableColumn, usePlayButtonBehavior } from '/@/renderer/store/settings.store'; import { MemoizedSwiperGridCarousel } from '/@/renderer/components/grid-carousel';
import { getColumnDefs, VirtualTable } from '/@/renderer/components/virtual-table';
import { FullWidthDiscCell } from '/@/renderer/components/virtual-table/cells/full-width-disc-cell';
import { useCurrentSongRowStyles } from '/@/renderer/components/virtual-table/hooks/use-current-song-row-styles';
import { useAlbumDetail } from '/@/renderer/features/albums/queries/album-detail-query';
import { useAlbumList } from '/@/renderer/features/albums/queries/album-list-query';
import { import {
useHandleGeneralContextMenu, useHandleGeneralContextMenu,
useHandleTableContextMenu, useHandleTableContextMenu,
} from '/@/renderer/features/context-menu'; } from '/@/renderer/features/context-menu';
import { Play, ServerType, TableColumn } from '/@/renderer/types';
import { import {
ALBUM_CONTEXT_MENU_ITEMS, ALBUM_CONTEXT_MENU_ITEMS,
SONG_CONTEXT_MENU_ITEMS, SONG_CONTEXT_MENU_ITEMS,
} from '/@/renderer/features/context-menu/context-menu-items'; } from '/@/renderer/features/context-menu/context-menu-items';
import { PlayButton, useCreateFavorite, useDeleteFavorite } from '/@/renderer/features/shared';
import { useAlbumList } from '/@/renderer/features/albums/queries/album-list-query';
import { AlbumListSort, LibraryItem, QueueSong, SortOrder } from '/@/renderer/api/types';
import { usePlayQueueAdd } from '/@/renderer/features/player'; import { usePlayQueueAdd } from '/@/renderer/features/player';
import { useCurrentServer } from '/@/renderer/store'; import { PlayButton, useCreateFavorite, useDeleteFavorite } from '/@/renderer/features/shared';
import {
getColumnDefs,
useFixedTableHeader,
VirtualTable,
} from '/@/renderer/components/virtual-table';
import { SwiperGridCarousel } from '/@/renderer/components/grid-carousel';
import { FullWidthDiscCell } from '/@/renderer/components/virtual-table/cells/full-width-disc-cell';
import { useCurrentSongRowStyles } from '/@/renderer/components/virtual-table/hooks/use-current-song-row-styles';
import { LibraryBackgroundOverlay } from '/@/renderer/features/shared/components/library-background-overlay'; import { LibraryBackgroundOverlay } from '/@/renderer/features/shared/components/library-background-overlay';
import { useContainerQuery } from '/@/renderer/hooks';
import { AppRoute } from '/@/renderer/router/routes';
import { useCurrentServer } from '/@/renderer/store';
import { PersistedTableColumn, usePlayButtonBehavior } from '/@/renderer/store/settings.store';
import { Play, ServerType, TableColumn } from '/@/renderer/types';
const isFullWidthRow = (node: RowNode) => { const isFullWidthRow = (node: RowNode) => {
return node.id?.startsWith('disc-'); return node.id?.startsWith('disc-');
@ -373,59 +369,55 @@ export const AlbumDetailContent = ({ tableRef, background }: AlbumDetailContentP
ref={cq.ref} ref={cq.ref}
mt="5rem" mt="5rem"
> >
<> {cq.height || cq.width ? (
{cq.height || cq.width ? ( <>
<> {carousels
{carousels .filter((c) => !c.isHidden)
.filter((c) => !c.isHidden) .map((carousel, index) => (
.map((carousel, index) => ( <MemoizedSwiperGridCarousel
<SwiperGridCarousel key={`carousel-${carousel.uniqueId}-${index}`}
key={`carousel-${carousel.uniqueId}-${index}`} cardRows={[
cardRows={[ {
{ property: 'name',
property: 'name', route: {
route: { route: AppRoute.LIBRARY_ALBUMS_DETAIL,
route: AppRoute.LIBRARY_ALBUMS_DETAIL, slugs: [
slugs: [ {
{ idProperty: 'id',
idProperty: 'id', slugProperty: 'albumId',
slugProperty: 'albumId', },
}, ],
],
},
}, },
{ },
arrayProperty: 'name', {
property: 'albumArtists', arrayProperty: 'name',
route: { property: 'albumArtists',
route: AppRoute.LIBRARY_ALBUM_ARTISTS_DETAIL, route: {
slugs: [ route: AppRoute.LIBRARY_ALBUM_ARTISTS_DETAIL,
{ slugs: [
idProperty: 'id', {
slugProperty: 'albumArtistId', idProperty: 'id',
}, slugProperty: 'albumArtistId',
], },
}, ],
}, },
]} },
data={carousel.data} ]}
isLoading={carousel.loading} data={carousel.data}
itemType={LibraryItem.ALBUM} isLoading={carousel.loading}
route={{ itemType={LibraryItem.ALBUM}
route: AppRoute.LIBRARY_ALBUMS_DETAIL, route={{
slugs: [ route: AppRoute.LIBRARY_ALBUMS_DETAIL,
{ idProperty: 'id', slugProperty: 'albumId' }, slugs: [{ idProperty: 'id', slugProperty: 'albumId' }],
], }}
}} title={{
title={{ label: carousel.title,
label: carousel.title, }}
}} uniqueId={carousel.uniqueId}
uniqueId={carousel.uniqueId} />
/> ))}
))} </>
</> ) : null}
) : null}
</>
</Stack> </Stack>
</DetailContainer> </DetailContainer>
</ContentContainer> </ContentContainer>

View file

@ -1,26 +1,10 @@
import { useMemo } from 'react';
import { Button, Text, TextTitle } from '/@/renderer/components';
import { ColDef, RowDoubleClickedEvent } from '@ag-grid-community/core'; import { ColDef, RowDoubleClickedEvent } from '@ag-grid-community/core';
import { Box, Group, Stack } from '@mantine/core'; import { Box, Group, Stack } from '@mantine/core';
import { useMemo } from 'react';
import { RiHeartFill, RiHeartLine, RiMoreFill } from 'react-icons/ri'; import { RiHeartFill, RiHeartLine, RiMoreFill } from 'react-icons/ri';
import { generatePath, useParams } from 'react-router'; import { generatePath, useParams } from 'react-router';
import { useCurrentServer } from '/@/renderer/store';
import { createSearchParams, Link } from 'react-router-dom'; import { createSearchParams, Link } from 'react-router-dom';
import styled from 'styled-components'; import styled from 'styled-components';
import { AppRoute } from '/@/renderer/router/routes';
import { useContainerQuery } from '/@/renderer/hooks';
import { usePlayButtonBehavior } from '/@/renderer/store/settings.store';
import {
useHandleGeneralContextMenu,
useHandleTableContextMenu,
} from '/@/renderer/features/context-menu';
import { CardRow, Play, TableColumn } from '/@/renderer/types';
import {
ARTIST_CONTEXT_MENU_ITEMS,
SONG_CONTEXT_MENU_ITEMS,
} from '/@/renderer/features/context-menu/context-menu-items';
import { PlayButton, useCreateFavorite, useDeleteFavorite } from '/@/renderer/features/shared';
import { useAlbumList } from '/@/renderer/features/albums/queries/album-list-query';
import { import {
Album, Album,
AlbumArtist, AlbumArtist,
@ -30,12 +14,28 @@ import {
ServerType, ServerType,
SortOrder, SortOrder,
} from '/@/renderer/api/types'; } from '/@/renderer/api/types';
import { usePlayQueueAdd } from '/@/renderer/features/player'; import { Button, Text, TextTitle } from '/@/renderer/components';
import { MemoizedSwiperGridCarousel } from '/@/renderer/components/grid-carousel';
import { getColumnDefs, VirtualTable } from '/@/renderer/components/virtual-table';
import { useAlbumList } from '/@/renderer/features/albums/queries/album-list-query';
import { useAlbumArtistDetail } from '/@/renderer/features/artists/queries/album-artist-detail-query'; import { useAlbumArtistDetail } from '/@/renderer/features/artists/queries/album-artist-detail-query';
import { useTopSongsList } from '/@/renderer/features/artists/queries/top-songs-list-query'; import { useTopSongsList } from '/@/renderer/features/artists/queries/top-songs-list-query';
import { getColumnDefs, VirtualTable } from '/@/renderer/components/virtual-table'; import {
import { SwiperGridCarousel } from '/@/renderer/components/grid-carousel'; useHandleGeneralContextMenu,
useHandleTableContextMenu,
} from '/@/renderer/features/context-menu';
import {
ARTIST_CONTEXT_MENU_ITEMS,
SONG_CONTEXT_MENU_ITEMS,
} from '/@/renderer/features/context-menu/context-menu-items';
import { usePlayQueueAdd } from '/@/renderer/features/player';
import { PlayButton, useCreateFavorite, useDeleteFavorite } from '/@/renderer/features/shared';
import { LibraryBackgroundOverlay } from '/@/renderer/features/shared/components/library-background-overlay'; import { LibraryBackgroundOverlay } from '/@/renderer/features/shared/components/library-background-overlay';
import { useContainerQuery } from '/@/renderer/hooks';
import { AppRoute } from '/@/renderer/router/routes';
import { useCurrentServer } from '/@/renderer/store';
import { usePlayButtonBehavior } from '/@/renderer/store/settings.store';
import { CardRow, Play, TableColumn } from '/@/renderer/types';
const ContentContainer = styled.div` const ContentContainer = styled.div`
position: relative; position: relative;
@ -195,64 +195,74 @@ export const AlbumArtistDetailContent = ({ background }: AlbumArtistDetailConten
}, },
}; };
const carousels = [ const carousels = useMemo(() => {
{ return [
data: recentAlbumsQuery?.data?.items, {
isHidden: !recentAlbumsQuery?.data?.items?.length, data: recentAlbumsQuery?.data?.items,
itemType: LibraryItem.ALBUM, isHidden: !recentAlbumsQuery?.data?.items?.length,
loading: recentAlbumsQuery?.isLoading || recentAlbumsQuery.isFetching, itemType: LibraryItem.ALBUM,
title: ( loading: recentAlbumsQuery?.isLoading || recentAlbumsQuery.isFetching,
<Group align="flex-end"> title: (
<Group align="flex-end">
<TextTitle
order={2}
weight={700}
>
Recent releases
</TextTitle>
<Button
compact
uppercase
component={Link}
to={artistDiscographyLink}
variant="subtle"
>
View discography
</Button>
</Group>
),
uniqueId: 'recentReleases',
},
{
data: compilationAlbumsQuery?.data?.items,
isHidden: !compilationAlbumsQuery?.data?.items?.length,
itemType: LibraryItem.ALBUM,
loading: compilationAlbumsQuery?.isLoading || compilationAlbumsQuery.isFetching,
title: (
<TextTitle <TextTitle
order={2} order={2}
weight={700} weight={700}
> >
Recent releases Appears on
</TextTitle> </TextTitle>
<Button ),
compact uniqueId: 'compilationAlbums',
uppercase },
component={Link} {
to={artistDiscographyLink} data: detailQuery?.data?.similarArtists || [],
variant="subtle" isHidden: !detailQuery?.data?.similarArtists,
itemType: LibraryItem.ALBUM_ARTIST,
title: (
<TextTitle
order={2}
weight={700}
> >
View discography Related artists
</Button> </TextTitle>
</Group> ),
), uniqueId: 'similarArtists',
uniqueId: 'recentReleases', },
}, ];
{ }, [
data: compilationAlbumsQuery?.data?.items, artistDiscographyLink,
isHidden: !compilationAlbumsQuery?.data?.items?.length, compilationAlbumsQuery?.data?.items,
itemType: LibraryItem.ALBUM, compilationAlbumsQuery.isFetching,
loading: compilationAlbumsQuery?.isLoading || compilationAlbumsQuery.isFetching, compilationAlbumsQuery?.isLoading,
title: ( detailQuery?.data?.similarArtists,
<TextTitle recentAlbumsQuery?.data?.items,
order={2} recentAlbumsQuery.isFetching,
weight={700} recentAlbumsQuery?.isLoading,
> ]);
Appears on
</TextTitle>
),
uniqueId: 'compilationAlbums',
},
{
data: detailQuery?.data?.similarArtists || [],
isHidden: !detailQuery?.data?.similarArtists,
itemType: LibraryItem.ALBUM_ARTIST,
loading: detailQuery?.isLoading || detailQuery.isFetching,
title: (
<TextTitle
order={2}
weight={700}
>
Related artists
</TextTitle>
),
uniqueId: 'similarArtists',
},
];
const playButtonBehavior = usePlayButtonBehavior(); const playButtonBehavior = usePlayButtonBehavior();
@ -457,6 +467,7 @@ export const AlbumArtistDetailContent = ({ background }: AlbumArtistDetailConten
autoFitColumns autoFitColumns
autoHeight autoHeight
deselectOnClickOutside deselectOnClickOutside
stickyHeader
suppressCellFocus suppressCellFocus
suppressHorizontalScroll suppressHorizontalScroll
suppressLoadingOverlay suppressLoadingOverlay
@ -477,7 +488,7 @@ export const AlbumArtistDetailContent = ({ background }: AlbumArtistDetailConten
{carousels {carousels
.filter((c) => !c.isHidden) .filter((c) => !c.isHidden)
.map((carousel) => ( .map((carousel) => (
<SwiperGridCarousel <MemoizedSwiperGridCarousel
key={`carousel-${carousel.uniqueId}`} key={`carousel-${carousel.uniqueId}`}
cardRows={cardRows[carousel.itemType as keyof typeof cardRows]} cardRows={cardRows[carousel.itemType as keyof typeof cardRows]}
data={carousel.data} data={carousel.data}

View file

@ -7,7 +7,7 @@ import { useRecentlyPlayed } from '/@/renderer/features/home/queries/recently-pl
import { AnimatedPage, LibraryHeaderBar } from '/@/renderer/features/shared'; import { AnimatedPage, LibraryHeaderBar } from '/@/renderer/features/shared';
import { AppRoute } from '/@/renderer/router/routes'; import { AppRoute } from '/@/renderer/router/routes';
import { useCurrentServer, useWindowSettings } from '/@/renderer/store'; import { useCurrentServer, useWindowSettings } from '/@/renderer/store';
import { SwiperGridCarousel } from '/@/renderer/components/grid-carousel'; import { MemoizedSwiperGridCarousel } from '/@/renderer/components/grid-carousel';
import { Platform } from '/@/renderer/types'; import { Platform } from '/@/renderer/types';
const HomeRoute = () => { const HomeRoute = () => {
@ -161,7 +161,7 @@ const HomeRoute = () => {
return carousel; return carousel;
}) })
.map((carousel) => ( .map((carousel) => (
<SwiperGridCarousel <MemoizedSwiperGridCarousel
key={`carousel-${carousel.uniqueId}`} key={`carousel-${carousel.uniqueId}`}
cardRows={[ cardRows={[
{ {