import React, { Fragment, memo } from 'react'
import Button, { Color as ButtonColor } from '@/components/Button'
import Skeleton from '@/components/Skeleton'
import SvgIcon from '@/components/SvgIcon'
import TracksList from '@/components/TracksList'
import usePlaylist from '@/hooks/usePlaylist'
import useScroll from '@/hooks/useScroll'
import useTracksInfinite from '@/hooks/useTracksInfinite'
import { player } from '@/store'
import { formatDate, resizeImage } from '@/utils/common'
const enableRenderLog = true
const Header = memo(
({
playlist,
isLoading,
handlePlay,
}: {
playlist: Playlist | undefined
isLoading: boolean
handlePlay: () => void
}) => {
if (enableRenderLog) console.debug('Rendering Playlist.tsx Header')
const coverUrl = resizeImage(playlist?.coverImgUrl || '', 'lg')
return (
{/* Header background */}
{/* Cover */}
{!isLoading && (
)}
{!isLoading && (

)}
{isLoading && (
)}
{/* */}
{/* */}
{!isLoading && (
{playlist?.name}
)}
{isLoading && (
PLACEHOLDER
)}
{/* */}
{!isLoading && (
Playlist by {playlist?.creator?.nickname}
)}
{isLoading && (
PLACEHOLDER
)}
{/* */}
{!isLoading && (
更新于 {formatDate(playlist?.updateTime || 0, 'zh-CN')} ·{' '}
{playlist?.trackCount} 首歌
)}
{isLoading && (
PLACEHOLDER
)}
{/* */}
{!isLoading && (
{playlist?.description}
)}
{isLoading && (
PLACEHOLDER
)}
{/* */}
)
}
)
Header.displayName = 'Header'
const Tracks = memo(
({
playlist,
handlePlay,
isLoadingPlaylist,
}: {
playlist: Playlist | undefined
handlePlay: (trackID: number | null) => void
isLoadingPlaylist: boolean
}) => {
if (enableRenderLog) console.debug('Rendering Playlist.tsx Tracks')
const {
data: tracksPages,
hasNextPage,
isLoading: isLoadingTracks,
isFetchingNextPage,
fetchNextPage,
} = useTracksInfinite({
ids: playlist?.trackIds?.map(t => t.id) || [],
})
const scroll = useScroll(document.getElementById('mainContainer'), {
throttle: 500,
offset: {
bottom: 256,
},
})
useEffect(() => {
if (!scroll.arrivedState.bottom || !hasNextPage || isFetchingNextPage)
return
fetchNextPage()
}, [
fetchNextPage,
hasNextPage,
isFetchingNextPage,
scroll.arrivedState.bottom,
])
const tracks = useMemo(() => {
if (!tracksPages) return []
const allTracks: Track[] = []
tracksPages.pages.forEach(page => allTracks.push(...(page?.songs ?? [])))
return allTracks
}, [tracksPages])
return (
{isLoadingPlaylist ? (
) : isLoadingTracks ? (
) : (
)}
)
}
)
Tracks.displayName = 'Tracks'
const Playlist = () => {
if (enableRenderLog) console.debug('Rendering Playlist.tsx Playlist')
const params = useParams()
const { data: playlist, isLoading } = usePlaylist({
id: Number(params.id) || 0,
})
const handlePlay = useCallback(
(trackID: number | null = null) => {
if (!playlist) {
toast('Failed to play playlist')
return
}
player.playPlaylist(playlist.playlist, trackID)
},
[playlist]
)
return (
)
}
export default Playlist