diff --git a/frontend/src/Layout.tsx b/frontend/src/Layout.tsx
index 196c449..042c83e 100644
--- a/frontend/src/Layout.tsx
+++ b/frontend/src/Layout.tsx
@@ -1,7 +1,7 @@
import { ThemeProvider } from '@emotion/react'
+import ArchiveIcon from '@mui/icons-material/Archive'
import ChevronLeft from '@mui/icons-material/ChevronLeft'
import Dashboard from '@mui/icons-material/Dashboard'
-import DownloadIcon from '@mui/icons-material/Download'
import Menu from '@mui/icons-material/Menu'
import SettingsIcon from '@mui/icons-material/Settings'
import TerminalIcon from '@mui/icons-material/Terminal'
@@ -116,7 +116,7 @@ export default function Layout() {
}>
-
+
diff --git a/frontend/src/atoms/ui.ts b/frontend/src/atoms/ui.ts
index 3ba1c19..2eac349 100644
--- a/frontend/src/atoms/ui.ts
+++ b/frontend/src/atoms/ui.ts
@@ -9,4 +9,9 @@ export const loadingAtom = atom({
export const optimisticDownloadsState = atom({
key: 'optimisticDownloadsState',
default: []
+})
+
+export const totalDownloadSpeedState = atom({
+ key: 'totalDownloadSpeedState',
+ default: 0
})
\ No newline at end of file
diff --git a/frontend/src/components/DownloadCard.tsx b/frontend/src/components/DownloadCard.tsx
index 9f47a90..b4f8298 100644
--- a/frontend/src/components/DownloadCard.tsx
+++ b/frontend/src/components/DownloadCard.tsx
@@ -61,14 +61,22 @@ const DownloadCard: React.FC = ({ download, onStop, onCopy }) => {
/> :
}
+ {download.progress.percentage ?
+ :
+ null
+ }
{download.info.title !== '' ?
- {ellipsis(download.info.title, 54)}
+ {ellipsis(download.info.title, 100)}
:
}
-
+
= ({ download, onStop, onCopy }) => {
- {download.progress.percentage ?
- :
- null
- }
diff --git a/frontend/src/components/Downloads.tsx b/frontend/src/components/Downloads.tsx
index 8c477ed..1b114bd 100644
--- a/frontend/src/components/Downloads.tsx
+++ b/frontend/src/components/Downloads.tsx
@@ -1,8 +1,8 @@
import { useEffect } from 'react'
import { useRecoilState, useRecoilValue } from 'recoil'
-import { loadingDownloadsState } from '../atoms/downloads'
+import { activeDownloadsState, loadingDownloadsState } from '../atoms/downloads'
import { listViewState } from '../atoms/settings'
-import { loadingAtom } from '../atoms/ui'
+import { loadingAtom, totalDownloadSpeedState } from '../atoms/ui'
import DownloadsCardView from './DownloadsCardView'
import DownloadsTableView from './DownloadsTableView'
@@ -12,10 +12,18 @@ const Downloads: React.FC = () => {
const [isLoading, setIsLoading] = useRecoilState(loadingAtom)
+ const downloads = useRecoilValue(activeDownloadsState)
+ const [, setTotalDownloadSpeed] = useRecoilState(totalDownloadSpeedState)
+
+ useEffect(() => {
+ setTotalDownloadSpeed(
+ downloads.map(d => d.progress.speed).reduce((curr, next) => curr + next)
+ )
+ }, [downloads])
+
useEffect(() => {
if (loadingDownloads) {
- setIsLoading(true)
- return
+ return setIsLoading(true)
}
setIsLoading(false)
}, [loadingDownloads, isLoading])
diff --git a/frontend/src/components/Footer.tsx b/frontend/src/components/Footer.tsx
index da35cc4..95425fb 100644
--- a/frontend/src/components/Footer.tsx
+++ b/frontend/src/components/Footer.tsx
@@ -7,10 +7,14 @@ import { connectedState } from '../atoms/status'
import { useI18n } from '../hooks/useI18n'
import FreeSpaceIndicator from './FreeSpaceIndicator'
import VersionIndicator from './VersionIndicator'
+import DownloadIcon from '@mui/icons-material/Download'
+import { totalDownloadSpeedState } from '../atoms/ui'
+import { formatSpeedMiB } from '../utils'
const Footer: React.FC = () => {
const settings = useRecoilValue(settingsState)
const isConnected = useRecoilValue(connectedState)
+ const totalDownloadSpeed = useRecoilValue(totalDownloadSpeedState)
const mode = settings.theme
const { i18n } = useI18n()
@@ -42,6 +46,11 @@ const Footer: React.FC = () => {
marginRight: 'px',
gap: 3,
}}>
+
+
+ {formatSpeedMiB(totalDownloadSpeed)}
+
+
{isConnected ? settings.serverAddr : i18n.t('notConnectedText')}
diff --git a/frontend/src/views/Settings.tsx b/frontend/src/views/Settings.tsx
index 8e9a69a..d74b086 100644
--- a/frontend/src/views/Settings.tsx
+++ b/frontend/src/views/Settings.tsx
@@ -130,7 +130,7 @@ export default function Settings() {
* Updates yt-dlp binary via RPC
*/
const updateBinary = () => {
- client.updateExecutable().then(() => pushMessage(i18n.t('toastUpdated')))
+ client.updateExecutable().then(() => pushMessage(i18n.t('toastUpdated'), 'success'))
}
return (
@@ -204,7 +204,7 @@ export default function Settings() {
label={i18n.t('languageSelect')}
onChange={handleLanguageChange}
>
- {languages.map(l => (
+ {languages.toSorted((a, b) => a.localeCompare(b)).map(l => (