frontend performance optimizations
This commit is contained in:
@@ -55,126 +55,125 @@ export default function Layout() {
|
||||
|
||||
return (
|
||||
<ThemeProvider theme={theme}>
|
||||
<SocketSubscriber>
|
||||
<Helmet>
|
||||
<title>
|
||||
{settings.appTitle}
|
||||
</title>
|
||||
</Helmet>
|
||||
<Box sx={{ display: 'flex' }}>
|
||||
<CssBaseline />
|
||||
<AppBar position="absolute" open={open}>
|
||||
<Toolbar sx={{ pr: '24px' }}>
|
||||
<IconButton
|
||||
edge="start"
|
||||
color="inherit"
|
||||
aria-label="open drawer"
|
||||
onClick={toggleDrawer}
|
||||
sx={{
|
||||
marginRight: '36px',
|
||||
...(open && { display: 'none' }),
|
||||
}}
|
||||
>
|
||||
<Menu />
|
||||
</IconButton>
|
||||
<Typography
|
||||
component="h1"
|
||||
variant="h6"
|
||||
color="inherit"
|
||||
noWrap
|
||||
sx={{ flexGrow: 1 }}
|
||||
>
|
||||
{settings.appTitle}
|
||||
</Typography>
|
||||
<Suspense fallback={i18n.t('loadingLabel')}>
|
||||
<FreeSpaceIndicator />
|
||||
</Suspense>
|
||||
<div style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
flexWrap: 'wrap',
|
||||
marginLeft: '4px',
|
||||
gap: 3,
|
||||
}}>
|
||||
<SettingsEthernet />
|
||||
<span>
|
||||
{isConnected ? settings.serverAddr : i18n.t('notConnectedText')}
|
||||
</span>
|
||||
</div>
|
||||
</Toolbar>
|
||||
</AppBar>
|
||||
<Drawer variant="permanent" open={open}>
|
||||
<Toolbar
|
||||
<SocketSubscriber />
|
||||
<Helmet>
|
||||
<title>
|
||||
{settings.appTitle}
|
||||
</title>
|
||||
</Helmet>
|
||||
<Box sx={{ display: 'flex' }}>
|
||||
<CssBaseline />
|
||||
<AppBar position="absolute" open={open}>
|
||||
<Toolbar sx={{ pr: '24px' }}>
|
||||
<IconButton
|
||||
edge="start"
|
||||
color="inherit"
|
||||
aria-label="open drawer"
|
||||
onClick={toggleDrawer}
|
||||
sx={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'flex-end',
|
||||
px: [1],
|
||||
marginRight: '36px',
|
||||
...(open && { display: 'none' }),
|
||||
}}
|
||||
>
|
||||
<IconButton onClick={toggleDrawer}>
|
||||
<ChevronLeft />
|
||||
</IconButton>
|
||||
</Toolbar>
|
||||
<Divider />
|
||||
<List component="nav">
|
||||
<Link to={'/'} style={
|
||||
{
|
||||
textDecoration: 'none',
|
||||
color: mode === 'dark' ? '#ffffff' : '#000000DE'
|
||||
}
|
||||
}>
|
||||
<ListItemButton>
|
||||
<ListItemIcon>
|
||||
<Dashboard />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary={i18n.t('homeButtonLabel')} />
|
||||
</ListItemButton>
|
||||
</Link>
|
||||
<Link to={'/archive'} style={
|
||||
{
|
||||
textDecoration: 'none',
|
||||
color: mode === 'dark' ? '#ffffff' : '#000000DE'
|
||||
}
|
||||
}>
|
||||
<ListItemButton>
|
||||
<ListItemIcon>
|
||||
<DownloadIcon />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary={i18n.t('archiveButtonLabel')} />
|
||||
</ListItemButton>
|
||||
</Link>
|
||||
<Link to={'/settings'} style={
|
||||
{
|
||||
textDecoration: 'none',
|
||||
color: mode === 'dark' ? '#ffffff' : '#000000DE'
|
||||
}
|
||||
}>
|
||||
<ListItemButton>
|
||||
<ListItemIcon>
|
||||
<SettingsIcon />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary={i18n.t('settingsButtonLabel')} />
|
||||
</ListItemButton>
|
||||
</Link>
|
||||
<ThemeToggler />
|
||||
<Logout />
|
||||
</List>
|
||||
</Drawer>
|
||||
<Box
|
||||
component="main"
|
||||
<Menu />
|
||||
</IconButton>
|
||||
<Typography
|
||||
component="h1"
|
||||
variant="h6"
|
||||
color="inherit"
|
||||
noWrap
|
||||
sx={{ flexGrow: 1 }}
|
||||
>
|
||||
{settings.appTitle}
|
||||
</Typography>
|
||||
<Suspense fallback={i18n.t('loadingLabel')}>
|
||||
<FreeSpaceIndicator />
|
||||
</Suspense>
|
||||
<div style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
flexWrap: 'wrap',
|
||||
marginLeft: '4px',
|
||||
gap: 3,
|
||||
}}>
|
||||
<SettingsEthernet />
|
||||
<span>
|
||||
{isConnected ? settings.serverAddr : i18n.t('notConnectedText')}
|
||||
</span>
|
||||
</div>
|
||||
</Toolbar>
|
||||
</AppBar>
|
||||
<Drawer variant="permanent" open={open}>
|
||||
<Toolbar
|
||||
sx={{
|
||||
flexGrow: 1,
|
||||
height: '100vh',
|
||||
overflow: 'auto',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'flex-end',
|
||||
px: [1],
|
||||
}}
|
||||
>
|
||||
<Toolbar />
|
||||
<Outlet />
|
||||
</Box>
|
||||
<IconButton onClick={toggleDrawer}>
|
||||
<ChevronLeft />
|
||||
</IconButton>
|
||||
</Toolbar>
|
||||
<Divider />
|
||||
<List component="nav">
|
||||
<Link to={'/'} style={
|
||||
{
|
||||
textDecoration: 'none',
|
||||
color: mode === 'dark' ? '#ffffff' : '#000000DE'
|
||||
}
|
||||
}>
|
||||
<ListItemButton>
|
||||
<ListItemIcon>
|
||||
<Dashboard />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary={i18n.t('homeButtonLabel')} />
|
||||
</ListItemButton>
|
||||
</Link>
|
||||
<Link to={'/archive'} style={
|
||||
{
|
||||
textDecoration: 'none',
|
||||
color: mode === 'dark' ? '#ffffff' : '#000000DE'
|
||||
}
|
||||
}>
|
||||
<ListItemButton>
|
||||
<ListItemIcon>
|
||||
<DownloadIcon />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary={i18n.t('archiveButtonLabel')} />
|
||||
</ListItemButton>
|
||||
</Link>
|
||||
<Link to={'/settings'} style={
|
||||
{
|
||||
textDecoration: 'none',
|
||||
color: mode === 'dark' ? '#ffffff' : '#000000DE'
|
||||
}
|
||||
}>
|
||||
<ListItemButton>
|
||||
<ListItemIcon>
|
||||
<SettingsIcon />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary={i18n.t('settingsButtonLabel')} />
|
||||
</ListItemButton>
|
||||
</Link>
|
||||
<ThemeToggler />
|
||||
<Logout />
|
||||
</List>
|
||||
</Drawer>
|
||||
<Box
|
||||
component="main"
|
||||
sx={{
|
||||
flexGrow: 1,
|
||||
height: '100vh',
|
||||
overflow: 'auto',
|
||||
}}
|
||||
>
|
||||
<Toolbar />
|
||||
<Outlet />
|
||||
</Box>
|
||||
<Toaster />
|
||||
</SocketSubscriber>
|
||||
</Box>
|
||||
<Toaster />
|
||||
</ThemeProvider>
|
||||
)
|
||||
}
|
||||
@@ -15,6 +15,7 @@ import {
|
||||
Stack,
|
||||
Typography
|
||||
} from '@mui/material'
|
||||
import { useCallback } from 'react'
|
||||
import { RPCResult } from '../types'
|
||||
import { ellipsis, formatSpeedMiB, mapProcessStatus, roundMiB } from '../utils'
|
||||
|
||||
@@ -34,11 +35,17 @@ const Resolution: React.FC<{ resolution?: string }> = ({ resolution }) => {
|
||||
}
|
||||
|
||||
const DownloadCard: React.FC<Props> = ({ download, onStop, onCopy }) => {
|
||||
const isCompleted = () => download.progress.percentage === '-1'
|
||||
const isCompleted = useCallback(
|
||||
() => download.progress.percentage === '-1',
|
||||
[download.progress.percentage]
|
||||
)
|
||||
|
||||
const percentageToNumber = () => isCompleted()
|
||||
? 100
|
||||
: Number(download.progress.percentage.replace('%', ''))
|
||||
const percentageToNumber = useCallback(
|
||||
() => isCompleted()
|
||||
? 100
|
||||
: Number(download.progress.percentage.replace('%', '')),
|
||||
[download.progress.percentage, isCompleted]
|
||||
)
|
||||
|
||||
return (
|
||||
<Card>
|
||||
|
||||
@@ -20,13 +20,11 @@ const DownloadsCardView: React.FC = () => {
|
||||
{
|
||||
downloads.map(download => (
|
||||
<Grid item xs={4} sm={8} md={6} key={download.id}>
|
||||
<>
|
||||
<DownloadCard
|
||||
download={download}
|
||||
onStop={() => abort(download.id)}
|
||||
onCopy={() => pushMessage(i18n.t('clipboardAction'), 'info')}
|
||||
/>
|
||||
</>
|
||||
<DownloadCard
|
||||
download={download}
|
||||
onStop={() => abort(download.id)}
|
||||
onCopy={() => pushMessage(i18n.t('clipboardAction'), 'info')}
|
||||
/>
|
||||
</Grid>
|
||||
))
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ export default function Splash() {
|
||||
const { i18n } = useI18n()
|
||||
const activeDownloads = useRecoilValue(activeDownloadsState)
|
||||
|
||||
if (!activeDownloads || activeDownloads.length !== 0) {
|
||||
if (activeDownloads.length !== 0) {
|
||||
return null
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user