import { useState, useCallback } from 'react'; type TauriInternals = { invoke: (cmd: string, args?: Record) => Promise }; const tauriInvoke = (): TauriInternals['invoke'] | undefined => (window as unknown as { __TAURI_INTERNALS__?: TauriInternals }).__TAURI_INTERNALS__?.invoke; type UpdateStatus = | { state: 'idle' } | { state: 'checking' } | { state: 'up-to-date' } | { state: 'available'; version: string } | { state: 'installing' } | { state: 'error'; message: string }; export function useTauriUpdater() { const isTauri = !!tauriInvoke(); const [status, setStatus] = useState({ state: 'idle' }); const check = useCallback(async () => { const invoke = tauriInvoke(); if (!invoke) return; setStatus({ state: 'checking' }); try { const result = (await invoke('check_for_update')) as { available: boolean; version?: string }; setStatus( result.available && result.version ? { state: 'available', version: result.version } : { state: 'up-to-date' }, ); } catch (e) { setStatus({ state: 'error', message: String(e) }); } }, []); const install = useCallback(async () => { const invoke = tauriInvoke(); if (!invoke) return; setStatus({ state: 'installing' }); try { await invoke('install_update'); // On a successful install the native side calls app.restart(), so this // resolve is only reached when nothing was installed (no update found) — // don't leave the UI stuck on "installing". setStatus({ state: 'up-to-date' }); } catch (e) { setStatus({ state: 'error', message: String(e) }); } }, []); return { isTauri, status, check, install }; }