import { io } from "socket.io-client"; import React, { useState, useEffect } from "react"; import { Container, Row, Col, ProgressBar, InputGroup, FormControl, Button, ButtonGroup, Toast, } from "react-bootstrap"; import { validateDomain, validateIP } from "./utils"; import { IDLInfo, IMessage } from "./interfaces"; import './App.css'; const socket = io(`http://${localStorage.getItem('server-addr') || 'localhost'}:3022`) export function App() { const [progress, setProgress] = useState(0) const [message, setMessage] = useState('') const [halt, setHalt] = useState(false) const [url, setUrl] = useState('') const [showToast, setShowToast] = useState(false) const [invalidIP, setInvalidIP] = useState(false) const [updatedBin, setUpdatedBin] = useState(false) const [showSettings, setShowSettings] = useState(false) const [darkMode, setDarkMode] = useState(localStorage.getItem('theme') === 'dark') const [extractAudio, setExtractAudio] = useState(localStorage.getItem('-x') === 'true') const [downloadInfo, setDownloadInfo] = useState() useEffect(() => { socket.on('connect', () => { setShowToast(true) socket.emit('fetch-jobs') }) return () => { socket.disconnect() } }, []) useEffect(() => { socket.on('pending-jobs', (jobs: Array) => { //if (jobs.length > 0) { socket.emit('retrieve-jobs') //} }) }, []) useEffect(() => { darkMode ? document.body.classList.add('dark') : document.body.classList.remove('dark') }, [darkMode]) useEffect(() => { socket.on('info', (data: IDLInfo) => { setDownloadInfo(data) }) }, []) useEffect(() => { socket.on('progress', (data: IMessage) => { setMessage(`operation: ${data.status || '...'} \nprogress: ${data.progress || '?'} \nsize: ${data.size || '?'} \nspeed: ${data.dlSpeed || '?'}`) if (data.status === 'Done!' || data.status === 'Aborted') { setHalt(false) setMessage('Done!') setProgress(0) return } if (data.progress) { setProgress(Math.ceil(Number(data.progress.replace('%', '')))) } // if (data.dlSpeed) { // const event = new CustomEvent("dlSpeed", { "detail": detectSpeed(data.dlSpeed) }); // document.dispatchEvent(event); // } }) }, []) useEffect(() => { socket.on('updated', () => { setUpdatedBin(true) setHalt(false) }) }, []) const sendUrl = () => { setHalt(true) socket.emit('send-url', { url: url, params: { xa: extractAudio }, }) } const handleUrlChange = (e: React.ChangeEvent) => { setUrl(e.target.value) } const handleAddrChange = (e: React.ChangeEvent) => { const input = e.target.value; if (validateIP(input)) { setInvalidIP(false) localStorage.setItem('server-addr', input) } else if (validateDomain(input)) { setInvalidIP(false) localStorage.setItem('server-addr', input) } else { setInvalidIP(true) } } const abort = () => { setDownloadInfo({ title: '', thumbnail: '' }) socket.emit('abort') setHalt(false) } const updateBinary = () => { setHalt(true) socket.emit('update-bin') } const toggleTheme = () => { if (darkMode) { localStorage.setItem('theme', 'light') setDarkMode(false) } else { localStorage.setItem('theme', 'dark') setDarkMode(true) } } const toggleExtractAudio = () => { if (extractAudio) { localStorage.setItem('-x', 'false') setExtractAudio(false) } else { localStorage.setItem('-x', 'true') setExtractAudio(true) } } return (

yt-dlp WebUI

{downloadInfo ?

{downloadInfo.title}

: null}
Status
{!message ?
Ready
: null}
{message}

{/* */}
{progress ? : null}
setShowSettings(!showSettings)}>Settings
{showSettings ?
Server address
ws:// :3022 {' '}
toggleExtractAudio()} checked={extractAudio} />
: null }
Once you close this page the download will continue in the background.
setShowToast(false)} bg={'primary'} delay={1500} autohide className="mt-5" > {`Connected to ${localStorage.getItem('server-addr') || 'localhost'}`} setUpdatedBin(false)} bg={'primary'} delay={1500} autohide className="mt-5" > Updated yt-dlp binary!
Made with ❤️ by Marcobaobao
) }