Show download queue size in nav bar

This commit is contained in:
schroda
2025-05-24 17:10:29 +02:00
parent 2d34f67df4
commit 86578593ca
6 changed files with 66 additions and 18 deletions

View File

@@ -164,6 +164,10 @@
"failed_to_retry": "Could not retry failed download."
}
},
"info": {
"paused": "Paused — $t(download.queue.info.remaining)",
"remaining": "{{count}} remaining"
},
"label": {
"delete_all": "Delete all",
"no_downloads": "No downloads"
@@ -455,6 +459,7 @@
"sort": "Sort",
"standard": "Standard",
"started": "Started",
"stopped": "Stopped",
"success": "Success",
"system": "System",
"type": "Type",

View File

@@ -19,8 +19,11 @@ import GetAppOutlinedIcon from '@mui/icons-material/GetAppOutlined';
import MoreHorizIcon from '@mui/icons-material/MoreHoriz';
import SettingsIcon from '@mui/icons-material/Settings';
import InfoIcon from '@mui/icons-material/Info';
import { useTranslation } from 'react-i18next';
import { NavbarItem, NavBarItemMoreGroup } from '@/modules/navigation-bar/NavigationBar.types.ts';
import { AppRoutes } from '@/modules/core/AppRoute.constants.ts';
import { requestManager } from '@/lib/requests/RequestManager.ts';
import { DownloaderState } from '@/lib/graphql/generated/graphql.ts';
type RestrictedNavBarItem<Show extends NavbarItem['show']> = Omit<NavbarItem, 'show'> & { show: Show };
@@ -67,6 +70,19 @@ const NAVIGATION_BAR_DESKTOP_ITEMS = [
IconComponent: GetAppOutlinedIcon,
show: 'desktop',
moreGroup: NavBarItemMoreGroup.HIDDEN_ITEM,
useBadge: () => {
const { t } = useTranslation();
const { data } = requestManager.useGetDownloadStatus();
const downloadStatus = data?.downloadStatus;
const isPaused = downloadStatus?.state === DownloaderState.Stopped;
const count = downloadStatus?.queue.length ?? 0;
return {
count,
title: t(isPaused ? 'download.queue.info.paused' : 'download.queue.info.remaining', { count }),
};
},
},
{
path: AppRoutes.settings.path,

View File

@@ -30,6 +30,7 @@ export interface NavbarItem {
IconComponent: OverridableComponent<SvgIconTypeMap<{}, 'svg'>>;
show: 'mobile' | 'desktop' | 'both';
moreGroup: NavBarItemMoreGroup;
useBadge?: () => { count: number; title: string };
}
export type NavbarContextType = {

View File

@@ -20,6 +20,8 @@ import { styled, useTheme } from '@mui/material/styles';
import { useCallback, useMemo, useRef } from 'react';
import Box from '@mui/material/Box';
import ListItem from '@mui/material/ListItem';
import Badge from '@mui/material/Badge';
import Typography from '@mui/material/Typography';
import { CustomTooltip } from '@/modules/core/components/CustomTooltip.tsx';
import { ListItemLink } from '@/modules/core/components/lists/ListItemLink.tsx';
import { useGetOptionForDirection } from '@/modules/theme/services/ThemeCreator.ts';
@@ -37,11 +39,12 @@ const DrawerHeader = styled('div')(({ theme }) => ({
...theme.mixins.toolbar,
}));
const NavigationBarItem = ({ path, title, IconComponent, SelectedIconComponent }: NavbarItem) => {
const NavigationBarItem = ({ path, title, IconComponent, SelectedIconComponent, useBadge }: NavbarItem) => {
const { t } = useTranslation();
const location = useLocation();
const { isCollapsed } = useNavBarContext();
const theme = useTheme();
const badgeInfo = useBadge?.();
const isActive = location.pathname.startsWith(path);
const Icon = isActive ? SelectedIconComponent : IconComponent;
@@ -56,18 +59,30 @@ const NavigationBarItem = ({ path, title, IconComponent, SelectedIconComponent }
return (
<ListItemLink selected={!isCollapsed && isActive} sx={{ p: 0, m: 0 }} to={path}>
<CustomTooltip title={t(title)} placement="right">
<CustomTooltip
title={
<>
{t(title)}
<br />
{badgeInfo?.title}
</>
}
placement="right"
>
<ListItem sx={listItemProps}>
<ListItemIcon sx={listItemIconProps}>
<Icon
sx={{
color: isActive ? 'primary.dark' : undefined,
...theme.applyStyles('dark', {
color: isActive ? 'primary.light' : undefined,
}),
}}
/>
<Badge badgeContent={badgeInfo?.count} color="primary">
<Icon
sx={{
color: isActive ? 'primary.dark' : undefined,
...theme.applyStyles('dark', {
color: isActive ? 'primary.light' : undefined,
}),
}}
/>
</Badge>
</ListItemIcon>
<ListItemText
primary={
<TypographyMaxLines
@@ -83,7 +98,14 @@ const NavigationBarItem = ({ path, title, IconComponent, SelectedIconComponent }
{t(title)}
</TypographyMaxLines>
}
sx={{ maxWidth: '100%', m: 0 }}
secondary={
!isCollapsed && (
<Typography variant="caption" color="textSecondary">
{badgeInfo?.title}
</Typography>
)
}
sx={{ maxWidth: '100%', m: 0, display: 'flex', flexDirection: 'column' }}
/>
</ListItem>
</CustomTooltip>

View File

@@ -10,9 +10,10 @@ import BottomNavigation from '@mui/material/BottomNavigation';
import BottomNavigationAction from '@mui/material/BottomNavigationAction';
import { useTranslation } from 'react-i18next';
import Paper from '@mui/material/Paper';
import { useCallback, useLayoutEffect, useRef, useState } from 'react';
import { CSSProperties, useCallback, useLayoutEffect, useRef, useState } from 'react';
import { useLocation, useNavigate } from 'react-router-dom';
import { CSSObject, useTheme } from '@mui/material/styles';
import { useTheme } from '@mui/material/styles';
import Badge from '@mui/material/Badge';
import { useResizeObserver } from '@/modules/core/hooks/useResizeObserver.tsx';
import { useNavBarContext } from '@/modules/navigation-bar/contexts/NavbarContext.tsx';
import { NavbarItem } from '@/modules/navigation-bar/NavigationBar.types.ts';
@@ -52,7 +53,7 @@ export const MobileBottomBar = ({ navBarItems }: { navBarItems: NavbarItem[] })
style={{
...(theme.applyStyles('dark', {
'--Paper-overlay': 'unset',
}) as Omit<CSSObject, 'accentColorsd'>),
}) as CSSProperties),
}}
elevation={3}
>
@@ -64,12 +65,15 @@ export const MobileBottomBar = ({ navBarItems }: { navBarItems: NavbarItem[] })
navigate(newValue);
}}
>
{navBarItems.map(({ path, title, IconComponent, SelectedIconComponent }) => (
{navBarItems.map(({ path, title, IconComponent, SelectedIconComponent, useBadge }) => (
<BottomNavigationAction
key={path}
value={path}
label={t(title)}
icon={selectedNavBarItem === path ? <SelectedIconComponent /> : <IconComponent />}
icon={
<Badge key={path} badgeContent={useBadge?.().count} color="primary">
{selectedNavBarItem === path ? <SelectedIconComponent /> : <IconComponent />}
</Badge>
}
/>
))}
</BottomNavigation>

View File

@@ -68,7 +68,7 @@ export const More = () => {
<ListItemIcon>
<item.IconComponent />
</ListItemIcon>
<ListItemText primary={t(item.title)} />
<ListItemText primary={t(item.title)} secondary={item.useBadge?.().title} />
</ListItemLink>
))}
{index !== list.length - 1 && <Divider />}