Update mui based layout ui
This commit is contained in:
parent
bfbdffdff5
commit
4e7f0136f7
14 changed files with 163 additions and 194 deletions
|
@ -1,7 +1,8 @@
|
|||
import AppBar from '@mui/material/AppBar';
|
||||
import Box from '@mui/material/Box';
|
||||
import { useTheme } from '@mui/material/styles';
|
||||
import React, { FC, useCallback, useEffect, useState } from 'react';
|
||||
import { type Theme } from '@mui/material/styles';
|
||||
import useMediaQuery from '@mui/material/useMediaQuery';
|
||||
import React, { FC, useCallback, useState } from 'react';
|
||||
import { Outlet, useLocation } from 'react-router-dom';
|
||||
|
||||
import AppBody from 'components/AppBody';
|
||||
|
@ -9,7 +10,6 @@ import AppToolbar from 'components/toolbar/AppToolbar';
|
|||
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';
|
||||
|
||||
|
@ -19,45 +19,37 @@ interface AppLayoutProps {
|
|||
drawerlessPaths: string[]
|
||||
}
|
||||
|
||||
interface DashboardAppSettings {
|
||||
isDrawerPinned: boolean
|
||||
}
|
||||
|
||||
const DEFAULT_APP_SETTINGS: DashboardAppSettings = {
|
||||
isDrawerPinned: false
|
||||
};
|
||||
|
||||
const AppLayout: FC<AppLayoutProps> = ({
|
||||
drawerlessPaths
|
||||
}) => {
|
||||
const [ appSettings, setAppSettings ] = useLocalStorage<DashboardAppSettings>('DashboardAppSettings', DEFAULT_APP_SETTINGS);
|
||||
const [ isDrawerActive, setIsDrawerActive ] = useState(appSettings.isDrawerPinned);
|
||||
const [ isDrawerActive, setIsDrawerActive ] = useState(false);
|
||||
const location = useLocation();
|
||||
const theme = useTheme();
|
||||
const { user } = useApi();
|
||||
|
||||
const isDrawerAvailable = !drawerlessPaths.some(path => location.pathname.startsWith(`/${path}`));
|
||||
const isSmallScreen = useMediaQuery((t: Theme) => t.breakpoints.up('sm'));
|
||||
const isDrawerAvailable = !isSmallScreen
|
||||
&& !drawerlessPaths.some(path => location.pathname.startsWith(`/${path}`));
|
||||
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}>
|
||||
<ElevationScroll elevate={false}>
|
||||
<AppBar
|
||||
position='fixed'
|
||||
sx={{ zIndex: (muiTheme) => muiTheme.zIndex.drawer + 1 }}
|
||||
sx={{
|
||||
width: {
|
||||
xs: '100%',
|
||||
sm: `calc(100% - ${DRAWER_WIDTH}px)`
|
||||
},
|
||||
ml: {
|
||||
xs: 0,
|
||||
sm: `${DRAWER_WIDTH}px`
|
||||
}
|
||||
}}
|
||||
>
|
||||
<AppToolbar
|
||||
isDrawerAvailable={isDrawerAvailable}
|
||||
|
@ -77,24 +69,7 @@ const AppLayout: FC<AppLayoutProps> = ({
|
|||
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
|
||||
})
|
||||
flexGrow: 1
|
||||
}}
|
||||
>
|
||||
<AppBody>
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
import ListItem from '@mui/material/ListItem';
|
||||
import List from '@mui/material/List';
|
||||
import React, { FC } from 'react';
|
||||
|
||||
import DrawerHeaderLink from 'apps/experimental/components/drawers/DrawerHeaderLink';
|
||||
import ResponsiveDrawer, { ResponsiveDrawerProps } from 'components/ResponsiveDrawer';
|
||||
|
||||
import ServerDrawerSection from './sections/ServerDrawerSection';
|
||||
|
@ -18,6 +21,11 @@ const AppDrawer: FC<ResponsiveDrawerProps> = ({
|
|||
onClose={onClose}
|
||||
onOpen={onOpen}
|
||||
>
|
||||
<List disablePadding>
|
||||
<ListItem disablePadding>
|
||||
<DrawerHeaderLink />
|
||||
</ListItem>
|
||||
</List>
|
||||
<ServerDrawerSection />
|
||||
<DevicesDrawerSection />
|
||||
<LiveTvDrawerSection />
|
||||
|
|
|
@ -1,46 +1,28 @@
|
|||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import React, { useCallback, useState } from 'react';
|
||||
import AppBar from '@mui/material/AppBar';
|
||||
import Box from '@mui/material/Box';
|
||||
import { useTheme } from '@mui/material/styles';
|
||||
import { type Theme } from '@mui/material/styles';
|
||||
import useMediaQuery from '@mui/material/useMediaQuery';
|
||||
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 AppToolbar from './components/AppToolbar';
|
||||
import AppDrawer, { isDrawerPath } from './components/drawers/AppDrawer';
|
||||
|
||||
import './AppOverrides.scss';
|
||||
|
||||
interface ExperimentalAppSettings {
|
||||
isDrawerPinned: boolean
|
||||
}
|
||||
|
||||
const DEFAULT_EXPERIMENTAL_APP_SETTINGS: ExperimentalAppSettings = {
|
||||
isDrawerPinned: false
|
||||
};
|
||||
|
||||
const AppLayout = () => {
|
||||
const [ appSettings, setAppSettings ] = useLocalStorage<ExperimentalAppSettings>('ExperimentalAppSettings', DEFAULT_EXPERIMENTAL_APP_SETTINGS);
|
||||
const [ isDrawerActive, setIsDrawerActive ] = useState(appSettings.isDrawerPinned);
|
||||
const [ isDrawerActive, setIsDrawerActive ] = useState(false);
|
||||
const { user } = useApi();
|
||||
const location = useLocation();
|
||||
const theme = useTheme();
|
||||
|
||||
const isDrawerAvailable = isDrawerPath(location.pathname);
|
||||
const isDrawerOpen = isDrawerActive && isDrawerAvailable && Boolean(user);
|
||||
|
||||
useEffect(() => {
|
||||
if (isDrawerActive !== appSettings.isDrawerPinned) {
|
||||
setAppSettings({
|
||||
...appSettings,
|
||||
isDrawerPinned: isDrawerActive
|
||||
});
|
||||
}
|
||||
}, [ appSettings, isDrawerActive, setAppSettings ]);
|
||||
const isSmallScreen = useMediaQuery((t: Theme) => t.breakpoints.up('sm'));
|
||||
const isDrawerAvailable = isDrawerPath(location.pathname) && Boolean(user);
|
||||
const isDrawerOpen = isDrawerActive && isDrawerAvailable;
|
||||
|
||||
const onToggleDrawer = useCallback(() => {
|
||||
setIsDrawerActive(!isDrawerActive);
|
||||
|
@ -48,46 +30,43 @@ const AppLayout = () => {
|
|||
|
||||
return (
|
||||
<Box sx={{ display: 'flex' }}>
|
||||
<ElevationScroll elevate={isDrawerOpen}>
|
||||
<ElevationScroll elevate={false}>
|
||||
<AppBar
|
||||
position='fixed'
|
||||
sx={{ zIndex: (muiTheme) => muiTheme.zIndex.drawer + 1 }}
|
||||
sx={{
|
||||
width: {
|
||||
xs: '100%',
|
||||
sm: isDrawerAvailable ? `calc(100% - ${DRAWER_WIDTH}px)` : '100%'
|
||||
},
|
||||
ml: {
|
||||
xs: 0,
|
||||
sm: isDrawerAvailable ? DRAWER_WIDTH : 0
|
||||
}
|
||||
}}
|
||||
>
|
||||
<AppToolbar
|
||||
isDrawerAvailable={!isSmallScreen && isDrawerAvailable}
|
||||
isDrawerOpen={isDrawerOpen}
|
||||
onDrawerButtonClick={onToggleDrawer}
|
||||
/>
|
||||
</AppBar>
|
||||
</ElevationScroll>
|
||||
|
||||
<AppDrawer
|
||||
open={isDrawerOpen}
|
||||
onClose={onToggleDrawer}
|
||||
onOpen={onToggleDrawer}
|
||||
/>
|
||||
{
|
||||
user && (
|
||||
<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
|
||||
})
|
||||
flexGrow: 1
|
||||
}}
|
||||
>
|
||||
<AppBody>
|
||||
|
|
|
@ -20,7 +20,7 @@ $mui-bp-xl: 1536px;
|
|||
}
|
||||
|
||||
// Fix the padding of some pages
|
||||
.homePage.libraryPage, // Home page
|
||||
.homePage.libraryPage.withTabs, // Home page
|
||||
.libraryPage:not(.withTabs) { // Tabless library pages
|
||||
padding-top: 3.25rem !important;
|
||||
}
|
||||
|
|
|
@ -8,22 +8,22 @@ import AppToolbar from 'components/toolbar/AppToolbar';
|
|||
import globalize from 'scripts/globalize';
|
||||
|
||||
import AppTabs from '../tabs/AppTabs';
|
||||
import { isDrawerPath } from '../drawers/AppDrawer';
|
||||
import RemotePlayButton from './RemotePlayButton';
|
||||
import SyncPlayButton from './SyncPlayButton';
|
||||
import { isTabPath } from '../tabs/tabRoutes';
|
||||
|
||||
interface AppToolbarProps {
|
||||
isDrawerAvailable: boolean
|
||||
isDrawerOpen: boolean
|
||||
onDrawerButtonClick: (event: React.MouseEvent<HTMLElement>) => void
|
||||
}
|
||||
|
||||
const ExperimentalAppToolbar: FC<AppToolbarProps> = ({
|
||||
isDrawerAvailable,
|
||||
isDrawerOpen,
|
||||
onDrawerButtonClick
|
||||
}) => {
|
||||
const location = useLocation();
|
||||
const isDrawerAvailable = isDrawerPath(location.pathname);
|
||||
const isTabsAvailable = isTabPath(location.pathname);
|
||||
|
||||
return (
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
import React, { FC } from 'react';
|
||||
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 { isTabPath } from '../tabs/tabRoutes';
|
||||
|
||||
import MainDrawerContent from './MainDrawerContent';
|
||||
|
||||
|
@ -27,20 +25,14 @@ const AppDrawer: FC<ResponsiveDrawerProps> = ({
|
|||
open = false,
|
||||
onClose,
|
||||
onOpen
|
||||
}) => {
|
||||
const location = useLocation();
|
||||
const hasSecondaryToolBar = isTabPath(location.pathname);
|
||||
|
||||
return (
|
||||
<ResponsiveDrawer
|
||||
hasSecondaryToolBar={hasSecondaryToolBar}
|
||||
open={open}
|
||||
onClose={onClose}
|
||||
onOpen={onOpen}
|
||||
>
|
||||
<MainDrawerContent />
|
||||
</ResponsiveDrawer>
|
||||
);
|
||||
};
|
||||
}) => (
|
||||
<ResponsiveDrawer
|
||||
open={open}
|
||||
onClose={onClose}
|
||||
onOpen={onOpen}
|
||||
>
|
||||
<MainDrawerContent />
|
||||
</ResponsiveDrawer>
|
||||
);
|
||||
|
||||
export default AppDrawer;
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
import Box from '@mui/material/Box';
|
||||
import ListItemIcon from '@mui/material/ListItemIcon';
|
||||
import ListItemText from '@mui/material/ListItemText';
|
||||
import React from 'react';
|
||||
|
||||
import { useApi } from 'hooks/useApi';
|
||||
import { useSystemInfo } from 'hooks/useSystemInfo';
|
||||
import ListItemLink from 'components/ListItemLink';
|
||||
|
||||
import appIcon from 'assets/img/icon-transparent.png';
|
||||
|
||||
const DrawerHeaderLink = () => {
|
||||
const { api } = useApi();
|
||||
const { data: systemInfo } = useSystemInfo(api);
|
||||
|
||||
return (
|
||||
<ListItemLink to='/'>
|
||||
<ListItemIcon sx={{ minWidth: 56 }}>
|
||||
<Box
|
||||
component='img'
|
||||
src={appIcon}
|
||||
sx={{ height: '2.5rem' }}
|
||||
/>
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
primary={systemInfo?.ServerName || 'Jellyfin'}
|
||||
primaryTypographyProps={{ variant: 'h6' }}
|
||||
secondary={systemInfo?.Version}
|
||||
/>
|
||||
</ListItemLink>);
|
||||
};
|
||||
|
||||
export default DrawerHeaderLink;
|
|
@ -1,7 +1,5 @@
|
|||
import type { BaseItemDto } from '@jellyfin/sdk/lib/generated-client/models/base-item-dto';
|
||||
import type { SystemInfo } from '@jellyfin/sdk/lib/generated-client/models/system-info';
|
||||
import { getUserViewsApi } from '@jellyfin/sdk/lib/utils/api/user-views-api';
|
||||
import { getSystemApi } from '@jellyfin/sdk/lib/utils/api/system-api';
|
||||
import Dashboard from '@mui/icons-material/Dashboard';
|
||||
import Edit from '@mui/icons-material/Edit';
|
||||
import Favorite from '@mui/icons-material/Favorite';
|
||||
|
@ -24,11 +22,11 @@ import { useWebConfig } from 'hooks/useWebConfig';
|
|||
import globalize from 'scripts/globalize';
|
||||
|
||||
import LibraryIcon from '../LibraryIcon';
|
||||
import DrawerHeaderLink from './DrawerHeaderLink';
|
||||
|
||||
const MainDrawerContent = () => {
|
||||
const { api, user } = useApi();
|
||||
const location = useLocation();
|
||||
const [ systemInfo, setSystemInfo ] = useState<SystemInfo>();
|
||||
const [ userViews, setUserViews ] = useState<BaseItemDto[]>([]);
|
||||
const webConfig = useWebConfig();
|
||||
|
||||
|
@ -45,15 +43,6 @@ const MainDrawerContent = () => {
|
|||
console.warn('[MainDrawer] failed to fetch user views', err);
|
||||
setUserViews([]);
|
||||
});
|
||||
|
||||
getSystemApi(api)
|
||||
.getSystemInfo()
|
||||
.then(({ data }) => {
|
||||
setSystemInfo(data);
|
||||
})
|
||||
.catch(err => {
|
||||
console.warn('[MainDrawer] failed to fetch system info', err);
|
||||
});
|
||||
} else {
|
||||
setUserViews([]);
|
||||
}
|
||||
|
@ -62,7 +51,10 @@ const MainDrawerContent = () => {
|
|||
return (
|
||||
<>
|
||||
{/* MAIN LINKS */}
|
||||
<List>
|
||||
<List sx={{ paddingTop: 0 }}>
|
||||
<ListItem disablePadding>
|
||||
<DrawerHeaderLink />
|
||||
</ListItem>
|
||||
<ListItem disablePadding>
|
||||
<ListItemLink to='/home.html' selected={isHomeSelected}>
|
||||
<ListItemIcon>
|
||||
|
@ -168,17 +160,6 @@ const MainDrawerContent = () => {
|
|||
</List>
|
||||
</>
|
||||
)}
|
||||
|
||||
{/* FOOTER */}
|
||||
<Divider style={{ marginTop: 'auto' }} />
|
||||
<List>
|
||||
<ListItem>
|
||||
<ListItemText
|
||||
primary={systemInfo?.ServerName ? systemInfo.ServerName : 'Jellyfin'}
|
||||
secondary={systemInfo?.Version ? `v${systemInfo.Version}` : ''}
|
||||
/>
|
||||
</ListItem>
|
||||
</List>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
import Box from '@mui/material/Box';
|
||||
import React, { useEffect } from 'react';
|
||||
import { DRAWER_WIDTH } from './ResponsiveDrawer';
|
||||
|
||||
const Backdrop = () => {
|
||||
useEffect(() => {
|
||||
|
@ -8,7 +10,14 @@ const Backdrop = () => {
|
|||
|
||||
return (
|
||||
<>
|
||||
<div className='backdropContainer' />
|
||||
<Box
|
||||
className='backdropContainer'
|
||||
sx={{
|
||||
left: {
|
||||
sm: DRAWER_WIDTH
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<div className='backgroundContainer' />
|
||||
</>
|
||||
);
|
||||
|
|
|
@ -1,17 +1,15 @@
|
|||
import { Theme } from '@mui/material/styles';
|
||||
import type { Theme } from '@mui/material/styles';
|
||||
import Box from '@mui/material/Box';
|
||||
import Drawer from '@mui/material/Drawer';
|
||||
import SwipeableDrawer from '@mui/material/SwipeableDrawer';
|
||||
import Toolbar from '@mui/material/Toolbar';
|
||||
import useMediaQuery from '@mui/material/useMediaQuery';
|
||||
import React, { FC, useCallback } from 'react';
|
||||
import React, { FC } from 'react';
|
||||
|
||||
import browser from 'scripts/browser';
|
||||
|
||||
export const DRAWER_WIDTH = 240;
|
||||
|
||||
export interface ResponsiveDrawerProps {
|
||||
hasSecondaryToolBar?: boolean
|
||||
open: boolean
|
||||
onClose: () => void
|
||||
onOpen: () => void
|
||||
|
@ -19,17 +17,11 @@ export interface ResponsiveDrawerProps {
|
|||
|
||||
const ResponsiveDrawer: FC<ResponsiveDrawerProps> = ({
|
||||
children,
|
||||
hasSecondaryToolBar = false,
|
||||
open = false,
|
||||
onClose,
|
||||
onOpen
|
||||
}) => {
|
||||
const isSmallScreen = useMediaQuery((theme: Theme) => theme.breakpoints.up('sm'));
|
||||
const isLargeScreen = useMediaQuery((theme: Theme) => theme.breakpoints.up('lg'));
|
||||
|
||||
const getToolbarStyles = useCallback((theme: Theme) => ({
|
||||
marginBottom: (hasSecondaryToolBar && !isLargeScreen) ? theme.spacing(6) : 0
|
||||
}), [ hasSecondaryToolBar, isLargeScreen ]);
|
||||
|
||||
return ( isSmallScreen ? (
|
||||
/* DESKTOP DRAWER */
|
||||
|
@ -42,14 +34,9 @@ const ResponsiveDrawer: FC<ResponsiveDrawerProps> = ({
|
|||
boxSizing: 'border-box'
|
||||
}
|
||||
}}
|
||||
variant='persistent'
|
||||
variant='permanent'
|
||||
anchor='left'
|
||||
open={open}
|
||||
>
|
||||
<Toolbar
|
||||
variant='dense'
|
||||
sx={getToolbarStyles}
|
||||
/>
|
||||
{children}
|
||||
</Drawer>
|
||||
) : (
|
||||
|
@ -65,10 +52,6 @@ const ResponsiveDrawer: FC<ResponsiveDrawerProps> = ({
|
|||
keepMounted: true // Better open performance on mobile.
|
||||
}}
|
||||
>
|
||||
<Toolbar
|
||||
variant='dense'
|
||||
sx={getToolbarStyles}
|
||||
/>
|
||||
<Box
|
||||
role='presentation'
|
||||
// Close the drawer when the content is clicked
|
||||
|
|
|
@ -4,11 +4,9 @@ import Box from '@mui/material/Box';
|
|||
import IconButton from '@mui/material/IconButton';
|
||||
import Toolbar from '@mui/material/Toolbar';
|
||||
import Tooltip from '@mui/material/Tooltip';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import React, { FC, ReactNode } from 'react';
|
||||
import { Link, useLocation } from 'react-router-dom';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
|
||||
import appIcon from 'assets/img/icon-transparent.png';
|
||||
import { appRouter } from 'components/router/appRouter';
|
||||
import { useApi } from 'hooks/useApi';
|
||||
import globalize from 'scripts/globalize';
|
||||
|
@ -84,35 +82,6 @@ const AppToolbar: FC<AppToolbarProps> = ({
|
|||
</Tooltip>
|
||||
)}
|
||||
|
||||
<Box
|
||||
component={Link}
|
||||
to='/'
|
||||
color='inherit'
|
||||
aria-label={globalize.translate('Home')}
|
||||
sx={{
|
||||
ml: 2,
|
||||
display: 'inline-flex',
|
||||
textDecoration: 'none'
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
component='img'
|
||||
src={appIcon}
|
||||
sx={{
|
||||
height: '2rem',
|
||||
marginInlineEnd: 1
|
||||
}}
|
||||
/>
|
||||
<Typography
|
||||
variant='h6'
|
||||
noWrap
|
||||
component='div'
|
||||
sx={{ display: { xs: 'none', sm: 'inline-block' } }}
|
||||
>
|
||||
Jellyfin
|
||||
</Typography>
|
||||
</Box>
|
||||
|
||||
{children}
|
||||
|
||||
{isUserLoggedIn && isUserMenuAvailable && (
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { getQuickConnectApi } from '@jellyfin/sdk/lib/utils/api/quick-connect-api';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { AxiosRequestConfig } from 'axios';
|
||||
import type { AxiosRequestConfig } from 'axios';
|
||||
|
||||
import { JellyfinApiContext, useApi } from './useApi';
|
||||
import { type JellyfinApiContext, useApi } from './useApi';
|
||||
|
||||
const fetchQuickConnectEnabled = async (
|
||||
apiContext: JellyfinApiContext,
|
||||
|
|
23
src/hooks/useSystemInfo.ts
Normal file
23
src/hooks/useSystemInfo.ts
Normal file
|
@ -0,0 +1,23 @@
|
|||
import { useQuery } from '@tanstack/react-query';
|
||||
import type { Api } from '@jellyfin/sdk';
|
||||
import { getSystemApi } from '@jellyfin/sdk/lib/utils/api/system-api';
|
||||
import type { AxiosRequestConfig } from 'axios';
|
||||
|
||||
const fetchSystemInfo = async (
|
||||
api: Api | undefined,
|
||||
options: AxiosRequestConfig
|
||||
) => {
|
||||
if (!api) throw new Error('No API instance available');
|
||||
|
||||
const response = await getSystemApi(api)
|
||||
.getSystemInfo(options);
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const useSystemInfo = (api: Api | undefined) => {
|
||||
return useQuery({
|
||||
queryKey: [ 'SystemInfo' ],
|
||||
queryFn: ({ signal }) => fetchSystemInfo(api, { signal }),
|
||||
enabled: !!api
|
||||
});
|
||||
};
|
|
@ -1,5 +1,7 @@
|
|||
import { createTheme } from '@mui/material/styles';
|
||||
|
||||
const LIST_ICON_WIDTH = 36;
|
||||
|
||||
/** The default Jellyfin app theme for mui */
|
||||
const theme = createTheme({
|
||||
palette: {
|
||||
|
@ -49,11 +51,26 @@ const theme = createTheme({
|
|||
variant: 'filled'
|
||||
}
|
||||
},
|
||||
MuiListItemIcon: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
minWidth: LIST_ICON_WIDTH
|
||||
}
|
||||
}
|
||||
},
|
||||
MuiListSubheader: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
// NOTE: Added for drawer subheaders, but maybe it won't work in other cases?
|
||||
backgroundColor: 'inherit'
|
||||
backgroundColor: 'inherit',
|
||||
position: 'initial'
|
||||
}
|
||||
}
|
||||
},
|
||||
MuiListItemText: {
|
||||
styleOverrides: {
|
||||
inset: {
|
||||
paddingLeft: LIST_ICON_WIDTH
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue