mirror of
https://github.com/jeffvli/feishin.git
synced 2026-05-09 20:29:36 +02:00
Animate activity song change
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Avatar, Group, Indicator, Stack } from '@mantine/core';
|
import { Avatar, Group, Indicator, Stack } from '@mantine/core';
|
||||||
import { useDisclosure } from '@mantine/hooks';
|
import { useDisclosure } from '@mantine/hooks';
|
||||||
import { motion } from 'framer-motion';
|
import { AnimatePresence, motion, Variants } from 'framer-motion';
|
||||||
import { IoIosPause } from 'react-icons/io';
|
import { IoIosPause } from 'react-icons/io';
|
||||||
import { RiPlayFill, RiServerLine, RiUserLine } from 'react-icons/ri';
|
import { RiPlayFill, RiServerLine, RiUserLine } from 'react-icons/ri';
|
||||||
import { generatePath } from 'react-router';
|
import { generatePath } from 'react-router';
|
||||||
@@ -57,6 +57,8 @@ const ItemInfoContainer = styled.div`
|
|||||||
grid-area: info;
|
grid-area: info;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const MotionStack = motion(Stack);
|
||||||
|
|
||||||
export const UserActivityItem = ({ user }: UserActivityItemProps) => {
|
export const UserActivityItem = ({ user }: UserActivityItemProps) => {
|
||||||
const { data: serverMap } = useServerMap();
|
const { data: serverMap } = useServerMap();
|
||||||
const [opened, { close, open }] = useDisclosure(false);
|
const [opened, { close, open }] = useDisclosure(false);
|
||||||
@@ -72,9 +74,27 @@ export const UserActivityItem = ({ user }: UserActivityItemProps) => {
|
|||||||
const status = user?.activity?.status;
|
const status = user?.activity?.status;
|
||||||
const albumArtists = user?.activity?.song?.albumArtists;
|
const albumArtists = user?.activity?.song?.albumArtists;
|
||||||
|
|
||||||
console.log('serverMap', serverMap);
|
const infoVariants: Variants = {
|
||||||
|
animate: {
|
||||||
console.log('serverId', serverId);
|
opacity: 1,
|
||||||
|
transition: {
|
||||||
|
duration: 0.2,
|
||||||
|
},
|
||||||
|
x: 0,
|
||||||
|
},
|
||||||
|
exit: {
|
||||||
|
opacity: 0,
|
||||||
|
transition: {
|
||||||
|
duration: 0.2,
|
||||||
|
ease: 'easeInOut',
|
||||||
|
},
|
||||||
|
x: 10,
|
||||||
|
},
|
||||||
|
initial: {
|
||||||
|
opacity: 0,
|
||||||
|
x: -10,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ActivityContainer>
|
<ActivityContainer>
|
||||||
@@ -113,56 +133,69 @@ export const UserActivityItem = ({ user }: UserActivityItemProps) => {
|
|||||||
</ItemImageContainer>
|
</ItemImageContainer>
|
||||||
<ItemInfoContainer>
|
<ItemInfoContainer>
|
||||||
<Group noWrap position="apart">
|
<Group noWrap position="apart">
|
||||||
<Stack spacing={0} sx={{ lineHeight: 1, maxWidth: '80%' }}>
|
<AnimatePresence exitBeforeEnter initial={false}>
|
||||||
<Text overflow="hidden" size="sm">
|
<MotionStack
|
||||||
{songId ? songName : 'Idle...'}
|
key={`activity-user-${user?.id}-${songId}`}
|
||||||
</Text>
|
animate="animate"
|
||||||
<Text $secondary overflow="hidden" size="xs">
|
exit="exit"
|
||||||
{albumArtists?.length ? (
|
initial="initial"
|
||||||
albumArtists.map((artist, index) => (
|
spacing={0}
|
||||||
<React.Fragment
|
sx={{ lineHeight: 1, maxWidth: '80%' }}
|
||||||
key={`activity-${user.id}-artist-${artist.id}`}
|
variants={infoVariants}
|
||||||
>
|
>
|
||||||
{index > 0 ? ', ' : null}
|
<Text $secondary={!songId} overflow="hidden" size="sm">
|
||||||
<Text
|
{songId ? songName : 'Not Playing'}
|
||||||
$link
|
|
||||||
$secondary
|
|
||||||
component={Link}
|
|
||||||
overflow="hidden"
|
|
||||||
size="xs"
|
|
||||||
sx={{ width: 'fit-content' }}
|
|
||||||
to={generatePath(AppRoute.LIBRARY_ALBUMARTISTS_DETAIL, {
|
|
||||||
albumArtistId: artist.id,
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
{artist.name}
|
|
||||||
</Text>
|
|
||||||
</React.Fragment>
|
|
||||||
))
|
|
||||||
) : (
|
|
||||||
<Text $secondary>—</Text>
|
|
||||||
)}
|
|
||||||
</Text>
|
|
||||||
{albumId ? (
|
|
||||||
<Text
|
|
||||||
$link
|
|
||||||
$secondary
|
|
||||||
component={Link}
|
|
||||||
overflow="hidden"
|
|
||||||
size="xs"
|
|
||||||
sx={{ width: 'fit-content' }}
|
|
||||||
to={generatePath(AppRoute.LIBRARY_ALBUMS_DETAIL, {
|
|
||||||
albumId,
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
{albumName}
|
|
||||||
</Text>
|
</Text>
|
||||||
) : (
|
|
||||||
<Text $secondary overflow="hidden" size="xs">
|
<Text $secondary overflow="hidden" size="xs">
|
||||||
—
|
{albumArtists?.length ? (
|
||||||
|
albumArtists.map((artist, index) => (
|
||||||
|
<React.Fragment
|
||||||
|
key={`activity-${user.id}-artist-${artist.id}`}
|
||||||
|
>
|
||||||
|
{index > 0 ? ', ' : null}
|
||||||
|
<Text
|
||||||
|
$link
|
||||||
|
$secondary
|
||||||
|
component={Link}
|
||||||
|
overflow="hidden"
|
||||||
|
size="xs"
|
||||||
|
sx={{ width: 'fit-content' }}
|
||||||
|
to={generatePath(
|
||||||
|
AppRoute.LIBRARY_ALBUMARTISTS_DETAIL,
|
||||||
|
{
|
||||||
|
albumArtistId: artist.id,
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{artist.name}
|
||||||
|
</Text>
|
||||||
|
</React.Fragment>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<Text $secondary>—</Text>
|
||||||
|
)}
|
||||||
</Text>
|
</Text>
|
||||||
)}
|
{albumId ? (
|
||||||
</Stack>
|
<Text $secondary overflow="hidden" size="xs">
|
||||||
|
<Text
|
||||||
|
$link
|
||||||
|
$secondary
|
||||||
|
component={Link}
|
||||||
|
sx={{ width: 'fit-content' }}
|
||||||
|
to={generatePath(AppRoute.LIBRARY_ALBUMS_DETAIL, {
|
||||||
|
albumId,
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
{albumName}
|
||||||
|
</Text>
|
||||||
|
</Text>
|
||||||
|
) : (
|
||||||
|
<Text $secondary overflow="hidden" size="xs">
|
||||||
|
—
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
|
</MotionStack>
|
||||||
|
</AnimatePresence>
|
||||||
<Group>
|
<Group>
|
||||||
{status === 'playing' ? (
|
{status === 'playing' ? (
|
||||||
<RiPlayFill color="var(--main-fg)" size={15} />
|
<RiPlayFill color="var(--main-fg)" size={15} />
|
||||||
|
|||||||
Reference in New Issue
Block a user