Use memoized carousel component for pages
This commit is contained in:
parent
74384639de
commit
a8dfc7bcd6
3 changed files with 148 additions and 145 deletions
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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}
|
||||||
|
|
|
||||||
|
|
@ -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={[
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Reference in a new issue