mirror of
https://github.com/jeffvli/feishin.git
synced 2026-05-16 21:50:35 +02:00
Add sidebar image option
This commit is contained in:
@@ -1,7 +1,10 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { Text } from '../../../components';
|
||||
import { usePlayerStore } from '../../../store';
|
||||
import { Font } from '../../../styles';
|
||||
import { Group } from '@mantine/core';
|
||||
import { motion, AnimatePresence } from 'framer-motion';
|
||||
import { RiArrowUpSLine } from 'react-icons/ri';
|
||||
import { Button, Text } from '@/renderer/components';
|
||||
import { useAppStore, usePlayerStore } from '@/renderer/store';
|
||||
import { Font } from '@/renderer/styles';
|
||||
|
||||
const LeftControlsContainer = styled.div`
|
||||
display: flex;
|
||||
@@ -25,7 +28,25 @@ const MetadataStack = styled.div`
|
||||
overflow: hidden;
|
||||
`;
|
||||
|
||||
const Image = styled(motion.div)<{ url: string }>`
|
||||
width: 70px;
|
||||
height: 70px;
|
||||
background-image: url(${(props) => props.url});
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
|
||||
button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&:hover button {
|
||||
display: block;
|
||||
}
|
||||
`;
|
||||
|
||||
export const LeftControls = () => {
|
||||
const hideImage = useAppStore((state) => state.sidebar.image);
|
||||
const setSidebar = useAppStore((state) => state.setSidebar);
|
||||
const song = usePlayerStore((state) => state.current.song);
|
||||
const title = song?.name;
|
||||
const artists = song?.artists?.map((artist) => artist?.name).join(', ');
|
||||
@@ -34,9 +55,31 @@ export const LeftControls = () => {
|
||||
return (
|
||||
<LeftControlsContainer>
|
||||
<ImageWrapper>
|
||||
{song?.imageUrl && (
|
||||
<img alt="img" height={60} src={song?.imageUrl} width={60} />
|
||||
)}
|
||||
<AnimatePresence>
|
||||
{!hideImage && (
|
||||
<Image
|
||||
key="playerbar-image"
|
||||
animate={{ opacity: 1, scale: 1, x: 0 }}
|
||||
exit={{ opacity: 0, y: 50 }}
|
||||
initial={{ opacity: 0, x: -50 }}
|
||||
transition={{ duration: 0.3, ease: 'easeInOut' }}
|
||||
url={song?.imageUrl}
|
||||
>
|
||||
<Group position="right">
|
||||
<Button
|
||||
compact
|
||||
variant="subtle"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
setSidebar({ image: true });
|
||||
}}
|
||||
>
|
||||
<RiArrowUpSLine color="white" size={20} />
|
||||
</Button>
|
||||
</Group>
|
||||
</Image>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</ImageWrapper>
|
||||
<MetadataStack>
|
||||
<Text
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
import { useMemo } from 'react';
|
||||
import styled from '@emotion/styled';
|
||||
import { Stack, Group, Grid, Accordion } from '@mantine/core';
|
||||
import { SpotlightProvider, openSpotlight } from '@mantine/spotlight';
|
||||
import { AnimatePresence, motion } from 'framer-motion';
|
||||
import {
|
||||
RiAlbumLine,
|
||||
RiArrowDownSLine,
|
||||
RiArrowLeftSLine,
|
||||
RiArrowRightSLine,
|
||||
RiDatabaseLine,
|
||||
@@ -16,120 +19,182 @@ import {
|
||||
} from 'react-icons/ri';
|
||||
import { useNavigate } from 'react-router';
|
||||
import { Button, TextInput } from '@/renderer/components';
|
||||
import { AppRoute } from '../../../router/routes';
|
||||
import { AppRoute } from '@/renderer/router/routes';
|
||||
import { useAppStore, usePlayerStore } from '@/renderer/store';
|
||||
import { SidebarItem } from './sidebar-item';
|
||||
|
||||
const StyledSidebar = styled.div``;
|
||||
const SidebarContainer = styled.div`
|
||||
height: 100%;
|
||||
max-height: calc(100vh - 120px); // Account for titlebar and playerbar
|
||||
`;
|
||||
|
||||
const Image = styled(motion.div)<{ height: string; url: string }>`
|
||||
height: ${(props) => props.height};
|
||||
background-image: ${(props) => `url(${props.url})`};
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
transition: background-image 0.5s linear 0.2s;
|
||||
|
||||
button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&:hover button {
|
||||
display: block;
|
||||
}
|
||||
`;
|
||||
|
||||
export const Sidebar = () => {
|
||||
const navigate = useNavigate();
|
||||
const playerData = usePlayerStore((state) => state.getPlayerData());
|
||||
const sidebar = useAppStore((state) => state.sidebar);
|
||||
const setSidebar = useAppStore((state) => state.setSidebar);
|
||||
|
||||
const showImage = sidebar.image;
|
||||
|
||||
const backgroundImage = useMemo(() => {
|
||||
return playerData.current.song.imageUrl;
|
||||
}, [playerData]);
|
||||
|
||||
return (
|
||||
<StyledSidebar>
|
||||
<Stack p={10}>
|
||||
<Grid>
|
||||
<Grid.Col span={8}>
|
||||
<SpotlightProvider actions={[]}>
|
||||
<TextInput
|
||||
readOnly
|
||||
icon={<RiSearchLine />}
|
||||
placeholder="Search"
|
||||
rightSectionWidth={90}
|
||||
onClick={() => openSpotlight()}
|
||||
/>
|
||||
</SpotlightProvider>
|
||||
</Grid.Col>
|
||||
<Grid.Col span={4}>
|
||||
<Group grow spacing={5}>
|
||||
<Button
|
||||
px={5}
|
||||
sx={{ color: 'var(--titlebar-fg)' }}
|
||||
variant="default"
|
||||
onClick={() => navigate(-1)}
|
||||
>
|
||||
<RiArrowLeftSLine size={20} />
|
||||
</Button>
|
||||
<Button
|
||||
px={5}
|
||||
sx={{ color: 'var(--titlebar-fg)' }}
|
||||
variant="default"
|
||||
onClick={() => navigate(1)}
|
||||
>
|
||||
<RiArrowRightSLine size={20} />
|
||||
</Button>
|
||||
</Group>
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
<SidebarContainer>
|
||||
<Stack justify="space-between" spacing={0} sx={{ height: '100%' }}>
|
||||
<Stack
|
||||
sx={{
|
||||
maxHeight: showImage ? `calc(100% - ${sidebar.leftWidth})` : '100%',
|
||||
}}
|
||||
>
|
||||
<Grid p={10}>
|
||||
<Grid.Col span={8}>
|
||||
<SpotlightProvider actions={[]}>
|
||||
<TextInput
|
||||
readOnly
|
||||
icon={<RiSearchLine />}
|
||||
placeholder="Search"
|
||||
rightSectionWidth={90}
|
||||
onClick={() => openSpotlight()}
|
||||
/>
|
||||
</SpotlightProvider>
|
||||
</Grid.Col>
|
||||
<Grid.Col span={4}>
|
||||
<Group grow spacing={5}>
|
||||
<Button
|
||||
px={5}
|
||||
sx={{ color: 'var(--titlebar-fg)' }}
|
||||
variant="default"
|
||||
onClick={() => navigate(-1)}
|
||||
>
|
||||
<RiArrowLeftSLine size={20} />
|
||||
</Button>
|
||||
<Button
|
||||
px={5}
|
||||
sx={{ color: 'var(--titlebar-fg)' }}
|
||||
variant="default"
|
||||
onClick={() => navigate(1)}
|
||||
>
|
||||
<RiArrowRightSLine size={20} />
|
||||
</Button>
|
||||
</Group>
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
<Stack spacing={0} sx={{ overflowY: 'auto' }}>
|
||||
<SidebarItem to={AppRoute.HOME}>
|
||||
<Group>
|
||||
<RiHome5Line size={15} />
|
||||
Home
|
||||
</Group>
|
||||
</SidebarItem>
|
||||
<SidebarItem>
|
||||
<SidebarItem.Link disabled to={AppRoute.EXPLORE}>
|
||||
<Group>
|
||||
<RiEyeLine />
|
||||
Explore
|
||||
</Group>
|
||||
</SidebarItem.Link>
|
||||
</SidebarItem>
|
||||
<Accordion disableChevronRotation multiple>
|
||||
<Accordion.Item value="library">
|
||||
<Accordion.Control p="1rem">
|
||||
<Group>
|
||||
<RiDatabaseLine size={15} />
|
||||
Library
|
||||
</Group>
|
||||
</Accordion.Control>
|
||||
<Accordion.Panel>
|
||||
<SidebarItem to={AppRoute.LIBRARY_ALBUMS}>
|
||||
<Group>
|
||||
<RiAlbumLine />
|
||||
Albums
|
||||
</Group>
|
||||
</SidebarItem>
|
||||
<SidebarItem disabled to={AppRoute.LIBRARY_SONGS}>
|
||||
<Group>
|
||||
<RiMusicLine />
|
||||
Tracks
|
||||
</Group>
|
||||
</SidebarItem>
|
||||
<SidebarItem disabled to={AppRoute.LIBRARY_ALBUMARTISTS}>
|
||||
<Group>
|
||||
<RiUserVoiceLine />
|
||||
Artists
|
||||
</Group>
|
||||
</SidebarItem>
|
||||
<SidebarItem disabled to={AppRoute.LIBRARY_FOLDERS}>
|
||||
<Group>
|
||||
<RiFolder3Line />
|
||||
Folders
|
||||
</Group>
|
||||
</SidebarItem>
|
||||
</Accordion.Panel>
|
||||
</Accordion.Item>
|
||||
<Accordion.Item value="collections">
|
||||
<Accordion.Control disabled p="1rem">
|
||||
<Group>
|
||||
<RiPlayListLine size={20} />
|
||||
Collections
|
||||
</Group>
|
||||
</Accordion.Control>
|
||||
<Accordion.Panel />
|
||||
</Accordion.Item>
|
||||
<Accordion.Item value="playlists">
|
||||
<Accordion.Control disabled p="1rem">
|
||||
<Group>
|
||||
<RiPlayListLine size={20} />
|
||||
Playlists
|
||||
</Group>
|
||||
</Accordion.Control>
|
||||
<Accordion.Panel />
|
||||
</Accordion.Item>
|
||||
</Accordion>
|
||||
</Stack>
|
||||
</Stack>
|
||||
<AnimatePresence>
|
||||
{showImage && (
|
||||
<Image
|
||||
key="sidebar-image"
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
exit={{ opacity: 0 }}
|
||||
height={sidebar.leftWidth}
|
||||
initial={{ opacity: 0, y: 200 }}
|
||||
transition={{ duration: 0.3, ease: 'easeInOut' }}
|
||||
url={backgroundImage}
|
||||
>
|
||||
<Group position="right">
|
||||
<Button
|
||||
compact
|
||||
variant="subtle"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
setSidebar({ image: false });
|
||||
}}
|
||||
>
|
||||
<RiArrowDownSLine color="white" size={20} />
|
||||
</Button>
|
||||
</Group>
|
||||
</Image>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</Stack>
|
||||
<SidebarItem to={AppRoute.HOME}>
|
||||
<Group>
|
||||
<RiHome5Line size={15} />
|
||||
Home
|
||||
</Group>
|
||||
</SidebarItem>
|
||||
<SidebarItem>
|
||||
<SidebarItem.Link disabled to={AppRoute.EXPLORE}>
|
||||
<Group>
|
||||
<RiEyeLine />
|
||||
Explore
|
||||
</Group>
|
||||
</SidebarItem.Link>
|
||||
</SidebarItem>
|
||||
|
||||
<Accordion disableChevronRotation multiple>
|
||||
<Accordion.Item value="library">
|
||||
<Accordion.Control p="1rem">
|
||||
<Group>
|
||||
<RiDatabaseLine size={15} />
|
||||
Library
|
||||
</Group>
|
||||
</Accordion.Control>
|
||||
<Accordion.Panel>
|
||||
<SidebarItem to={AppRoute.LIBRARY_ALBUMS}>
|
||||
<Group>
|
||||
<RiAlbumLine />
|
||||
Albums
|
||||
</Group>
|
||||
</SidebarItem>
|
||||
<SidebarItem disabled to={AppRoute.LIBRARY_SONGS}>
|
||||
<Group>
|
||||
<RiMusicLine />
|
||||
Tracks
|
||||
</Group>
|
||||
</SidebarItem>
|
||||
<SidebarItem disabled to={AppRoute.LIBRARY_ALBUMARTISTS}>
|
||||
<Group>
|
||||
<RiUserVoiceLine />
|
||||
Artists
|
||||
</Group>
|
||||
</SidebarItem>
|
||||
<SidebarItem disabled to={AppRoute.LIBRARY_FOLDERS}>
|
||||
<Group>
|
||||
<RiFolder3Line />
|
||||
Folders
|
||||
</Group>
|
||||
</SidebarItem>
|
||||
</Accordion.Panel>
|
||||
</Accordion.Item>
|
||||
<Accordion.Item value="collections">
|
||||
<Accordion.Control disabled p="1rem">
|
||||
<Group>
|
||||
<RiPlayListLine size={20} />
|
||||
Collections
|
||||
</Group>
|
||||
</Accordion.Control>
|
||||
<Accordion.Panel />
|
||||
</Accordion.Item>
|
||||
<Accordion.Item value="playlists">
|
||||
<Accordion.Control disabled p="1rem">
|
||||
<Group>
|
||||
<RiPlayListLine size={20} />
|
||||
Playlists
|
||||
</Group>
|
||||
</Accordion.Control>
|
||||
<Accordion.Panel />
|
||||
</Accordion.Item>
|
||||
</Accordion>
|
||||
</StyledSidebar>
|
||||
</SidebarContainer>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user