2022-10-28 20:29:04 +08:00
|
|
|
import { resizeImage } from '@/web/utils/common'
|
2022-05-29 17:53:27 +08:00
|
|
|
import { cx } from '@emotion/css'
|
2022-05-12 02:45:43 +08:00
|
|
|
import { useNavigate } from 'react-router-dom'
|
2022-10-28 20:29:04 +08:00
|
|
|
import Image from './Image'
|
|
|
|
import { prefetchAlbum } from '@/web/api/hooks/useAlbum'
|
|
|
|
import { prefetchPlaylist } from '@/web/api/hooks/usePlaylist'
|
|
|
|
import { memo, useCallback } from 'react'
|
|
|
|
import dayjs from 'dayjs'
|
2023-01-24 16:29:33 +08:00
|
|
|
import ArtistInline from './ArtistsInline'
|
2022-03-13 14:40:38 +08:00
|
|
|
|
2022-10-28 20:29:04 +08:00
|
|
|
type ItemTitle = undefined | 'name'
|
|
|
|
type ItemSubTitle = undefined | 'artist' | 'year'
|
2022-03-13 14:40:38 +08:00
|
|
|
|
2022-10-28 20:29:04 +08:00
|
|
|
const Album = ({
|
|
|
|
album,
|
|
|
|
itemTitle,
|
|
|
|
itemSubtitle,
|
2022-03-13 14:40:38 +08:00
|
|
|
}: {
|
2022-10-28 20:29:04 +08:00
|
|
|
album: Album
|
|
|
|
itemTitle?: ItemTitle
|
|
|
|
itemSubtitle?: ItemSubTitle
|
2022-03-13 14:40:38 +08:00
|
|
|
}) => {
|
2022-10-28 20:29:04 +08:00
|
|
|
const navigate = useNavigate()
|
|
|
|
const goTo = () => {
|
|
|
|
navigate(`/album/${album.id}`)
|
|
|
|
}
|
|
|
|
const prefetch = () => {
|
|
|
|
prefetchAlbum({ id: album.id })
|
|
|
|
}
|
|
|
|
|
|
|
|
const title =
|
|
|
|
itemTitle &&
|
|
|
|
{
|
|
|
|
name: album.name,
|
|
|
|
}[itemTitle]
|
|
|
|
|
|
|
|
const subtitle =
|
|
|
|
itemSubtitle &&
|
|
|
|
{
|
|
|
|
artist: (
|
|
|
|
<ArtistInline
|
|
|
|
artists={album.artists}
|
|
|
|
hoverClassName='hover:text-white/50 transition-colors duration-400'
|
|
|
|
/>
|
|
|
|
),
|
|
|
|
year: dayjs(album.publishTime || 0).year(),
|
|
|
|
}[itemSubtitle]
|
|
|
|
|
2022-03-13 14:40:38 +08:00
|
|
|
return (
|
2022-10-28 20:29:04 +08:00
|
|
|
<div>
|
|
|
|
<Image
|
|
|
|
onClick={goTo}
|
|
|
|
key={album.id}
|
|
|
|
src={resizeImage(album?.picUrl || '', 'md')}
|
|
|
|
className='aspect-square rounded-24'
|
|
|
|
onMouseOver={prefetch}
|
|
|
|
/>
|
|
|
|
{title && (
|
2023-01-24 16:29:33 +08:00
|
|
|
<div className='line-clamp-2 mt-2 text-14 font-medium text-neutral-300'>{title}</div>
|
2022-03-13 14:40:38 +08:00
|
|
|
)}
|
2023-01-24 16:29:33 +08:00
|
|
|
{subtitle && <div className='mt-1 text-14 font-medium text-neutral-700'>{subtitle}</div>}
|
2022-03-13 14:40:38 +08:00
|
|
|
</div>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2022-10-28 20:29:04 +08:00
|
|
|
const Playlist = ({ playlist }: { playlist: Playlist }) => {
|
|
|
|
const navigate = useNavigate()
|
|
|
|
const goTo = useCallback(() => {
|
|
|
|
navigate(`/playlist/${playlist.id}`)
|
|
|
|
}, [navigate, playlist.id])
|
|
|
|
const prefetch = useCallback(() => {
|
|
|
|
prefetchPlaylist({ id: playlist.id })
|
|
|
|
}, [playlist.id])
|
2022-03-13 14:40:38 +08:00
|
|
|
|
2022-10-28 20:29:04 +08:00
|
|
|
return (
|
|
|
|
<Image
|
|
|
|
onClick={goTo}
|
|
|
|
key={playlist.id}
|
|
|
|
src={resizeImage(playlist.coverImgUrl || playlist?.picUrl || '', 'md')}
|
|
|
|
className='aspect-square rounded-24'
|
|
|
|
onMouseOver={prefetch}
|
|
|
|
/>
|
|
|
|
)
|
2022-03-13 14:40:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
const CoverRow = ({
|
|
|
|
albums,
|
|
|
|
playlists,
|
2022-10-28 20:29:04 +08:00
|
|
|
title,
|
2022-03-13 14:40:38 +08:00
|
|
|
className,
|
2022-10-28 20:29:04 +08:00
|
|
|
itemTitle,
|
|
|
|
itemSubtitle,
|
2022-03-13 14:40:38 +08:00
|
|
|
}: {
|
|
|
|
title?: string
|
2022-10-28 20:29:04 +08:00
|
|
|
className?: string
|
2022-03-13 14:40:38 +08:00
|
|
|
albums?: Album[]
|
|
|
|
playlists?: Playlist[]
|
2022-10-28 20:29:04 +08:00
|
|
|
itemTitle?: ItemTitle
|
|
|
|
itemSubtitle?: ItemSubTitle
|
2022-03-13 14:40:38 +08:00
|
|
|
}) => {
|
|
|
|
return (
|
2022-10-28 20:29:04 +08:00
|
|
|
<div className={className}>
|
|
|
|
{/* Title */}
|
2023-01-24 16:29:33 +08:00
|
|
|
{title && <h4 className='mb-6 text-14 font-bold uppercase dark:text-neutral-300'>{title}</h4>}
|
2022-03-13 14:40:38 +08:00
|
|
|
|
2022-10-28 20:29:04 +08:00
|
|
|
{/* Items */}
|
|
|
|
<div className='grid grid-cols-3 gap-4 lg:gap-6 xl:grid-cols-4 2xl:grid-cols-5'>
|
|
|
|
{albums?.map(album => (
|
2023-01-24 16:29:33 +08:00
|
|
|
<Album key={album.id} album={album} itemTitle={itemTitle} itemSubtitle={itemSubtitle} />
|
2022-10-28 20:29:04 +08:00
|
|
|
))}
|
|
|
|
{playlists?.map(playlist => (
|
|
|
|
<Playlist key={playlist.id} playlist={playlist} />
|
2022-03-13 14:40:38 +08:00
|
|
|
))}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2022-10-28 20:29:04 +08:00
|
|
|
const memoizedCoverRow = memo(CoverRow)
|
|
|
|
memoizedCoverRow.displayName = 'CoverRow'
|
|
|
|
export default memoizedCoverRow
|