diff --git a/src/app/hooks/useTauriUpdater.ts b/src/app/hooks/useTauriUpdater.ts index 051a40d6a..0ae050145 100644 --- a/src/app/hooks/useTauriUpdater.ts +++ b/src/app/hooks/useTauriUpdater.ts @@ -1,4 +1,5 @@ -import { useState, useCallback } from 'react'; +import { useCallback } from 'react'; +import { atom, useAtom } from 'jotai'; type TauriInternals = { invoke: (cmd: string, args?: Record) => Promise }; const tauriInvoke = (): TauriInternals['invoke'] | undefined => @@ -12,9 +13,16 @@ type UpdateStatus = | { state: 'installing' } | { state: 'error'; message: string }; +// Module-level so the result of a manual "Check for updates" survives closing +// and reopening Settings (it used to be component state, so the "update +// available" answer was thrown away with the tab and had to be re-checked). +// A transient 'checking'/'installing' state is reset if the tab unmounts +// mid-request by the resolve/reject below, so nothing gets stuck. +const updateStatusAtom = atom({ state: 'idle' }); + export function useTauriUpdater() { const isTauri = !!tauriInvoke(); - const [status, setStatus] = useState({ state: 'idle' }); + const [status, setStatus] = useAtom(updateStatusAtom); const check = useCallback(async () => { const invoke = tauriInvoke(); @@ -30,7 +38,7 @@ export function useTauriUpdater() { } catch (e) { setStatus({ state: 'error', message: String(e) }); } - }, []); + }, [setStatus]); const install = useCallback(async () => { const invoke = tauriInvoke(); @@ -45,7 +53,7 @@ export function useTauriUpdater() { } catch (e) { setStatus({ state: 'error', message: String(e) }); } - }, []); + }, [setStatus]); return { isTauri, status, check, install }; }