| 9 | } |
| 10 | |
| 11 | export function DownloadQueue({ downloads, onPause, onResume, onCancel }: DownloadQueueProps) { |
| 12 | const downloadArray = Array.from(downloads.values()); |
| 13 | |
| 14 | if (downloadArray.length === 0) { |
| 15 | return null; |
| 16 | } |
| 17 | |
| 18 | return ( |
| 19 | <div className="bg-dark-surface border border-dark-border rounded-lg p-4 mb-4"> |
| 20 | <div className="flex items-center justify-between mb-3"> |
| 21 | <h3 className="text-dark-text font-semibold flex items-center gap-2"> |
| 22 | <svg className="w-5 h-5 text-dark-accent" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"> |
| 23 | <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" /> |
| 24 | </svg> |
| 25 | Active Downloads |
| 26 | </h3> |
| 27 | <span className="text-sm text-dark-text-secondary"> |
| 28 | {downloadArray.length} {downloadArray.length === 1 ? 'download' : 'downloads'} |
| 29 | </span> |
| 30 | </div> |
| 31 | |
| 32 | <div className="space-y-3"> |
| 33 | {downloadArray.map((download) => ( |
| 34 | <DownloadQueueItem |
| 35 | key={download.model_name} |
| 36 | download={download} |
| 37 | onPause={() => onPause(download.model_name)} |
| 38 | onResume={() => onResume(download.model_name)} |
| 39 | onCancel={() => onCancel(download.model_name)} |
| 40 | /> |
| 41 | ))} |
| 42 | </div> |
| 43 | </div> |
| 44 | ); |
| 45 | } |
| 46 | |
| 47 | interface DownloadQueueItemProps { |
| 48 | download: HfDownloadProgress; |