1
0
Fork 0
mirror of https://github.com/jellyfin/jellyfin-web synced 2025-03-30 19:56:21 +00:00

Refactor common navigation components

This commit is contained in:
Bill Thornton 2023-09-25 02:13:16 -04:00
parent 06386a8eb6
commit 1a934c7956
8 changed files with 138 additions and 75 deletions

View file

@ -1,15 +1,103 @@
import React from 'react';
import { Outlet } from 'react-router-dom';
import AppBar from '@mui/material/AppBar';
import Box from '@mui/material/Box';
import { useTheme } from '@mui/material/styles';
import React, { useCallback, useEffect, useState } from 'react';
import { Outlet, useLocation } from 'react-router-dom';
import AppBody from 'components/AppBody';
import ElevationScroll from 'components/ElevationScroll';
import { DRAWER_WIDTH } from 'components/ResponsiveDrawer';
import { useApi } from 'hooks/useApi';
import { useLocalStorage } from 'hooks/useLocalStorage';
import AppDrawer from './components/drawer/AppDrawer';
// FIXME: Remove main app override styles
import '../experimental/AppOverrides.scss';
import AppToolbar from 'components/toolbar/AppToolbar';
interface DashboardAppSettings {
isDrawerPinned: boolean
}
const DEFAULT_APP_SETTINGS: DashboardAppSettings = {
isDrawerPinned: false
};
const AppLayout = () => {
const [ appSettings, setAppSettings ] = useLocalStorage<DashboardAppSettings>('DashboardAppSettings', DEFAULT_APP_SETTINGS);
const [ isDrawerActive, setIsDrawerActive ] = useState(appSettings.isDrawerPinned);
const location = useLocation();
const theme = useTheme();
const { user } = useApi();
// FIXME: Use const for metadata editor
const isDrawerAvailable = !location.pathname.startsWith('/metadata');
const isDrawerOpen = isDrawerActive && isDrawerAvailable && Boolean(user);
useEffect(() => {
if (isDrawerActive !== appSettings.isDrawerPinned) {
setAppSettings({
...appSettings,
isDrawerPinned: isDrawerActive
});
}
}, [ appSettings, isDrawerActive, setAppSettings ]);
const onToggleDrawer = useCallback(() => {
setIsDrawerActive(!isDrawerActive);
}, [ isDrawerActive, setIsDrawerActive ]);
return (
<Box sx={{ display: 'flex' }}>
<ElevationScroll elevate={isDrawerOpen}>
<AppBar
position='fixed'
sx={{ zIndex: (muiTheme) => muiTheme.zIndex.drawer + 1 }}
>
<AppToolbar
isDrawerAvailable={isDrawerAvailable}
isDrawerOpen={isDrawerOpen}
onDrawerButtonClick={onToggleDrawer}
/>
</AppBar>
</ElevationScroll>
<AppDrawer
open={isDrawerOpen}
onClose={onToggleDrawer}
onOpen={onToggleDrawer}
/>
<Box
component='main'
sx={{
width: '100%',
flexGrow: 1,
transition: theme.transitions.create('margin', {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen
}),
marginLeft: 0,
...(isDrawerAvailable && {
marginLeft: {
sm: `-${DRAWER_WIDTH}px`
}
}),
...(isDrawerActive && {
transition: theme.transitions.create('margin', {
easing: theme.transitions.easing.easeOut,
duration: theme.transitions.duration.enteringScreen
}),
marginLeft: 0
})
}}
>
<AppBody>
<Outlet />
</AppBody>
</Box>
</Box>
);
};

View file

@ -0,0 +1,29 @@
import React, { FC } from 'react';
import ResponsiveDrawer, { ResponsiveDrawerProps } from 'components/ResponsiveDrawer';
import ServerDrawerSection from './sections/ServerDrawerSection';
import DevicesDrawerSection from './sections/DevicesDrawerSection';
import LiveTvDrawerSection from './sections/LiveTvDrawerSection';
import AdvancedDrawerSection from './sections/AdvancedDrawerSection';
import PluginDrawerSection from './sections/PluginDrawerSection';
const AppDrawer: FC<ResponsiveDrawerProps> = ({
open = false,
onClose,
onOpen
}) => (
<ResponsiveDrawer
open={open}
onClose={onClose}
onOpen={onOpen}
>
<ServerDrawerSection />
<DevicesDrawerSection />
<LiveTvDrawerSection />
<AdvancedDrawerSection />
<PluginDrawerSection />
</ResponsiveDrawer>
);
export default AppDrawer;

View file

@ -1,23 +1,15 @@
import React, { FC } from 'react';
import { Route, Routes, useLocation } from 'react-router-dom';
import { useLocation } from 'react-router-dom';
import ResponsiveDrawer, { ResponsiveDrawerProps } from 'components/ResponsiveDrawer';
import { ASYNC_USER_ROUTES } from '../../routes/asyncRoutes';
import { LEGACY_USER_ROUTES } from '../../routes/legacyRoutes';
import AdvancedDrawerSection from './dashboard/AdvancedDrawerSection';
import DevicesDrawerSection from './dashboard/DevicesDrawerSection';
import LiveTvDrawerSection from './dashboard/LiveTvDrawerSection';
import PluginDrawerSection from './dashboard/PluginDrawerSection';
import ServerDrawerSection from './dashboard/ServerDrawerSection';
import MainDrawerContent from './MainDrawerContent';
import { isTabPath } from '../tabs/tabRoutes';
export const DRAWER_WIDTH = 240;
const DRAWERLESS_ROUTES = [
'metadata', // metadata manager
'video' // video player
];
@ -26,75 +18,29 @@ const MAIN_DRAWER_ROUTES = [
...LEGACY_USER_ROUTES
].filter(route => !DRAWERLESS_ROUTES.includes(route.path));
const ADMIN_DRAWER_ROUTES = [
{ path: '/configurationpage' } // Plugin configuration page
].filter(route => !DRAWERLESS_ROUTES.includes(route.path));
/** Utility function to check if a path has a drawer. */
export const isDrawerPath = (path: string) => (
MAIN_DRAWER_ROUTES.some(route => route.path === path || `/${route.path}` === path)
|| ADMIN_DRAWER_ROUTES.some(route => route.path === path || `/${route.path}` === path)
);
const Drawer: FC<ResponsiveDrawerProps> = ({ children, ...props }) => {
const location = useLocation();
const hasSecondaryToolBar = isTabPath(location.pathname);
return (
<ResponsiveDrawer
{...props}
hasSecondaryToolBar={hasSecondaryToolBar}
>
{children}
</ResponsiveDrawer>
);
};
const AppDrawer: FC<ResponsiveDrawerProps> = ({
open = false,
onClose,
onOpen
}) => (
<Routes>
{
MAIN_DRAWER_ROUTES.map(route => (
<Route
key={route.path}
path={route.path}
element={
<Drawer
}) => {
const location = useLocation();
const hasSecondaryToolBar = isTabPath(location.pathname);
return (
<ResponsiveDrawer
hasSecondaryToolBar={hasSecondaryToolBar}
open={open}
onClose={onClose}
onOpen={onOpen}
>
<MainDrawerContent />
</Drawer>
}
/>
))
}
{
ADMIN_DRAWER_ROUTES.map(route => (
<Route
key={route.path}
path={route.path}
element={
<Drawer
open={open}
onClose={onClose}
onOpen={onOpen}
>
<ServerDrawerSection />
<DevicesDrawerSection />
<LiveTvDrawerSection />
<AdvancedDrawerSection />
<PluginDrawerSection />
</Drawer>
}
/>
))
}
</Routes>
);
</ResponsiveDrawer>
);
};
export default AppDrawer;