mirror of
https://github.com/jeffvli/feishin.git
synced 2026-05-09 20:29:36 +02:00
Add queue drawer
This commit is contained in:
@@ -1,7 +1,9 @@
|
|||||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||||
import { motion } from 'framer-motion';
|
import { useDisclosure } from '@mantine/hooks';
|
||||||
|
import { AnimatePresence, motion, Variants } from 'framer-motion';
|
||||||
import isElectron from 'is-electron';
|
import isElectron from 'is-electron';
|
||||||
import throttle from 'lodash/throttle';
|
import throttle from 'lodash/throttle';
|
||||||
|
import { TbArrowBarLeft } from 'react-icons/tb';
|
||||||
import { Outlet } from 'react-router';
|
import { Outlet } from 'react-router';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import { UserDetailResponse } from '@/renderer/api/users.api';
|
import { UserDetailResponse } from '@/renderer/api/users.api';
|
||||||
@@ -66,7 +68,7 @@ const RightSidebarContainer = styled(motion.div)`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
const PlayerbarContainer = styled.footer`
|
const PlayerbarContainer = styled.footer`
|
||||||
z-index: 50;
|
z-index: 100;
|
||||||
grid-area: player;
|
grid-area: player;
|
||||||
background: var(--playerbar-bg);
|
background: var(--playerbar-bg);
|
||||||
filter: drop-shadow(0 -3px 1px rgba(0, 0, 0, 10%));
|
filter: drop-shadow(0 -3px 1px rgba(0, 0, 0, 10%));
|
||||||
@@ -93,6 +95,24 @@ const ResizeHandle = styled.div<{
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const QueueDrawer = styled(motion.div)`
|
||||||
|
background: var(--sidebar-bg);
|
||||||
|
border-left: var(--sidebar-border);
|
||||||
|
`;
|
||||||
|
|
||||||
|
const QueueDrawerButton = styled(motion.div)`
|
||||||
|
position: absolute;
|
||||||
|
top: 35%;
|
||||||
|
right: 0;
|
||||||
|
z-index: 55;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
width: 50px;
|
||||||
|
height: 25vh;
|
||||||
|
opacity: 0.3;
|
||||||
|
user-select: none;
|
||||||
|
`;
|
||||||
|
|
||||||
interface DefaultLayoutProps {
|
interface DefaultLayoutProps {
|
||||||
shell?: boolean;
|
shell?: boolean;
|
||||||
}
|
}
|
||||||
@@ -100,6 +120,7 @@ interface DefaultLayoutProps {
|
|||||||
export const DefaultLayout = ({ shell }: DefaultLayoutProps) => {
|
export const DefaultLayout = ({ shell }: DefaultLayoutProps) => {
|
||||||
const sidebar = useAppStore((state) => state.sidebar);
|
const sidebar = useAppStore((state) => state.sidebar);
|
||||||
const setSidebar = useAppStore((state) => state.setSidebar);
|
const setSidebar = useAppStore((state) => state.setSidebar);
|
||||||
|
const [opened, drawerHandler] = useDisclosure(false);
|
||||||
|
|
||||||
const sidebarRef = useRef<HTMLDivElement | null>(null);
|
const sidebarRef = useRef<HTMLDivElement | null>(null);
|
||||||
const rightSidebarRef = useRef<HTMLDivElement | null>(null);
|
const rightSidebarRef = useRef<HTMLDivElement | null>(null);
|
||||||
@@ -109,6 +130,42 @@ export const DefaultLayout = ({ shell }: DefaultLayoutProps) => {
|
|||||||
const login = useAuthStore((state) => state.login);
|
const login = useAuthStore((state) => state.login);
|
||||||
const setSettings = useSettingsStore((state) => state.setSettings);
|
const setSettings = useSettingsStore((state) => state.setSettings);
|
||||||
|
|
||||||
|
const queueDrawerVariants: Variants = {
|
||||||
|
closed: {
|
||||||
|
height: 'calc(100% - 120px)',
|
||||||
|
position: 'absolute',
|
||||||
|
right: 0,
|
||||||
|
width: 0,
|
||||||
|
},
|
||||||
|
open: {
|
||||||
|
height: 'calc(100% - 120px)',
|
||||||
|
position: 'absolute',
|
||||||
|
right: 0,
|
||||||
|
transition: {
|
||||||
|
duration: 0.5,
|
||||||
|
ease: 'anticipate',
|
||||||
|
},
|
||||||
|
width: '30vw',
|
||||||
|
zIndex: 75,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const queueSidebarVariants: Variants = {
|
||||||
|
closed: {
|
||||||
|
transition: { duration: 0.5 },
|
||||||
|
x: 1000,
|
||||||
|
},
|
||||||
|
open: {
|
||||||
|
transition: {
|
||||||
|
duration: 0.5,
|
||||||
|
ease: 'anticipate',
|
||||||
|
},
|
||||||
|
width: sidebar.rightWidth,
|
||||||
|
x: 0,
|
||||||
|
zIndex: 75,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isElectron()) {
|
if (!isElectron()) {
|
||||||
setSettings({
|
setSettings({
|
||||||
@@ -205,12 +262,36 @@ export const DefaultLayout = ({ shell }: DefaultLayoutProps) => {
|
|||||||
/>
|
/>
|
||||||
<Sidebar />
|
<Sidebar />
|
||||||
</SidebarContainer>
|
</SidebarContainer>
|
||||||
|
{!sidebar.rightExpanded && (
|
||||||
|
<QueueDrawerButton
|
||||||
|
whileHover={{ opacity: 0, transition: { duration: 0.2 } }}
|
||||||
|
onMouseEnter={() => drawerHandler.open()}
|
||||||
|
>
|
||||||
|
<TbArrowBarLeft size={20} />
|
||||||
|
</QueueDrawerButton>
|
||||||
|
)}
|
||||||
|
<AnimatePresence key="queue-drawer" initial={false}>
|
||||||
|
{opened && (
|
||||||
|
<QueueDrawer
|
||||||
|
key="queue-drawer"
|
||||||
|
animate="open"
|
||||||
|
exit="closed"
|
||||||
|
initial="closed"
|
||||||
|
variants={queueDrawerVariants}
|
||||||
|
onMouseLeave={() => drawerHandler.close()}
|
||||||
|
>
|
||||||
|
<SideQueue />
|
||||||
|
</QueueDrawer>
|
||||||
|
)}
|
||||||
|
</AnimatePresence>
|
||||||
|
<AnimatePresence key="queue-sidebar" initial={false}>
|
||||||
{sidebar.rightExpanded && (
|
{sidebar.rightExpanded && (
|
||||||
<RightSidebarContainer
|
<RightSidebarContainer
|
||||||
key="sb"
|
key="queue-sidebar"
|
||||||
animate={{ opacity: 1, scale: 1, x: 0 }}
|
animate="open"
|
||||||
initial={{ opacity: 0, x: 500 }}
|
exit="closed"
|
||||||
transition={{ duration: 0.3, ease: 'circOut' }}
|
initial="oclosed"
|
||||||
|
variants={queueSidebarVariants}
|
||||||
>
|
>
|
||||||
<ResizeHandle
|
<ResizeHandle
|
||||||
ref={rightSidebarRef}
|
ref={rightSidebarRef}
|
||||||
@@ -224,9 +305,9 @@ export const DefaultLayout = ({ shell }: DefaultLayoutProps) => {
|
|||||||
<SideQueue />
|
<SideQueue />
|
||||||
</RightSidebarContainer>
|
</RightSidebarContainer>
|
||||||
)}
|
)}
|
||||||
|
</AnimatePresence>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<Outlet />
|
<Outlet />
|
||||||
</MainContainer>
|
</MainContainer>
|
||||||
<PlayerbarContainer>
|
<PlayerbarContainer>
|
||||||
|
|||||||
Reference in New Issue
Block a user