// Copyright (c) 2026 Gordon Bolton. MIT License. export function formatSize(size) { if (!size) return 'N/A'; // If already a formatted string (e.g., "21.5 GB"), return as-is if (typeof size === 'string') { return size; } // If it's a number (bytes), format it const sizes = ['B', 'KB', 'MB', 'GB', 'TB']; const i = Math.floor(Math.log(size) / Math.log(1024)); return Math.round(size / Math.pow(1024, i) * 100) / 100 + ' ' + sizes[i]; } export function formatSpeed(bytesPerSecond) { if (!bytesPerSecond || bytesPerSecond === 0) return '0 B/s'; const units = ['B/s', 'KB/s', 'MB/s', 'GB/s']; let value = bytesPerSecond; let unitIndex = 0; while (value >= 1024 && unitIndex < units.length - 1) { value /= 1024; unitIndex++; } return `${value.toFixed(2)} ${units[unitIndex]}`; } export function formatDate(dateString) { if (!dateString) return 'N/A'; return new Date(dateString).toLocaleString(); } export function formatTimeAgo(timestamp) { if (!timestamp) return 'Never'; const seconds = Math.floor((Date.now() - timestamp) / 1000); if (seconds < 60) return seconds + 's ago'; const minutes = Math.floor(seconds / 60); if (minutes < 60) return minutes + 'm ago'; const hours = Math.floor(minutes / 60); if (hours < 24) return hours + 'h ago'; return Math.floor(hours / 24) + 'd ago'; } export function escapeHtml(str) { const div = document.createElement('div'); div.textContent = str; return div.innerHTML; } // Build an episode-info element for series downloads/history. // Single episode: "S01E05 — Episode Title" // Multiple episodes: "Multiple episodes" with tooltip listing them all. // Returns null if no episode data. export function formatEpisodeInfo(episodes) { if (!episodes || episodes.length === 0) return null; const el = document.createElement('p'); el.className = 'episode-info'; if (episodes.length === 1) { const ep = episodes[0]; const code = 'S' + String(ep.season).padStart(2, '0') + 'E' + String(ep.episode).padStart(2, '0'); el.textContent = ep.title ? code + ' \u2014 ' + ep.title : code; } else { el.textContent = 'Multiple episodes'; el.classList.add('multi-episode'); const lines = episodes.map(ep => { const code = 'S' + String(ep.season).padStart(2, '0') + 'E' + String(ep.episode).padStart(2, '0'); return ep.title ? code + ' \u2014 ' + ep.title : code; }); el.setAttribute('data-tooltip', lines.join('\n')); } return el; }