import React, { useEffect, useMemo, useRef, useState } from 'react' import { css, cx } from '@emotion/css' import Icon from '../Icon' import { formatDuration, resizeImage } from '@/web/utils/common' import { player } from '@/web/store' import { useSnapshot } from 'valtio' import { State as PlayerState, Mode as PlayerMode } from '@/web/utils/player' import Slider from './Slider' import { animate, motion, useAnimation } from 'framer-motion' import { ease } from '@/web/utils/const' const Progress = () => { const playerSnapshot = useSnapshot(player) const track = useMemo(() => playerSnapshot.track, [playerSnapshot.track]) const progress = useMemo( () => playerSnapshot.progress, [playerSnapshot.progress] ) return (
{ player.progress = value }} onlyCallOnChangeAfterDragEnded={true} />
{formatDuration(progress * 1000, 'en', 'hh:mm:ss')} {formatDuration(track?.dt || 0, 'en', 'hh:mm:ss')}
) } const Cover = () => { const playerSnapshot = useSnapshot(player) const [cover, setCover] = useState('') const animationStartTime = useRef(0) const controls = useAnimation() const duration = 150 // ms useEffect(() => { const resizedCover = resizeImage( playerSnapshot.track?.al.picUrl || '', 'lg' ) const animate = async () => { animationStartTime.current = Date.now() await controls.start({ opacity: 0 }) setCover(resizedCover) } animate() }, [controls, playerSnapshot.track?.al.picUrl]) // 防止狂点下一首或上一首造成封面与歌曲不匹配的问题 useEffect(() => { const realCover = resizeImage(playerSnapshot.track?.al.picUrl ?? '', 'lg') if (cover !== realCover) setCover(realCover) }, [cover, playerSnapshot.track?.al.picUrl]) const onLoad = () => { const passedTime = Date.now() - animationStartTime.current controls.start({ opacity: 1, transition: { delay: passedTime > duration ? 0 : (duration - passedTime) / 1000, }, }) } return ( ) } const NowPlaying = () => { const playerSnapshot = useSnapshot(player) const state = useMemo(() => playerSnapshot.state, [playerSnapshot.state]) const track = useMemo(() => playerSnapshot.track, [playerSnapshot.track]) return (
{/* Cover */} {/* Info & Controls */}
{/* Track Info */}
{track?.name}
{track?.ar.map(a => a.name).join(', ')}
{/* Dividing line */}
{/* Progress */} {/* Controls */}
) } export default NowPlaying