import { useState, useEffect, useRef } from 'react'
import { getDownloadHistory, getActiveDownloads, getUser, getScrapeJobs } from '../api'
import Spinner from '../components/Spinner'
export default function Downloads() {
const [history, setHistory] = useState([])
const [active, setActive] = useState([])
const [scrapeJobs, setScrapeJobs] = useState([])
const [loading, setLoading] = useState(true)
const [error, setError] = useState(null)
const pollRef = useRef(null)
const [usernames, setUsernames] = useState({})
useEffect(() => {
loadAll()
startPolling()
return () => {
if (pollRef.current) clearInterval(pollRef.current)
}
}, [])
const loadAll = async () => {
setLoading(true)
setError(null)
const [histData, activeData, scrapeData] = await Promise.all([
getDownloadHistory(),
getActiveDownloads(),
getScrapeJobs(),
])
if (histData.error) {
setError(histData.error)
setLoading(false)
return
}
const histList = Array.isArray(histData) ? histData : histData.list || []
setHistory(histList)
setActive(Array.isArray(activeData) ? activeData : [])
setScrapeJobs(Array.isArray(scrapeData) ? scrapeData.filter(j => j.running) : [])
setLoading(false)
resolveUsernames(histList)
}
const startPolling = () => {
pollRef.current = setInterval(async () => {
const [activeData, scrapeData] = await Promise.all([
getActiveDownloads(),
getScrapeJobs(),
])
if (!activeData.error) {
const list = Array.isArray(activeData) ? activeData : []
setActive((prev) => {
if (prev.length > 0 && list.length < prev.length) {
getDownloadHistory().then((h) => {
if (!h.error) setHistory(Array.isArray(h) ? h : h.list || [])
})
}
return list
})
}
if (!scrapeData.error) {
setScrapeJobs(Array.isArray(scrapeData) ? scrapeData.filter(j => j.running) : [])
}
}, 2000)
}
const resolveUsernames = async (items) => {
const ids = [...new Set(items.map((i) => i.userId || i.user_id).filter(Boolean))]
for (const id of ids) {
if (usernames[id]) continue
const data = await getUser(id)
if (data && !data.error && data.username) {
setUsernames((prev) => ({ ...prev, [id]: data.username }))
}
}
}
const formatDate = (dateStr) => {
if (!dateStr) return '--'
const d = new Date(dateStr)
return d.toLocaleDateString('en-US', {
month: 'short',
day: 'numeric',
year: 'numeric',
hour: '2-digit',
minute: '2-digit',
})
}
if (loading) return
{error}
Manage and monitor media downloads
{usernames[uid] ? `@${usernames[uid]}` : `User ${uid}`}
{dl.completed || 0} / {dl.total || '?'} files {dl.errors > 0 && ( ({dl.errors} error{dl.errors !== 1 ? 's' : ''}) )}
{job.folderName}
{job.progress.completed} / {job.progress.total} {job.type === 'forum' ? 'pages' : 'files'} {job.progress.errors > 0 && ( ({job.progress.errors} errors) )}
No download history yet
Start downloading from the Users page