import { useCallback } from 'react'; import { usePlatform } from '../platform'; import { clearDecryptionCache } from '../components/channel/Messages'; /** * useLogout — wipes all client-side auth state and hard-reloads the * app so AuthGuard lands on /login with a clean React tree (no stale * Convex subscriptions, no lingering in-memory keys). Callers don't * need to navigate themselves — the reload does it. * * Storage cleared (mirrors what AuthGuard hydrates on restore): * - localStorage: userId, username, publicKey, userPrefs_ * - sessionStorage: privateKey, signingKey, masterKey, searchDbKey * - platform.session: full encrypted blob (Electron safeStorage / web localStorage) */ export function useLogout(): () => Promise { const { session } = usePlatform(); return useCallback(async () => { // Flush in-memory plaintext before anything else so a failure in a // later step (e.g. platform session clear throws, reload never // fires) still wipes decrypted message content from this tab's // heap. The hard reload below normally covers this already. try { clearDecryptionCache(); } catch (err) { console.warn('Failed to clear decryption cache:', err); } try { await session?.clear?.(); } catch (err) { console.warn('Failed to clear platform session:', err); } try { const userId = localStorage.getItem('userId'); localStorage.removeItem('userId'); localStorage.removeItem('username'); localStorage.removeItem('publicKey'); if (userId) localStorage.removeItem(`userPrefs_${userId}`); sessionStorage.removeItem('privateKey'); sessionStorage.removeItem('signingKey'); sessionStorage.removeItem('masterKey'); sessionStorage.removeItem('searchDbKey'); } catch (err) { console.warn('Failed to clear auth storage:', err); } // Hard reload: dumps the React tree, LiveKit rooms, Convex // client, and any open audio/video contexts. AuthGuard then // mounts fresh with empty storage and redirects to /login. window.location.reload(); }, [session]); }