import clsx from 'clsx';
import { AnimatePresence, HTMLMotionProps, motion, Variants } from 'motion/react';
import { Fragment, useEffect, useRef } from 'react';
import { generatePath, Link } from 'react-router';
import styles from './full-screen-player-image.module.css';
import { useItemImageUrl } from '/@/renderer/components/item-image/item-image';
import { AppRoute } from '/@/renderer/router/routes';
import { useNativeAspectRatio, usePlayerData, usePlayerSong } from '/@/renderer/store';
import { Badge } from '/@/shared/components/badge/badge';
import { Center } from '/@/shared/components/center/center';
import { Flex } from '/@/shared/components/flex/flex';
import { Group } from '/@/shared/components/group/group';
import { Icon } from '/@/shared/components/icon/icon';
import { Stack } from '/@/shared/components/stack/stack';
import { Text } from '/@/shared/components/text/text';
import { useSetState } from '/@/shared/hooks/use-set-state';
import { LibraryItem } from '/@/shared/types/domain-types';
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 MotionImage = motion.img;
const ImageWithPlaceholder = ({
className,
...props
}: HTMLMotionProps<'img'> & { placeholder?: string }) => {
const nativeAspectRatio = useNativeAspectRatio();
if (!props.src) {
return (
);
}
return (
);
};
export const FullScreenPlayerImage = () => {
const mainImageRef = useRef(null);
const currentSong = usePlayerSong();
const { nextSong } = usePlayerData();
const currentImageUrl = useItemImageUrl({
id: currentSong?.imageId || undefined,
itemType: LibraryItem.SONG,
serverId: currentSong?._serverId,
type: 'fullScreenPlayer',
});
const nextImageUrl = useItemImageUrl({
id: nextSong?.imageId || undefined,
itemType: LibraryItem.SONG,
serverId: nextSong?._serverId,
type: 'fullScreenPlayer',
});
const [imageState, setImageState] = useSetState({
bottomImage: nextImageUrl,
current: 0,
topImage: currentImageUrl,
});
// Track previous song to detect changes
const previousSongRef = useRef(currentSong?._uniqueId);
const imageStateRef = useRef(imageState);
// Keep ref in sync
useEffect(() => {
imageStateRef.current = imageState;
}, [imageState]);
// Update images when song or size changes
useEffect(() => {
if (currentSong?._uniqueId === previousSongRef.current) {
return;
}
const isTop = imageStateRef.current.current === 0;
setImageState({
bottomImage: isTop ? currentImageUrl : nextImageUrl,
current: isTop ? 1 : 0,
topImage: isTop ? nextImageUrl : currentImageUrl,
});
previousSongRef.current = currentSong?._uniqueId;
}, [currentSong?._uniqueId, currentImageUrl, nextSong?._uniqueId, nextImageUrl, 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?.releaseYear && (
{currentSong?.releaseYear}
)}
);
};