diff --git a/src/renderer/components/card/card-rows.tsx b/src/renderer/components/card/card-rows.tsx new file mode 100644 index 00000000..2ff8b30e --- /dev/null +++ b/src/renderer/components/card/card-rows.tsx @@ -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[]; +} + +export const CardRows = ({ data, rows }: CardRowsProps) => { + return ( + <> + {rows.map((row, index: number) => { + if (row.arrayProperty && row.route) { + return ( + 0} + > + {data[row.property].map((item: any, itemIndex: number) => ( + + {itemIndex > 0 && ( + + , + + )}{' '} + 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]} + + + ))} + + ); + } + + if (row.arrayProperty) { + return ( + + {data[row.property].map((item: any) => ( + 0} + overflow="hidden" + size={index > 0 ? 'sm' : 'md'} + > + {row.arrayProperty && item[row.arrayProperty]} + + ))} + + ); + } + + return ( + + {row.route ? ( + { + return { + ...acc, + [slug.slugProperty]: data[slug.idProperty], + }; + }, {}), + )} + onClick={(e) => e.stopPropagation()} + > + {data && data[row.property]} + + ) : ( + 0} + overflow="hidden" + size={index > 0 ? 'sm' : 'md'} + > + {data && data[row.property]} + + )} + + ); + })} + + ); +}; + +export const ALBUM_CARD_ROWS: { [key: string]: CardRow } = { + 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', + }, +}; diff --git a/src/renderer/components/card/index.tsx b/src/renderer/components/card/index.tsx index fe08e1c1..a3b57698 100644 --- a/src/renderer/components/card/index.tsx +++ b/src/renderer/components/card/index.tsx @@ -1 +1,2 @@ export * from './album-card'; +export * from './card-rows'; diff --git a/src/renderer/components/virtual-grid/grid-card/default-card.tsx b/src/renderer/components/virtual-grid/grid-card/default-card.tsx index 247273c6..2c6d2ade 100644 --- a/src/renderer/components/virtual-grid/grid-card/default-card.tsx +++ b/src/renderer/components/virtual-grid/grid-card/default-card.tsx @@ -1,15 +1,14 @@ -import React from 'react'; import { Center } from '@mantine/core'; import { RiAlbumFill } from 'react-icons/ri'; import { generatePath, useNavigate } from 'react-router'; -import { Link } from 'react-router-dom'; import { SimpleImg } from 'react-simple-img'; import type { ListChildComponentProps } from 'react-window'; import styled from 'styled-components'; -import { Text } from '/@/renderer/components/text'; import type { LibraryItem, CardRow, CardRoute, Play, PlayQueueAddOptions } from '/@/renderer/types'; import { Skeleton } from '/@/renderer/components/skeleton'; 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<{ itemGap: number; @@ -98,22 +97,10 @@ const DetailSection = styled.div` 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 { columnIndex: number; controls: { - cardRows: CardRow[]; + cardRows: CardRow[]; handlePlayQueueAdd: (options: PlayQueueAddOptions) => void; itemType: LibraryItem; playButtonBehavior: Play; @@ -199,104 +186,10 @@ export const DefaultCard = ({ - {cardRows.map((row: CardRow, index: number) => { - if (row.arrayProperty && row.route) { - return ( - 0} - > - {data[row.property].map((item: any, itemIndex: number) => ( - - {itemIndex > 0 && ( - - , - - )}{' '} - 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]} - - - ))} - - ); - } - - if (row.arrayProperty) { - return ( - - {data[row.property].map((item: any) => ( - 0} - overflow="hidden" - size={index > 0 ? 'xs' : 'md'} - > - {row.arrayProperty && item[row.arrayProperty]} - - ))} - - ); - } - - return ( - - {row.route ? ( - { - return { - ...acc, - [slug.slugProperty]: data[slug.idProperty], - }; - }, {}), - )} - onClick={(e) => e.stopPropagation()} - > - {data && data[row.property]} - - ) : ( - 0} - overflow="hidden" - size={index > 0 ? 'xs' : 'md'} - > - {data && data[row.property]} - - )} - - ); - })} + @@ -318,7 +211,7 @@ export const DefaultCard = ({ - {cardRows.map((row: CardRow, index: number) => ( + {cardRows.map((row: CardRow, index: number) => ( 0 ? '50%' : '90%') : '100%'} - > - - + /> ))} diff --git a/src/renderer/components/virtual-grid/grid-card/poster-card.tsx b/src/renderer/components/virtual-grid/grid-card/poster-card.tsx index 51dc016f..cc274213 100644 --- a/src/renderer/components/virtual-grid/grid-card/poster-card.tsx +++ b/src/renderer/components/virtual-grid/grid-card/poster-card.tsx @@ -1,4 +1,3 @@ -import React from 'react'; import { Center } from '@mantine/core'; import { RiAlbumFill } from 'react-icons/ri'; import { generatePath } from 'react-router'; @@ -7,9 +6,10 @@ import { SimpleImg } from 'react-simple-img'; import type { ListChildComponentProps } from 'react-window'; import styled from 'styled-components'; import { Skeleton } from '/@/renderer/components/skeleton'; -import { Text } from '/@/renderer/components/text'; import type { LibraryItem, CardRow, CardRoute, Play, PlayQueueAddOptions } from '/@/renderer/types'; 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<{ itemGap: number; @@ -101,22 +101,10 @@ const DetailSection = styled.div` 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 { columnIndex: number; controls: { - cardRows: CardRow[]; + cardRows: CardRow[]; handlePlayQueueAdd: (options: PlayQueueAddOptions) => void; itemType: LibraryItem; playButtonBehavior: Play; @@ -193,104 +181,10 @@ export const PosterCard = ({ - {controls.cardRows.map((row: CardRow, index: number) => { - if (row.arrayProperty && row.route) { - return ( - 0} - > - {data[row.property].map((item: any, itemIndex: number) => ( - - {itemIndex > 0 && ( - 0 ? 'xs' : 'md'} - sx={{ - display: 'inline-block', - padding: '0 2px 0 1px', - }} - > - , - - )}{' '} - 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]} - - - ))} - - ); - } - - if (row.arrayProperty) { - return ( - - {data[row.property].map((item: any) => ( - 0} - overflow="hidden" - size={index > 0 ? 'xs' : 'md'} - > - {row.arrayProperty && item[row.arrayProperty]} - - ))} - - ); - } - - return ( - - {row.route ? ( - 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]} - - ) : ( - 0} - overflow="hidden" - size={index > 0 ? 'xs' : 'md'} - > - {data && data[row.property]} - - )} - - ); - })} + @@ -312,7 +206,7 @@ export const PosterCard = ({ - {controls.cardRows.map((row: CardRow, index: number) => ( + {controls.cardRows.map((row: CardRow, index: number) => ( 0 ? '50%' : '90%') : '100%'} - > - - + /> ))} diff --git a/src/renderer/components/virtual-grid/virtual-grid-wrapper.tsx b/src/renderer/components/virtual-grid/virtual-grid-wrapper.tsx index 95b544ef..23f8660f 100644 --- a/src/renderer/components/virtual-grid/virtual-grid-wrapper.tsx +++ b/src/renderer/components/virtual-grid/virtual-grid-wrapper.tsx @@ -12,6 +12,7 @@ import type { CardRoute, PlayQueueAddOptions, } from '/@/renderer/types'; +import { Album, AlbumArtist, Artist } from '/@/renderer/api/types'; const createItemData = memoize( ( @@ -61,7 +62,7 @@ export const VirtualGridWrapper = ({ onScroll, ...rest }: Omit & { - cardRows: CardRow[]; + cardRows: CardRow[]; columnCount: number; display: CardDisplayType; handlePlayQueueAdd?: (options: PlayQueueAddOptions) => void;