/** * Update Settings Component * Displays update status and allows manual update checking/installation */ import { useEffect, useCallback } from 'react'; import { Download, RefreshCw, Loader2, Rocket, XCircle } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { Progress } from '@/components/ui/progress'; import { useUpdateStore } from '@/stores/update'; import { useTranslation } from 'react-i18next'; function formatBytes(bytes: number): string { if (bytes === 0) return '0 B'; const k = 1024; const sizes = ['B', 'KB', 'MB', 'GB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; } export function UpdateSettings() { const { t } = useTranslation('settings'); const { status, currentVersion, updateInfo, progress, error, isInitialized, autoInstallCountdown, init, checkForUpdates, downloadUpdate, installUpdate, cancelAutoInstall, clearError, } = useUpdateStore(); // Initialize on mount useEffect(() => { init(); }, [init]); const handleCheckForUpdates = useCallback(async () => { clearError(); await checkForUpdates(); }, [checkForUpdates, clearError]); const renderStatusIcon = () => { switch (status) { case 'checking': case 'downloading': return ; case 'available': return ; case 'downloaded': return ; case 'error': return ; default: return ; } }; const renderStatusText = () => { if (status === 'downloaded' && autoInstallCountdown != null && autoInstallCountdown >= 0) { return t('updates.status.autoInstalling', { seconds: autoInstallCountdown }); } switch (status) { case 'checking': return t('updates.status.checking'); case 'downloading': return t('updates.status.downloading'); case 'available': return t('updates.status.available', { version: updateInfo?.version }); case 'downloaded': return t('updates.status.downloaded', { version: updateInfo?.version }); case 'error': return error || t('updates.status.failed'); case 'not-available': return t('updates.status.latest'); default: return t('updates.status.check'); } }; const renderAction = () => { switch (status) { case 'checking': return ( ); case 'downloading': return ( ); case 'available': return ( ); case 'downloaded': if (autoInstallCountdown != null && autoInstallCountdown >= 0) { return ( ); } return ( ); case 'error': return ( ); default: return ( ); } }; if (!isInitialized) { return (
Loading...
); } return (
{/* Current Version */}

{t('updates.currentVersion')}

v{currentVersion}

{renderStatusIcon()}
{/* Status */}

{renderStatusText()}

{renderAction()}
{/* Download Progress */} {status === 'downloading' && progress && (
{formatBytes(progress.transferred)} / {formatBytes(progress.total)} {formatBytes(progress.bytesPerSecond)}/s

{Math.round(progress.percent)}% complete

)} {/* Update Info */} {updateInfo && (status === 'available' || status === 'downloaded') && (

Version {updateInfo.version}

{updateInfo.releaseDate && (

{new Date(updateInfo.releaseDate).toLocaleDateString()}

)}
{updateInfo.releaseNotes && (

{t('updates.whatsNew')}

{updateInfo.releaseNotes}

)}
)} {/* Error Details */} {status === 'error' && error && (

{t('updates.errorDetails')}

{error}

)} {/* Help Text */}

{t('updates.help')}

); } export default UpdateSettings;