import { Flex, Stack, Group, Center } from '@mantine/core'; import { useSetState } from '@mantine/hooks'; import { AnimatePresence, HTMLMotionProps, motion, Variants } from 'framer-motion'; import { useEffect } from 'react'; import { RiAlbumFill } from 'react-icons/ri'; import { generatePath } from 'react-router'; import { Link } from 'react-router-dom'; import styled from 'styled-components'; import { QueueSong } from '/@/renderer/api/types'; import { Badge, Text, TextTitle } from '/@/renderer/components'; import { useFastAverageColor } from '/@/renderer/hooks'; import { AppRoute } from '/@/renderer/router/routes'; import { PlayerData, usePlayerData, usePlayerStore } from '/@/renderer/store'; const PlayerContainer = styled(Flex)` flex: 0.5; gap: '1rem'; @media screen and (min-width: 1080px) { max-width: 60%; } `; const Image = styled(motion.img)` position: absolute; width: 100%; max-width: 100%; max-height: 100%; object-fit: cover; border-radius: 5px; box-shadow: 2px 2px 10px 2px rgba(0, 0, 0, 40%); `; const ImageContainer = styled(motion.div)` position: relative; display: flex; align-items: center; height: 65%; aspect-ratio: 1/1; max-width: 100%; `; const imageVariants: Variants = { closed: { opacity: 0, transition: { duration: 0.8, ease: 'linear', }, }, initial: { opacity: 0, }, open: (custom) => { const { isOpen } = custom; return { opacity: isOpen ? 1 : 0, transition: { duration: 0.4, ease: 'linear', }, }; }, }; const scaleImageUrl = (url?: string | null) => { return url ?.replace(/&size=\d+/, '&size=800') .replace(/\?width=\d+/, '?width=800') .replace(/&height=\d+/, '&height=800'); }; const ImageWithPlaceholder = ({ ...props }: HTMLMotionProps<'img'>) => { if (!props.src) { return (
); } return ; }; export const FullScreenPlayerImage = () => { const { queue } = usePlayerData(); const currentSong = queue.current; const background = useFastAverageColor(queue.current?.imageUrl, true, 'dominant'); const imageKey = `image-${background}`; const [imageState, setImageState] = useSetState({ bottomImage: scaleImageUrl(queue.next?.imageUrl), current: 0, topImage: scaleImageUrl(queue.current?.imageUrl), }); useEffect(() => { const unsubSongChange = usePlayerStore.subscribe( (state) => [state.current.song, state.actions.getPlayerData().queue], (state) => { const isTop = imageState.current === 0; const queue = state[1] as PlayerData['queue']; const currentImageUrl = scaleImageUrl(queue.current?.imageUrl); const nextImageUrl = scaleImageUrl(queue.next?.imageUrl); setImageState({ bottomImage: isTop ? currentImageUrl : nextImageUrl, current: isTop ? 1 : 0, topImage: isTop ? nextImageUrl : currentImageUrl, }); }, { equalityFn: (a, b) => (a[0] as QueueSong)?.id === (b[0] as QueueSong)?.id }, ); return () => { unsubSongChange(); }; }, [imageState, queue, setImageState]); return ( {imageState.current === 0 && ( )} {imageState.current === 1 && ( )} {currentSong?.name} {currentSong?.album}{' '} {currentSong?.artists?.map((artist, index) => ( {index > 0 && ( )} {artist.name} ))} {currentSong?.container && ( {currentSong?.container} {currentSong?.bitRate} )} {currentSong?.releaseYear && {currentSong?.releaseYear}} ); };