import { useState, useEffect } from 'react'; import { Button } from '../../ui/button'; import { Loader2, Download, CheckCircle, AlertCircle } from 'lucide-react'; type UpdateStatus = | 'idle' | 'checking' | 'downloading' | 'installing' | 'success' | 'error' | 'ready'; interface UpdateInfo { currentVersion: string; latestVersion?: string; isUpdateAvailable?: boolean; error?: string; } interface UpdateEventData { version?: string; percent?: number; } export default function UpdateSection() { const [updateStatus, setUpdateStatus] = useState('idle'); const [updateInfo, setUpdateInfo] = useState({ currentVersion: '', }); const [progress, setProgress] = useState(0); useEffect(() => { // Get current version on mount const currentVersion = window.electron.getVersion(); setUpdateInfo((prev) => ({ ...prev, currentVersion })); // Check if there's already an update state from the auto-check window.electron.getUpdateState().then((state) => { if (state) { console.log('Found existing update state:', state); setUpdateInfo((prev) => ({ ...prev, isUpdateAvailable: state.updateAvailable, latestVersion: state.latestVersion, })); } }); // Listen for updater events window.electron.onUpdaterEvent((event) => { console.log('Updater event:', event); switch (event.event) { case 'checking-for-update': setUpdateStatus('checking'); break; case 'update-available': setUpdateStatus('idle'); setUpdateInfo((prev) => ({ ...prev, latestVersion: (event.data as UpdateEventData)?.version, isUpdateAvailable: true, })); break; case 'update-not-available': setUpdateStatus('idle'); setUpdateInfo((prev) => ({ ...prev, isUpdateAvailable: false, })); break; case 'download-progress': setUpdateStatus('downloading'); setProgress((event.data as UpdateEventData)?.percent || 0); break; case 'update-downloaded': setUpdateStatus('ready'); setProgress(100); break; case 'error': setUpdateStatus('error'); setUpdateInfo((prev) => ({ ...prev, error: String(event.data || 'An error occurred'), })); setTimeout(() => setUpdateStatus('idle'), 5000); break; } }); }, []); const checkForUpdates = async () => { setUpdateStatus('checking'); setProgress(0); try { const result = await window.electron.checkForUpdates(); if (result.error) { throw new Error(result.error); } // If we successfully checked and no update is available, show success if (!result.error && updateInfo.isUpdateAvailable === false) { setUpdateStatus('success'); setTimeout(() => setUpdateStatus('idle'), 3000); } // The actual status will be handled by the updater events } catch (error) { console.error('Error checking for updates:', error); setUpdateInfo((prev) => ({ ...prev, error: error instanceof Error ? error.message : 'Failed to check for updates', })); setUpdateStatus('error'); setTimeout(() => setUpdateStatus('idle'), 5000); } }; const downloadAndInstallUpdate = async () => { setUpdateStatus('downloading'); setProgress(0); try { const result = await window.electron.downloadUpdate(); if (!result.success) { throw new Error(result.error || 'Failed to download update'); } // The download progress and completion will be handled by updater events } catch (error) { console.error('Error downloading update:', error); setUpdateInfo((prev) => ({ ...prev, error: error instanceof Error ? error.message : 'Failed to download update', })); setUpdateStatus('error'); setTimeout(() => setUpdateStatus('idle'), 5000); } }; const installUpdate = () => { window.electron.installUpdate(); }; const getStatusMessage = () => { switch (updateStatus) { case 'checking': return 'Checking for updates...'; case 'downloading': return `Downloading update... ${Math.round(progress)}%`; case 'ready': return 'Update downloaded and ready to install!'; case 'success': return updateInfo.isUpdateAvailable === false ? 'You are running the latest version!' : 'Update available!'; case 'error': return updateInfo.error || 'An error occurred'; default: if (updateInfo.isUpdateAvailable) { return `Version ${updateInfo.latestVersion} is available`; } return ''; } }; const getStatusIcon = () => { switch (updateStatus) { case 'checking': case 'downloading': return ; case 'success': return ; case 'error': return ; case 'ready': return ; default: return updateInfo.isUpdateAvailable ? : null; } }; return (

Updates

Current version: {updateInfo.currentVersion || 'Loading...'} {updateInfo.latestVersion && updateInfo.isUpdateAvailable && ( → {updateInfo.latestVersion} available )} {updateInfo.currentVersion && updateInfo.isUpdateAvailable === false && ' (up to date)'}

{updateInfo.isUpdateAvailable && updateStatus === 'idle' && ( )} {updateStatus === 'ready' && ( )}
{getStatusMessage() && (
{getStatusIcon()} {getStatusMessage()}
)} {updateStatus === 'downloading' && (
)} {/* Update information */} {updateInfo.isUpdateAvailable && (

Update will be downloaded to your Downloads folder.

After download, extract Goose-{updateInfo.latestVersion}.zip and move the Goose app to /Applications to complete the update.

)}
); }