const units = ["B", "KB", "MB", "GB", "TB"]; export const statusLabels = { queued: "Queued", downloading: "Downloading", paused: "Paused", extracting: "Extracting", ready: "Ready", moving: "Moving", completed: "Completed", failed: "Failed", cancelled: "Cancelled", }; export function formatBytes(bytes) { let value = Math.max(0, bytes || 0); let unitIndex = 0; while (value >= 1024 && unitIndex < units.length - 1) { value /= 1024; unitIndex += 1; } return `${value.toFixed(unitIndex === 0 ? 0 : 1)} ${units[unitIndex]}`; } function roundTo(value, step) { return Math.max(step, Math.round(value / step) * step); } export function formatRemaining(seconds) { if (!Number.isFinite(seconds) || seconds <= 0) return "almost done"; if (seconds < 60) return `${roundTo(seconds, 5)}s`; if (seconds < 600) { const rounded = roundTo(seconds, 15); const minutes = Math.floor(rounded / 60); const remainingSeconds = rounded % 60; return remainingSeconds === 0 ? `${minutes}m` : `${minutes}m ${remainingSeconds}s`; } if (seconds < 3600) return `${roundTo(seconds / 60, 1)}m`; const totalMinutes = roundTo(seconds / 60, 5); const hours = Math.floor(totalMinutes / 60); const minutes = totalMinutes % 60; return minutes === 0 ? `${hours}h` : `${hours}h ${minutes}m`; } export function formatDate(value) { const date = new Date(value); return Number.isNaN(date.getTime()) ? "" : date.toLocaleString(); } export function percentOf(done, total) { if (!total || total <= 0) return null; return Math.min(100, (done / total) * 100); }