Parallelize cloud library listing

This commit is contained in:
ShukeBta
2026-06-16 15:21:19 +08:00
parent 18ae6df115
commit 829b88036a
5 changed files with 272 additions and 21 deletions
+60
View File
@@ -5,6 +5,7 @@ import toast from 'react-hot-toast'
import { ArrowLeft, Play, Film } from 'lucide-react'
import { libraryAPI } from '../api/library'
import { storageAPI, type CloudScanStatus } from '../api/storage_config'
import type { Library, Media } from '../types'
import { MediaCard } from '../components/MediaCard'
import { ExternalPlayerButton } from '../components/ExternalPlayerButton'
@@ -147,6 +148,51 @@ export function LibraryPage() {
useWebSocket(onRealtimeEvent)
useEffect(() => {
if (role !== 'admin' || !id) return
let cancelled = false
let terminal = false
let timer: number | undefined
const restoreCloudScanStatus = async () => {
const r = await storageAPI.cloudScanStatus()
if (cancelled) return
const status = (r.items ?? []).find((item) => item.library_id === id)
if (!status) return
if (status.state === 'running' || status.state === 'queued' || status.state === 'canceling') {
setScanning(true)
setScanProgress(formatCloudScanStatus(status))
return
}
if (status.state === 'finished') {
setScanning(false)
setScanProgress(formatCloudScanStatus(status))
reloadCurrentLibrary()
terminal = true
if (timer) window.clearInterval(timer)
return
}
if (status.state === 'error' && status.error) {
setScanning(false)
setScanProgress(`扫描失败:${status.error}`)
terminal = true
if (timer) window.clearInterval(timer)
}
}
restoreCloudScanStatus()
.catch(() => undefined)
.finally(() => {
if (!cancelled && !terminal) {
timer = window.setInterval(() => {
restoreCloudScanStatus().catch(() => undefined)
}, 5000)
}
})
return () => {
cancelled = true
if (timer) window.clearInterval(timer)
}
}, [id, reloadCurrentLibrary, role])
useEffect(() => {
if (loading) return
if (!isSeries) {
@@ -419,6 +465,20 @@ function formatDuration(seconds: number): string {
return `${hours}小时${minutes % 60}分`
}
function formatCloudScanStatus(status: CloudScanStatus): string {
const stage =
status.state === 'queued' ? '扫描已排队'
: status.state === 'canceling' ? '正在中断扫描'
: status.state === 'finished' ? '扫描完成'
: status.stage === 'importing' ? '正在入库'
: '正在遍历目录'
const speed = Number(status.files_per_second ?? 0)
const speedText = speed > 0 && status.state !== 'finished'
? ` · ${speed.toFixed(speed >= 10 ? 0 : 1)} 个/秒`
: ''
return `${stage}:目录 ${status.dirs ?? 0} · 已发现 ${status.discovered ?? 0} · 已入库 ${status.visited ?? 0} · 新增 ${status.added ?? 0} · 更新 ${status.updated ?? 0}${speedText}`
}
function formatSize(bytes: number): string {
if (!bytes || bytes <= 0) return '—'
const units = ['B', 'KB', 'MB', 'GB', 'TB']