diff --git a/public/locales/en.json b/public/locales/en.json index 53644e68..a09fdd00 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -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", diff --git a/src/modules/navigation-bar/NavigationBar.constants.ts b/src/modules/navigation-bar/NavigationBar.constants.ts index 46c3ff76..66b49b05 100644 --- a/src/modules/navigation-bar/NavigationBar.constants.ts +++ b/src/modules/navigation-bar/NavigationBar.constants.ts @@ -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 = Omit & { 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, diff --git a/src/modules/navigation-bar/NavigationBar.types.ts b/src/modules/navigation-bar/NavigationBar.types.ts index 1323b6ab..15ac1a16 100644 --- a/src/modules/navigation-bar/NavigationBar.types.ts +++ b/src/modules/navigation-bar/NavigationBar.types.ts @@ -30,6 +30,7 @@ export interface NavbarItem { IconComponent: OverridableComponent>; show: 'mobile' | 'desktop' | 'both'; moreGroup: NavBarItemMoreGroup; + useBadge?: () => { count: number; title: string }; } export type NavbarContextType = { diff --git a/src/modules/navigation-bar/components/DesktopSideBar.tsx b/src/modules/navigation-bar/components/DesktopSideBar.tsx index c0cc382f..10334d62 100644 --- a/src/modules/navigation-bar/components/DesktopSideBar.tsx +++ b/src/modules/navigation-bar/components/DesktopSideBar.tsx @@ -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 ( - + + {t(title)} +
+ {badgeInfo?.title} + + } + placement="right" + > - + + + + } - sx={{ maxWidth: '100%', m: 0 }} + secondary={ + !isCollapsed && ( + + {badgeInfo?.title} + + ) + } + sx={{ maxWidth: '100%', m: 0, display: 'flex', flexDirection: 'column' }} />
diff --git a/src/modules/navigation-bar/components/MobileBottomBar.tsx b/src/modules/navigation-bar/components/MobileBottomBar.tsx index 24b96972..db73fa44 100644 --- a/src/modules/navigation-bar/components/MobileBottomBar.tsx +++ b/src/modules/navigation-bar/components/MobileBottomBar.tsx @@ -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), + }) 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 }) => ( : } + icon={ + + {selectedNavBarItem === path ? : } + + } /> ))} diff --git a/src/modules/settings/screens/More.tsx b/src/modules/settings/screens/More.tsx index 7195ae32..c0c03f47 100644 --- a/src/modules/settings/screens/More.tsx +++ b/src/modules/settings/screens/More.tsx @@ -68,7 +68,7 @@ export const More = () => { - +
))} {index !== list.length - 1 && }