Move card rows to separate component
This commit is contained in:
parent
6eb08243b7
commit
7d1083d1f7
5 changed files with 201 additions and 236 deletions
180
src/renderer/components/card/card-rows.tsx
Normal file
180
src/renderer/components/card/card-rows.tsx
Normal file
|
@ -0,0 +1,180 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { generatePath } from 'react-router';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
import { Album, AlbumArtist, Artist } from '/@/renderer/api/types';
|
||||||
|
import { Text } from '/@/renderer/components/text';
|
||||||
|
import { AppRoute } from '/@/renderer/router/routes';
|
||||||
|
import { CardRow } from '/@/renderer/types';
|
||||||
|
|
||||||
|
const Row = styled.div<{ $secondary?: boolean }>`
|
||||||
|
width: 100%;
|
||||||
|
max-width: 100%;
|
||||||
|
height: 22px;
|
||||||
|
padding: 0 0.2rem;
|
||||||
|
overflow: hidden;
|
||||||
|
color: ${({ $secondary }) => ($secondary ? 'var(--main-fg-secondary)' : 'var(--main-fg)')};
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
user-select: none;
|
||||||
|
`;
|
||||||
|
|
||||||
|
interface CardRowsProps {
|
||||||
|
data: any;
|
||||||
|
rows: CardRow<Album | Artist | AlbumArtist>[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const CardRows = ({ data, rows }: CardRowsProps) => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{rows.map((row, index: number) => {
|
||||||
|
if (row.arrayProperty && row.route) {
|
||||||
|
return (
|
||||||
|
<Row
|
||||||
|
key={`row-${row.property}-${index}`}
|
||||||
|
$secondary={index > 0}
|
||||||
|
>
|
||||||
|
{data[row.property].map((item: any, itemIndex: number) => (
|
||||||
|
<React.Fragment key={`${data.id}-${item.id}`}>
|
||||||
|
{itemIndex > 0 && (
|
||||||
|
<Text
|
||||||
|
$noSelect
|
||||||
|
sx={{
|
||||||
|
display: 'inline-block',
|
||||||
|
padding: '0 2px 0 1px',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
,
|
||||||
|
</Text>
|
||||||
|
)}{' '}
|
||||||
|
<Text
|
||||||
|
$link
|
||||||
|
$noSelect
|
||||||
|
$secondary={index > 0}
|
||||||
|
component={Link}
|
||||||
|
overflow="hidden"
|
||||||
|
size={index > 0 ? 'sm' : 'md'}
|
||||||
|
to={generatePath(
|
||||||
|
row.route!.route,
|
||||||
|
row.route!.slugs?.reduce((acc, slug) => {
|
||||||
|
return {
|
||||||
|
...acc,
|
||||||
|
[slug.slugProperty]: data[slug.idProperty],
|
||||||
|
};
|
||||||
|
}, {}),
|
||||||
|
)}
|
||||||
|
onClick={(e) => e.stopPropagation()}
|
||||||
|
>
|
||||||
|
{row.arrayProperty && item[row.arrayProperty]}
|
||||||
|
</Text>
|
||||||
|
</React.Fragment>
|
||||||
|
))}
|
||||||
|
</Row>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (row.arrayProperty) {
|
||||||
|
return (
|
||||||
|
<Row key={`row-${row.property}`}>
|
||||||
|
{data[row.property].map((item: any) => (
|
||||||
|
<Text
|
||||||
|
key={`${data.id}-${item.id}`}
|
||||||
|
$noSelect
|
||||||
|
$secondary={index > 0}
|
||||||
|
overflow="hidden"
|
||||||
|
size={index > 0 ? 'sm' : 'md'}
|
||||||
|
>
|
||||||
|
{row.arrayProperty && item[row.arrayProperty]}
|
||||||
|
</Text>
|
||||||
|
))}
|
||||||
|
</Row>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Row key={`row-${row.property}`}>
|
||||||
|
{row.route ? (
|
||||||
|
<Text
|
||||||
|
$link
|
||||||
|
$noSelect
|
||||||
|
component={Link}
|
||||||
|
overflow="hidden"
|
||||||
|
to={generatePath(
|
||||||
|
row.route.route,
|
||||||
|
row.route.slugs?.reduce((acc, slug) => {
|
||||||
|
return {
|
||||||
|
...acc,
|
||||||
|
[slug.slugProperty]: data[slug.idProperty],
|
||||||
|
};
|
||||||
|
}, {}),
|
||||||
|
)}
|
||||||
|
onClick={(e) => e.stopPropagation()}
|
||||||
|
>
|
||||||
|
{data && data[row.property]}
|
||||||
|
</Text>
|
||||||
|
) : (
|
||||||
|
<Text
|
||||||
|
$noSelect
|
||||||
|
$secondary={index > 0}
|
||||||
|
overflow="hidden"
|
||||||
|
size={index > 0 ? 'sm' : 'md'}
|
||||||
|
>
|
||||||
|
{data && data[row.property]}
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
|
</Row>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ALBUM_CARD_ROWS: { [key: string]: CardRow<Album> } = {
|
||||||
|
albumArtists: {
|
||||||
|
arrayProperty: 'name',
|
||||||
|
property: 'albumArtists',
|
||||||
|
route: {
|
||||||
|
route: AppRoute.LIBRARY_ALBUMARTISTS_DETAIL,
|
||||||
|
slugs: [{ idProperty: 'id', slugProperty: 'albumArtistId' }],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
artists: {
|
||||||
|
arrayProperty: 'name',
|
||||||
|
property: 'artists',
|
||||||
|
route: {
|
||||||
|
route: AppRoute.LIBRARY_ALBUMARTISTS_DETAIL,
|
||||||
|
slugs: [{ idProperty: 'id', slugProperty: 'albumArtistId' }],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
createdAt: {
|
||||||
|
property: 'createdAt',
|
||||||
|
},
|
||||||
|
duration: {
|
||||||
|
property: 'duration',
|
||||||
|
},
|
||||||
|
lastPlayedAt: {
|
||||||
|
property: 'lastPlayedAt',
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
property: 'name',
|
||||||
|
route: {
|
||||||
|
route: AppRoute.LIBRARY_ALBUMS_DETAIL,
|
||||||
|
slugs: [{ idProperty: 'id', slugProperty: 'albumId' }],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
playCount: {
|
||||||
|
property: 'playCount',
|
||||||
|
},
|
||||||
|
rating: {
|
||||||
|
property: 'rating',
|
||||||
|
},
|
||||||
|
releaseDate: {
|
||||||
|
property: 'releaseDate',
|
||||||
|
},
|
||||||
|
releaseYear: {
|
||||||
|
property: 'releaseYear',
|
||||||
|
},
|
||||||
|
songCount: {
|
||||||
|
property: 'songCount',
|
||||||
|
},
|
||||||
|
};
|
|
@ -1 +1,2 @@
|
||||||
export * from './album-card';
|
export * from './album-card';
|
||||||
|
export * from './card-rows';
|
||||||
|
|
|
@ -1,15 +1,14 @@
|
||||||
import React from 'react';
|
|
||||||
import { Center } from '@mantine/core';
|
import { Center } from '@mantine/core';
|
||||||
import { RiAlbumFill } from 'react-icons/ri';
|
import { RiAlbumFill } from 'react-icons/ri';
|
||||||
import { generatePath, useNavigate } from 'react-router';
|
import { generatePath, useNavigate } from 'react-router';
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
import { SimpleImg } from 'react-simple-img';
|
import { SimpleImg } from 'react-simple-img';
|
||||||
import type { ListChildComponentProps } from 'react-window';
|
import type { ListChildComponentProps } from 'react-window';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import { Text } from '/@/renderer/components/text';
|
|
||||||
import type { LibraryItem, CardRow, CardRoute, Play, PlayQueueAddOptions } from '/@/renderer/types';
|
import type { LibraryItem, CardRow, CardRoute, Play, PlayQueueAddOptions } from '/@/renderer/types';
|
||||||
import { Skeleton } from '/@/renderer/components/skeleton';
|
import { Skeleton } from '/@/renderer/components/skeleton';
|
||||||
import { GridCardControls } from '/@/renderer/components/virtual-grid/grid-card/grid-card-controls';
|
import { GridCardControls } from '/@/renderer/components/virtual-grid/grid-card/grid-card-controls';
|
||||||
|
import { Album, AlbumArtist, Artist } from '/@/renderer/api/types';
|
||||||
|
import { CardRows } from '/@/renderer/components/card';
|
||||||
|
|
||||||
const CardWrapper = styled.div<{
|
const CardWrapper = styled.div<{
|
||||||
itemGap: number;
|
itemGap: number;
|
||||||
|
@ -98,22 +97,10 @@ const DetailSection = styled.div`
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Row = styled.div<{ $secondary?: boolean }>`
|
|
||||||
width: 100%;
|
|
||||||
max-width: 100%;
|
|
||||||
height: 22px;
|
|
||||||
padding: 0 0.2rem;
|
|
||||||
overflow: hidden;
|
|
||||||
color: ${({ $secondary }) => ($secondary ? 'var(--main-fg-secondary)' : 'var(--main-fg)')};
|
|
||||||
white-space: nowrap;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
user-select: none;
|
|
||||||
`;
|
|
||||||
|
|
||||||
interface BaseGridCardProps {
|
interface BaseGridCardProps {
|
||||||
columnIndex: number;
|
columnIndex: number;
|
||||||
controls: {
|
controls: {
|
||||||
cardRows: CardRow[];
|
cardRows: CardRow<Album | AlbumArtist | Artist>[];
|
||||||
handlePlayQueueAdd: (options: PlayQueueAddOptions) => void;
|
handlePlayQueueAdd: (options: PlayQueueAddOptions) => void;
|
||||||
itemType: LibraryItem;
|
itemType: LibraryItem;
|
||||||
playButtonBehavior: Play;
|
playButtonBehavior: Play;
|
||||||
|
@ -199,104 +186,10 @@ export const DefaultCard = ({
|
||||||
</ControlsContainer>
|
</ControlsContainer>
|
||||||
</ImageSection>
|
</ImageSection>
|
||||||
<DetailSection>
|
<DetailSection>
|
||||||
{cardRows.map((row: CardRow, index: number) => {
|
<CardRows
|
||||||
if (row.arrayProperty && row.route) {
|
data={data}
|
||||||
return (
|
rows={cardRows}
|
||||||
<Row
|
/>
|
||||||
key={`row-${row.property}-${columnIndex}`}
|
|
||||||
$secondary={index > 0}
|
|
||||||
>
|
|
||||||
{data[row.property].map((item: any, itemIndex: number) => (
|
|
||||||
<React.Fragment key={`${data.id}-${item.id}`}>
|
|
||||||
{itemIndex > 0 && (
|
|
||||||
<Text
|
|
||||||
$noSelect
|
|
||||||
sx={{
|
|
||||||
display: 'inline-block',
|
|
||||||
padding: '0 2px 0 1px',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
,
|
|
||||||
</Text>
|
|
||||||
)}{' '}
|
|
||||||
<Text
|
|
||||||
$link
|
|
||||||
$noSelect
|
|
||||||
$secondary={index > 0}
|
|
||||||
component={Link}
|
|
||||||
overflow="hidden"
|
|
||||||
size={index > 0 ? 'xs' : 'md'}
|
|
||||||
to={generatePath(
|
|
||||||
row.route!.route,
|
|
||||||
row.route!.slugs?.reduce((acc, slug) => {
|
|
||||||
return {
|
|
||||||
...acc,
|
|
||||||
[slug.slugProperty]: data[slug.idProperty],
|
|
||||||
};
|
|
||||||
}, {}),
|
|
||||||
)}
|
|
||||||
onClick={(e) => e.stopPropagation()}
|
|
||||||
>
|
|
||||||
{row.arrayProperty && item[row.arrayProperty]}
|
|
||||||
</Text>
|
|
||||||
</React.Fragment>
|
|
||||||
))}
|
|
||||||
</Row>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (row.arrayProperty) {
|
|
||||||
return (
|
|
||||||
<Row key={`row-${row.property}-${columnIndex}`}>
|
|
||||||
{data[row.property].map((item: any) => (
|
|
||||||
<Text
|
|
||||||
key={`${data.id}-${item.id}`}
|
|
||||||
$noSelect
|
|
||||||
$secondary={index > 0}
|
|
||||||
overflow="hidden"
|
|
||||||
size={index > 0 ? 'xs' : 'md'}
|
|
||||||
>
|
|
||||||
{row.arrayProperty && item[row.arrayProperty]}
|
|
||||||
</Text>
|
|
||||||
))}
|
|
||||||
</Row>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Row key={`row-${row.property}-${columnIndex}`}>
|
|
||||||
{row.route ? (
|
|
||||||
<Text
|
|
||||||
$link
|
|
||||||
$noSelect
|
|
||||||
component={Link}
|
|
||||||
overflow="hidden"
|
|
||||||
to={generatePath(
|
|
||||||
row.route.route,
|
|
||||||
row.route.slugs?.reduce((acc, slug) => {
|
|
||||||
return {
|
|
||||||
...acc,
|
|
||||||
[slug.slugProperty]: data[slug.idProperty],
|
|
||||||
};
|
|
||||||
}, {}),
|
|
||||||
)}
|
|
||||||
onClick={(e) => e.stopPropagation()}
|
|
||||||
>
|
|
||||||
{data && data[row.property]}
|
|
||||||
</Text>
|
|
||||||
) : (
|
|
||||||
<Text
|
|
||||||
$noSelect
|
|
||||||
$secondary={index > 0}
|
|
||||||
overflow="hidden"
|
|
||||||
size={index > 0 ? 'xs' : 'md'}
|
|
||||||
>
|
|
||||||
{data && data[row.property]}
|
|
||||||
</Text>
|
|
||||||
)}
|
|
||||||
</Row>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</DetailSection>
|
</DetailSection>
|
||||||
</StyledCard>
|
</StyledCard>
|
||||||
</CardWrapper>
|
</CardWrapper>
|
||||||
|
@ -318,7 +211,7 @@ export const DefaultCard = ({
|
||||||
<ImageSection size={itemWidth} />
|
<ImageSection size={itemWidth} />
|
||||||
</Skeleton>
|
</Skeleton>
|
||||||
<DetailSection>
|
<DetailSection>
|
||||||
{cardRows.map((row: CardRow, index: number) => (
|
{cardRows.map((row: CardRow<Album | Artist | AlbumArtist>, index: number) => (
|
||||||
<Skeleton
|
<Skeleton
|
||||||
key={`row-${row.property}-${columnIndex}`}
|
key={`row-${row.property}-${columnIndex}`}
|
||||||
height={20}
|
height={20}
|
||||||
|
@ -326,9 +219,7 @@ export const DefaultCard = ({
|
||||||
radius="md"
|
radius="md"
|
||||||
visible={!data}
|
visible={!data}
|
||||||
width={!data ? (index > 0 ? '50%' : '90%') : '100%'}
|
width={!data ? (index > 0 ? '50%' : '90%') : '100%'}
|
||||||
>
|
/>
|
||||||
<Row />
|
|
||||||
</Skeleton>
|
|
||||||
))}
|
))}
|
||||||
</DetailSection>
|
</DetailSection>
|
||||||
</StyledCard>
|
</StyledCard>
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import React from 'react';
|
|
||||||
import { Center } from '@mantine/core';
|
import { Center } from '@mantine/core';
|
||||||
import { RiAlbumFill } from 'react-icons/ri';
|
import { RiAlbumFill } from 'react-icons/ri';
|
||||||
import { generatePath } from 'react-router';
|
import { generatePath } from 'react-router';
|
||||||
|
@ -7,9 +6,10 @@ import { SimpleImg } from 'react-simple-img';
|
||||||
import type { ListChildComponentProps } from 'react-window';
|
import type { ListChildComponentProps } from 'react-window';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import { Skeleton } from '/@/renderer/components/skeleton';
|
import { Skeleton } from '/@/renderer/components/skeleton';
|
||||||
import { Text } from '/@/renderer/components/text';
|
|
||||||
import type { LibraryItem, CardRow, CardRoute, Play, PlayQueueAddOptions } from '/@/renderer/types';
|
import type { LibraryItem, CardRow, CardRoute, Play, PlayQueueAddOptions } from '/@/renderer/types';
|
||||||
import { GridCardControls } from '/@/renderer/components/virtual-grid/grid-card/grid-card-controls';
|
import { GridCardControls } from '/@/renderer/components/virtual-grid/grid-card/grid-card-controls';
|
||||||
|
import { Album, Artist, AlbumArtist } from '/@/renderer/api/types';
|
||||||
|
import { CardRows } from '/@/renderer/components/card';
|
||||||
|
|
||||||
const CardWrapper = styled.div<{
|
const CardWrapper = styled.div<{
|
||||||
itemGap: number;
|
itemGap: number;
|
||||||
|
@ -101,22 +101,10 @@ const DetailSection = styled.div`
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Row = styled.div<{ $secondary?: boolean }>`
|
|
||||||
width: 100%;
|
|
||||||
max-width: 100%;
|
|
||||||
height: 22px;
|
|
||||||
padding: 0 0.2rem;
|
|
||||||
overflow: hidden;
|
|
||||||
color: ${({ $secondary }) => ($secondary ? 'var(--main-fg-secondary)' : 'var(--main-fg)')};
|
|
||||||
white-space: nowrap;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
user-select: none;
|
|
||||||
`;
|
|
||||||
|
|
||||||
interface BaseGridCardProps {
|
interface BaseGridCardProps {
|
||||||
columnIndex: number;
|
columnIndex: number;
|
||||||
controls: {
|
controls: {
|
||||||
cardRows: CardRow[];
|
cardRows: CardRow<Album | AlbumArtist | Artist>[];
|
||||||
handlePlayQueueAdd: (options: PlayQueueAddOptions) => void;
|
handlePlayQueueAdd: (options: PlayQueueAddOptions) => void;
|
||||||
itemType: LibraryItem;
|
itemType: LibraryItem;
|
||||||
playButtonBehavior: Play;
|
playButtonBehavior: Play;
|
||||||
|
@ -193,104 +181,10 @@ export const PosterCard = ({
|
||||||
</ImageSection>
|
</ImageSection>
|
||||||
</Link>
|
</Link>
|
||||||
<DetailSection>
|
<DetailSection>
|
||||||
{controls.cardRows.map((row: CardRow, index: number) => {
|
<CardRows
|
||||||
if (row.arrayProperty && row.route) {
|
data={data}
|
||||||
return (
|
rows={controls.cardRows}
|
||||||
<Row
|
/>
|
||||||
key={`row-${row.property}-${columnIndex}`}
|
|
||||||
$secondary={index > 0}
|
|
||||||
>
|
|
||||||
{data[row.property].map((item: any, itemIndex: number) => (
|
|
||||||
<React.Fragment key={`${data.id}-${item.id}`}>
|
|
||||||
{itemIndex > 0 && (
|
|
||||||
<Text
|
|
||||||
$noSelect
|
|
||||||
size={index > 0 ? 'xs' : 'md'}
|
|
||||||
sx={{
|
|
||||||
display: 'inline-block',
|
|
||||||
padding: '0 2px 0 1px',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
,
|
|
||||||
</Text>
|
|
||||||
)}{' '}
|
|
||||||
<Text
|
|
||||||
$link
|
|
||||||
$noSelect
|
|
||||||
$secondary={index > 0}
|
|
||||||
component={Link}
|
|
||||||
overflow="hidden"
|
|
||||||
size={index > 0 ? 'xs' : 'md'}
|
|
||||||
to={generatePath(
|
|
||||||
row.route!.route,
|
|
||||||
row.route!.slugs?.reduce((acc, slug) => {
|
|
||||||
return {
|
|
||||||
...acc,
|
|
||||||
[slug.slugProperty]: data[slug.idProperty],
|
|
||||||
};
|
|
||||||
}, {}),
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{row.arrayProperty && item[row.arrayProperty]}
|
|
||||||
</Text>
|
|
||||||
</React.Fragment>
|
|
||||||
))}
|
|
||||||
</Row>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (row.arrayProperty) {
|
|
||||||
return (
|
|
||||||
<Row key={`row-${row.property}-${columnIndex}`}>
|
|
||||||
{data[row.property].map((item: any) => (
|
|
||||||
<Text
|
|
||||||
key={`${data.id}-${item.id}`}
|
|
||||||
$noSelect
|
|
||||||
$secondary={index > 0}
|
|
||||||
overflow="hidden"
|
|
||||||
size={index > 0 ? 'xs' : 'md'}
|
|
||||||
>
|
|
||||||
{row.arrayProperty && item[row.arrayProperty]}
|
|
||||||
</Text>
|
|
||||||
))}
|
|
||||||
</Row>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Row key={`row-${row.property}-${columnIndex}`}>
|
|
||||||
{row.route ? (
|
|
||||||
<Text
|
|
||||||
$link
|
|
||||||
$noSelect
|
|
||||||
component={Link}
|
|
||||||
overflow="hidden"
|
|
||||||
size={index > 0 ? 'xs' : 'md'}
|
|
||||||
to={generatePath(
|
|
||||||
row.route.route,
|
|
||||||
row.route.slugs?.reduce((acc, slug) => {
|
|
||||||
return {
|
|
||||||
...acc,
|
|
||||||
[slug.slugProperty]: data[slug.idProperty],
|
|
||||||
};
|
|
||||||
}, {}),
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{data && data[row.property]}
|
|
||||||
</Text>
|
|
||||||
) : (
|
|
||||||
<Text
|
|
||||||
$noSelect
|
|
||||||
$secondary={index > 0}
|
|
||||||
overflow="hidden"
|
|
||||||
size={index > 0 ? 'xs' : 'md'}
|
|
||||||
>
|
|
||||||
{data && data[row.property]}
|
|
||||||
</Text>
|
|
||||||
)}
|
|
||||||
</Row>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</DetailSection>
|
</DetailSection>
|
||||||
</StyledCard>
|
</StyledCard>
|
||||||
</CardWrapper>
|
</CardWrapper>
|
||||||
|
@ -312,7 +206,7 @@ export const PosterCard = ({
|
||||||
<ImageSection style={{ height: `${sizes.itemWidth}px` }} />
|
<ImageSection style={{ height: `${sizes.itemWidth}px` }} />
|
||||||
</Skeleton>
|
</Skeleton>
|
||||||
<DetailSection>
|
<DetailSection>
|
||||||
{controls.cardRows.map((row: CardRow, index: number) => (
|
{controls.cardRows.map((row: CardRow<Album | Artist | AlbumArtist>, index: number) => (
|
||||||
<Skeleton
|
<Skeleton
|
||||||
key={`row-${row.property}-${columnIndex}`}
|
key={`row-${row.property}-${columnIndex}`}
|
||||||
height={20}
|
height={20}
|
||||||
|
@ -320,9 +214,7 @@ export const PosterCard = ({
|
||||||
radius="md"
|
radius="md"
|
||||||
visible={!data}
|
visible={!data}
|
||||||
width={!data ? (index > 0 ? '50%' : '90%') : '100%'}
|
width={!data ? (index > 0 ? '50%' : '90%') : '100%'}
|
||||||
>
|
/>
|
||||||
<Row />
|
|
||||||
</Skeleton>
|
|
||||||
))}
|
))}
|
||||||
</DetailSection>
|
</DetailSection>
|
||||||
</StyledCard>
|
</StyledCard>
|
||||||
|
|
|
@ -12,6 +12,7 @@ import type {
|
||||||
CardRoute,
|
CardRoute,
|
||||||
PlayQueueAddOptions,
|
PlayQueueAddOptions,
|
||||||
} from '/@/renderer/types';
|
} from '/@/renderer/types';
|
||||||
|
import { Album, AlbumArtist, Artist } from '/@/renderer/api/types';
|
||||||
|
|
||||||
const createItemData = memoize(
|
const createItemData = memoize(
|
||||||
(
|
(
|
||||||
|
@ -61,7 +62,7 @@ export const VirtualGridWrapper = ({
|
||||||
onScroll,
|
onScroll,
|
||||||
...rest
|
...rest
|
||||||
}: Omit<FixedSizeListProps, 'ref' | 'itemSize' | 'children'> & {
|
}: Omit<FixedSizeListProps, 'ref' | 'itemSize' | 'children'> & {
|
||||||
cardRows: CardRow[];
|
cardRows: CardRow<Album | AlbumArtist | Artist>[];
|
||||||
columnCount: number;
|
columnCount: number;
|
||||||
display: CardDisplayType;
|
display: CardDisplayType;
|
||||||
handlePlayQueueAdd?: (options: PlayQueueAddOptions) => void;
|
handlePlayQueueAdd?: (options: PlayQueueAddOptions) => void;
|
||||||
|
|
Reference in a new issue