forked from Light-Heart-Labs/DreamServer
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathuseDownloadProgress.js
More file actions
96 lines (85 loc) · 2.95 KB
/
useDownloadProgress.js
File metadata and controls
96 lines (85 loc) · 2.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
import { useState, useEffect, useCallback } from 'react'
/**
* Hook to poll download progress during model downloads.
* Returns progress data when a download is active.
*/
export function useDownloadProgress(pollIntervalMs = 1000) {
const [progress, setProgress] = useState(null)
const [isDownloading, setIsDownloading] = useState(false)
const fetchProgress = useCallback(async () => {
try {
const response = await fetch('/api/models/download-status')
if (!response.ok) return
const data = await response.json()
if (data.status === 'downloading' || data.status === 'verifying') {
const downloaded = data.bytesDownloaded || 0
const total = data.bytesTotal || 0
const percent = total > 0 ? (downloaded / total) * 100 : 0
setIsDownloading(true)
setProgress({
model: data.model,
status: data.status,
percent,
bytesDownloaded: downloaded,
bytesTotal: total,
speedMbps: data.speedBytesPerSec ? data.speedBytesPerSec / (1024 * 1024) : 0,
eta: data.eta,
startedAt: data.startedAt
})
} else if (data.status === 'complete' || data.status === 'idle') {
setIsDownloading(false)
setProgress(null)
} else if (data.status === 'failed' || data.status === 'error' || data.status === 'cancelled') {
setIsDownloading(false)
setProgress({
error: data.error || data.message || (data.status === 'cancelled' ? 'Download cancelled' : 'Download failed'),
model: data.model
})
}
} catch (err) {
// Silently fail - API might not be available
}
}, [])
useEffect(() => {
fetchProgress()
// Poll frequently only while downloading; otherwise check every 10s
const activeInterval = isDownloading ? pollIntervalMs : 10000
const interval = setInterval(fetchProgress, activeInterval)
return () => clearInterval(interval)
}, [fetchProgress, pollIntervalMs, isDownloading])
// Format helpers
const formatBytes = (bytes) => {
if (!bytes) return '0 B'
const gb = bytes / (1024 ** 3)
if (gb >= 1) return `${gb.toFixed(2)} GB`
const mb = bytes / (1024 ** 2)
if (mb >= 1) return `${mb.toFixed(1)} MB`
return `${(bytes / 1024).toFixed(0)} KB`
}
const formatEta = (eta) => {
if (!eta || eta === 'calculating...') return 'calculating...'
if (typeof eta === 'number') {
const mins = Math.floor(eta / 60)
const secs = eta % 60
if (mins > 0) return `${mins}m ${secs}s`
return `${secs}s`
}
return eta
}
const cancelDownload = useCallback(async () => {
try {
await fetch('/api/models/download/cancel', { method: 'POST' })
fetchProgress()
} catch (err) {
console.error('Failed to cancel download:', err)
}
}, [fetchProgress])
return {
isDownloading,
progress,
formatBytes,
formatEta,
refresh: fetchProgress,
cancelDownload
}
}