code refactoring, deps bump
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "yt-dlp-webui",
|
"name": "yt-dlp-webui",
|
||||||
"version": "2.0.7",
|
"version": "2.10.0",
|
||||||
"description": "Frontend compontent of yt-dlp-webui",
|
"description": "Frontend compontent of yt-dlp-webui",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
@@ -9,28 +9,28 @@
|
|||||||
"author": "marcopeocchi",
|
"author": "marcopeocchi",
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@emotion/react": "^11.11.0",
|
"@emotion/react": "^11.11.1",
|
||||||
"@emotion/styled": "^11.11.0",
|
"@emotion/styled": "^11.11.0",
|
||||||
"@mui/icons-material": "^5.11.16",
|
"@mui/icons-material": "^5.11.16",
|
||||||
"@mui/material": "^5.13.2",
|
"@mui/material": "^5.13.5",
|
||||||
"@reduxjs/toolkit": "^1.9.5",
|
"@reduxjs/toolkit": "^1.9.5",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-redux": "^8.0.5",
|
"react-redux": "^8.1.1",
|
||||||
"react-router-dom": "^6.11.2",
|
"react-router-dom": "^6.13.0",
|
||||||
"rxjs": "^7.8.1",
|
"rxjs": "^7.8.1",
|
||||||
"uuid": "^9.0.0"
|
"uuid": "^9.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@modyfi/vite-plugin-yaml": "^1.0.4",
|
"@modyfi/vite-plugin-yaml": "^1.0.4",
|
||||||
"@types/node": "^20.2.4",
|
"@types/node": "^20.3.1",
|
||||||
"@types/react": "^18.2.7",
|
"@types/react": "^18.2.13",
|
||||||
"@types/react-dom": "^18.0.10",
|
"@types/react-dom": "^18.2.6",
|
||||||
"@types/react-router-dom": "^5.3.3",
|
"@types/react-router-dom": "^5.3.3",
|
||||||
"@types/uuid": "^9.0.1",
|
"@types/uuid": "^9.0.2",
|
||||||
"@vitejs/plugin-react": "^4.0.0",
|
"@vitejs/plugin-react": "^4.0.1",
|
||||||
"buffer": "^6.0.3",
|
"buffer": "^6.0.3",
|
||||||
"typescript": "^5.0.4",
|
"typescript": "^5.1.3",
|
||||||
"vite": "^4.3.8"
|
"vite": "^4.3.9"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -34,7 +34,7 @@ import Drawer from './components/Drawer'
|
|||||||
import Logout from './components/Logout'
|
import Logout from './components/Logout'
|
||||||
import ThemeToggler from './components/ThemeToggler'
|
import ThemeToggler from './components/ThemeToggler'
|
||||||
import I18nProvider from './providers/i18nProvider'
|
import I18nProvider from './providers/i18nProvider'
|
||||||
import RPCCLientProvider from './providers/rpcClientProvider'
|
import RPCClientProvider from './providers/rpcClientProvider'
|
||||||
import { formatGiB } from './utils'
|
import { formatGiB } from './utils'
|
||||||
|
|
||||||
export default function Layout() {
|
export default function Layout() {
|
||||||
@@ -62,7 +62,7 @@ export default function Layout() {
|
|||||||
return (
|
return (
|
||||||
<ThemeProvider theme={theme}>
|
<ThemeProvider theme={theme}>
|
||||||
<I18nProvider>
|
<I18nProvider>
|
||||||
<RPCCLientProvider>
|
<RPCClientProvider>
|
||||||
<Box sx={{ display: 'flex' }}>
|
<Box sx={{ display: 'flex' }}>
|
||||||
<CssBaseline />
|
<CssBaseline />
|
||||||
<AppBar position="absolute" open={open}>
|
<AppBar position="absolute" open={open}>
|
||||||
@@ -184,7 +184,7 @@ export default function Layout() {
|
|||||||
<Outlet />
|
<Outlet />
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</RPCCLientProvider>
|
</RPCClientProvider>
|
||||||
</I18nProvider>
|
</I18nProvider>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -49,7 +49,6 @@ export default function DownloadDialog({ open, onClose }: Props) {
|
|||||||
// redux state
|
// redux state
|
||||||
const settings = useSelector((state: RootState) => state.settings)
|
const settings = useSelector((state: RootState) => state.settings)
|
||||||
const status = useSelector((state: RootState) => state.status)
|
const status = useSelector((state: RootState) => state.status)
|
||||||
const dispatch = useDispatch()
|
|
||||||
|
|
||||||
// ephemeral state
|
// ephemeral state
|
||||||
const [downloadFormats, setDownloadFormats] = useState<DLMetadata>()
|
const [downloadFormats, setDownloadFormats] = useState<DLMetadata>()
|
||||||
@@ -67,7 +66,8 @@ export default function DownloadDialog({ open, onClose }: Props) {
|
|||||||
const [workingUrl, setWorkingUrl] = useState('')
|
const [workingUrl, setWorkingUrl] = useState('')
|
||||||
|
|
||||||
// memos
|
// memos
|
||||||
const cliArgs = useMemo(() => new CliArguments().fromString(settings.cliArgs), [settings.cliArgs])
|
const cliArgs = useMemo(() =>
|
||||||
|
new CliArguments().fromString(settings.cliArgs), [settings.cliArgs])
|
||||||
|
|
||||||
// context
|
// context
|
||||||
const { i18n } = useContext(I18nContext)
|
const { i18n } = useContext(I18nContext)
|
||||||
@@ -210,7 +210,7 @@ export default function DownloadDialog({ open, onClose }: Props) {
|
|||||||
</Typography>
|
</Typography>
|
||||||
</Toolbar>
|
</Toolbar>
|
||||||
</AppBar>
|
</AppBar>
|
||||||
<Container sx={{ mt: 4 }}>
|
<Container sx={{ my: 4 }}>
|
||||||
<Grid container spacing={2}>
|
<Grid container spacing={2}>
|
||||||
<Grid item xs={12}>
|
<Grid item xs={12}>
|
||||||
<Paper
|
<Paper
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createContext, useMemo } from 'react'
|
import { createContext, useMemo } from 'react'
|
||||||
import { useSelector } from 'react-redux'
|
import { useSelector } from 'react-redux'
|
||||||
import { RPCClient } from '../lib/rpcClient'
|
import { RPCClient } from '../lib/rpcClient'
|
||||||
import { RootState } from '../stores/store'
|
import type { RootState } from '../stores/store'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
children: React.ReactNode
|
children: React.ReactNode
|
||||||
@@ -15,7 +15,7 @@ export const RPCClientContext = createContext<Context>({
|
|||||||
client: new RPCClient()
|
client: new RPCClient()
|
||||||
})
|
})
|
||||||
|
|
||||||
export default function RPCCLientProvider({ children }: Props) {
|
export default function RPCClientProvider({ children }: Props) {
|
||||||
const settings = useSelector((state: RootState) => state.settings)
|
const settings = useSelector((state: RootState) => state.settings)
|
||||||
|
|
||||||
const client = useMemo(() => new RPCClient(), [
|
const client = useMemo(() => new RPCClient(), [
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import type { RPCResponse } from "./types"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validate an ip v4 via regex
|
* Validate an ip v4 via regex
|
||||||
* @param {string} ipAddr
|
* @param {string} ipAddr
|
||||||
@@ -68,9 +70,9 @@ export function toFormatArgs(codes: string[]): string {
|
|||||||
return codes.reduce((v, a) => ` -f ${v}+${a}`)
|
return codes.reduce((v, a) => ` -f ${v}+${a}`)
|
||||||
}
|
}
|
||||||
if (codes.length === 1) {
|
if (codes.length === 1) {
|
||||||
return ` -f ${codes[0]}`;
|
return ` -f ${codes[0]}`
|
||||||
}
|
}
|
||||||
return '';
|
return ''
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getWebSocketEndpoint() {
|
export function getWebSocketEndpoint() {
|
||||||
@@ -94,3 +96,7 @@ export const roundMiB = (bytes: number) => `${(bytes / 1_000_000).toFixed(2)} Mi
|
|||||||
export const formatSpeedMiB = (val: number) => `${roundMiB(val)}/s`
|
export const formatSpeedMiB = (val: number) => `${roundMiB(val)}/s`
|
||||||
|
|
||||||
export const dateTimeComparatorFunc = (a: string, b: string) => new Date(a).getTime() - new Date(b).getTime()
|
export const dateTimeComparatorFunc = (a: string, b: string) => new Date(a).getTime() - new Date(b).getTime()
|
||||||
|
|
||||||
|
export function isRPCResponse(object: any): object is RPCResponse<any> {
|
||||||
|
return 'result' in object && 'id' in object
|
||||||
|
}
|
||||||
@@ -24,7 +24,7 @@ import { I18nContext } from '../providers/i18nProvider'
|
|||||||
import { RPCClientContext } from '../providers/rpcClientProvider'
|
import { RPCClientContext } from '../providers/rpcClientProvider'
|
||||||
import { RootState } from '../stores/store'
|
import { RootState } from '../stores/store'
|
||||||
import type { RPCResponse, RPCResult } from '../types'
|
import type { RPCResponse, RPCResult } from '../types'
|
||||||
import { dateTimeComparatorFunc } from '../utils'
|
import { dateTimeComparatorFunc, isRPCResponse } from '../utils'
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
// redux state
|
// redux state
|
||||||
@@ -83,20 +83,14 @@ export default function Home() {
|
|||||||
if (!status.connected) { return }
|
if (!status.connected) { return }
|
||||||
|
|
||||||
const sub = socket$.subscribe((event: RPCResponse<RPCResult[]>) => {
|
const sub = socket$.subscribe((event: RPCResponse<RPCResult[]>) => {
|
||||||
switch (typeof event.result) {
|
if (!isRPCResponse(event)) { return }
|
||||||
case 'object':
|
|
||||||
setActiveDownloads(
|
setActiveDownloads((event.result ?? [])
|
||||||
(event.result ?? [])
|
.filter(f => !!f.info.url)
|
||||||
.filter((r) => !!r.info.url)
|
.sort((a, b) => dateTimeComparatorFunc(
|
||||||
.sort((a, b) => dateTimeComparatorFunc(
|
b.info.created_at,
|
||||||
b.info.created_at,
|
a.info.created_at,
|
||||||
a.info.created_at,
|
)))
|
||||||
))
|
|
||||||
)
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
break
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
return () => sub.unsubscribe()
|
return () => sub.unsubscribe()
|
||||||
}, [socket$, status.connected])
|
}, [socket$, status.connected])
|
||||||
@@ -105,7 +99,7 @@ export default function Home() {
|
|||||||
if (activeDownloads && activeDownloads.length >= 0) {
|
if (activeDownloads && activeDownloads.length >= 0) {
|
||||||
setShowBackdrop(false)
|
setShowBackdrop(false)
|
||||||
}
|
}
|
||||||
}, [activeDownloads?.length])
|
}, [activeDownloads])
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abort a specific download if id's provided, other wise abort all running ones.
|
* Abort a specific download if id's provided, other wise abort all running ones.
|
||||||
|
|||||||
Reference in New Issue
Block a user