display yt-dlp version, multiple downloads enabled.
code refactoring preparations for optimistic ui updates for new downloads
This commit is contained in:
@@ -80,7 +80,6 @@ const DownloadDialog: FC<Props> = ({ open, onClose, onDownloadStart }) => {
|
||||
)
|
||||
|
||||
const [url, setUrl] = useState('')
|
||||
const [workingUrl, setWorkingUrl] = useState('')
|
||||
|
||||
const [isPlaylist, setIsPlaylist] = useState(false)
|
||||
|
||||
@@ -103,35 +102,36 @@ const DownloadDialog: FC<Props> = ({ open, onClose, onDownloadStart }) => {
|
||||
/**
|
||||
* Retrive url from input, cli-arguments from checkboxes and emits via WebSocket
|
||||
*/
|
||||
const sendUrl = (immediate?: string) => {
|
||||
const codes = new Array<string>()
|
||||
if (pickedVideoFormat !== '') codes.push(pickedVideoFormat)
|
||||
if (pickedAudioFormat !== '') codes.push(pickedAudioFormat)
|
||||
if (pickedBestFormat !== '') codes.push(pickedBestFormat)
|
||||
const sendUrl = async (immediate?: string) => {
|
||||
for (const line of url.split('\n')) {
|
||||
const codes = new Array<string>()
|
||||
if (pickedVideoFormat !== '') codes.push(pickedVideoFormat)
|
||||
if (pickedAudioFormat !== '') codes.push(pickedAudioFormat)
|
||||
if (pickedBestFormat !== '') codes.push(pickedBestFormat)
|
||||
|
||||
client.download({
|
||||
url: immediate || url || workingUrl,
|
||||
args: `${argsBuilder.toString()} ${toFormatArgs(codes)} ${downloadTemplate}`,
|
||||
pathOverride: downloadPath ?? '',
|
||||
renameTo: settings.fileRenaming ? filenameTemplate : '',
|
||||
playlist: isPlaylist,
|
||||
})
|
||||
await new Promise(r => setTimeout(r, 200))
|
||||
await client.download({
|
||||
url: immediate || line,
|
||||
args: `${argsBuilder.toString()} ${toFormatArgs(codes)} ${downloadTemplate}`,
|
||||
pathOverride: downloadPath ?? '',
|
||||
renameTo: settings.fileRenaming ? filenameTemplate : '',
|
||||
playlist: isPlaylist,
|
||||
})
|
||||
|
||||
setTimeout(() => {
|
||||
resetInput()
|
||||
setDownloadFormats(undefined)
|
||||
onDownloadStart(immediate || line)
|
||||
}, 250)
|
||||
}
|
||||
|
||||
setUrl('')
|
||||
setWorkingUrl('')
|
||||
|
||||
setTimeout(() => {
|
||||
resetInput()
|
||||
setDownloadFormats(undefined)
|
||||
onDownloadStart(immediate || url || workingUrl)
|
||||
}, 250)
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrive url from input and display the formats selection view
|
||||
*/
|
||||
const sendUrlFormatSelection = () => {
|
||||
setWorkingUrl(url)
|
||||
setUrl('')
|
||||
setPickedAudioFormat('')
|
||||
setPickedVideoFormat('')
|
||||
@@ -220,6 +220,7 @@ const DownloadDialog: FC<Props> = ({ open, onClose, onDownloadStart }) => {
|
||||
>
|
||||
<Grid container>
|
||||
<TextField
|
||||
multiline
|
||||
fullWidth
|
||||
ref={urlInputRef}
|
||||
label={i18n.t('urlInput')}
|
||||
|
||||
@@ -6,7 +6,7 @@ import { settingsState } from '../atoms/settings'
|
||||
import { connectedState } from '../atoms/status'
|
||||
import { useI18n } from '../hooks/useI18n'
|
||||
import FreeSpaceIndicator from './FreeSpaceIndicator'
|
||||
import GitHubIcon from '@mui/icons-material/GitHub'
|
||||
import VersionIndicator from './VersionIndicator'
|
||||
|
||||
const Footer: React.FC = () => {
|
||||
const settings = useRecoilValue(settingsState)
|
||||
@@ -30,8 +30,12 @@ const Footer: React.FC = () => {
|
||||
fontSize: 14,
|
||||
display: 'flex', gap: 1, justifyContent: 'space-between'
|
||||
}}>
|
||||
<div>v3.0.6</div>
|
||||
<div style={{ display: 'flex', gap: 1 }}>
|
||||
<div style={{ display: 'flex', gap: 2 }}>
|
||||
<div>RPC v3.0.6</div>
|
||||
<div></div>
|
||||
<VersionIndicator />
|
||||
</div>
|
||||
<div style={{ display: 'flex', gap: 1, 'alignItems': 'center' }}>
|
||||
<div style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Suspense, useState } from 'react'
|
||||
import { useRecoilState } from 'recoil'
|
||||
import { loadingAtom } from '../atoms/ui'
|
||||
import { loadingAtom, optimisticDownloadsState } from '../atoms/ui'
|
||||
import { useToast } from '../hooks/toast'
|
||||
import DownloadDialog from './DownloadDialog'
|
||||
import HomeSpeedDial from './HomeSpeedDial'
|
||||
@@ -8,12 +8,32 @@ import TemplatesEditor from './TemplatesEditor'
|
||||
|
||||
const HomeActions: React.FC = () => {
|
||||
const [, setIsLoading] = useRecoilState(loadingAtom)
|
||||
const [optimistic, setOptimistic] = useRecoilState(optimisticDownloadsState)
|
||||
|
||||
const [openDownload, setOpenDownload] = useState(false)
|
||||
const [openEditor, setOpenEditor] = useState(false)
|
||||
|
||||
const { pushMessage } = useToast()
|
||||
|
||||
// it's stupid because it will be overriden on the next server tick
|
||||
const handleOptimisticUpdate = (url: string) => setOptimistic([
|
||||
...optimistic, {
|
||||
id: url,
|
||||
info: {
|
||||
created_at: new Date().toISOString(),
|
||||
thumbnail: '',
|
||||
title: url,
|
||||
url: url
|
||||
},
|
||||
progress: {
|
||||
eta: Number.MAX_SAFE_INTEGER,
|
||||
percentage: '0%',
|
||||
process_status: 0,
|
||||
speed: 0
|
||||
}
|
||||
}
|
||||
])
|
||||
|
||||
return (
|
||||
<>
|
||||
<HomeSpeedDial
|
||||
@@ -27,7 +47,9 @@ const HomeActions: React.FC = () => {
|
||||
setOpenDownload(false)
|
||||
setIsLoading(true)
|
||||
}}
|
||||
// TODO: handle optimistic UI update
|
||||
onDownloadStart={(url) => {
|
||||
handleOptimisticUpdate(url)
|
||||
pushMessage(`Requested ${url}`, 'info')
|
||||
setOpenDownload(false)
|
||||
setIsLoading(true)
|
||||
|
||||
@@ -52,7 +52,7 @@ const SocketSubscriber: React.FC<Props> = () => {
|
||||
.filter(f => !!f.info.url).sort((a, b) => datetimeCompareFunc(
|
||||
b.info.created_at,
|
||||
a.info.created_at,
|
||||
))
|
||||
)),
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
34
frontend/src/components/VersionIndicator.tsx
Normal file
34
frontend/src/components/VersionIndicator.tsx
Normal file
@@ -0,0 +1,34 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useRecoilValue } from 'recoil'
|
||||
import { serverURL } from '../atoms/settings'
|
||||
import { CircularProgress } from '@mui/material'
|
||||
import { useToast } from '../hooks/toast'
|
||||
|
||||
const VersionIndicator: React.FC = () => {
|
||||
const serverAddr = useRecoilValue(serverURL)
|
||||
|
||||
const [version, setVersion] = useState('')
|
||||
const { pushMessage } = useToast()
|
||||
|
||||
const fetchVersion = async () => {
|
||||
const res = await fetch(`${serverAddr}/api/v1/version`)
|
||||
|
||||
if (!res.ok) {
|
||||
return pushMessage(await res.text(), 'error')
|
||||
}
|
||||
|
||||
setVersion(await res.json())
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
fetchVersion()
|
||||
}, [])
|
||||
|
||||
return (
|
||||
version
|
||||
? <div>yt-dlp v{version}</div>
|
||||
: <CircularProgress size={15} />
|
||||
)
|
||||
}
|
||||
|
||||
export default VersionIndicator
|
||||
Reference in New Issue
Block a user