diff --git a/CHANGELOG.md b/CHANGELOG.md index dbcb278..2fee81c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), ### Fixed +- **Login no longer gets stuck after updates.** If you happened to have Pulse open when a new version was deployed, logging back in could get stuck on a loading screen. The app now automatically refreshes itself to pick up the latest version. - **City and region data is now accurate.** Location data was incorrectly showing the CDN server's location (e.g. Paris, Villeurbanne) instead of the visitor's actual city. Fixed by reading the correct visitor IP header from Bunny CDN. - **"Reset Data" now clears everything.** Previously, resetting a site's data in Settings only removed pageviews and daily stats. Uptime check history, uptime daily stats, and cached dashboard data were left behind. All collected data is now properly cleared when you reset, while your site configuration, goals, funnels, and uptime monitors are kept. diff --git a/app/auth/callback/page.tsx b/app/auth/callback/page.tsx index 2359b75..933fdce 100644 --- a/app/auth/callback/page.tsx +++ b/app/auth/callback/page.tsx @@ -22,7 +22,14 @@ function AuthCallbackContent() { const codeVerifier = localStorage.getItem('oauth_code_verifier') const redirectUri = typeof window !== 'undefined' ? window.location.origin + '/auth/callback' : '' if (!code) return - const result = await exchangeAuthCode(code, codeVerifier, redirectUri) + let result: Awaited> + try { + result = await exchangeAuthCode(code, codeVerifier, redirectUri) + } catch { + // * Stale build — cached JS has old Server Action hashes. Hard reload to fix. + window.location.reload() + return + } if (result.success && result.user) { // * Fetch full profile (including display_name) before navigating so header shows correct name on first paint try { diff --git a/lib/auth/context.tsx b/lib/auth/context.tsx index 95f8b39..d9adb92 100644 --- a/lib/auth/context.tsx +++ b/lib/auth/context.tsx @@ -90,7 +90,7 @@ export function AuthProvider({ children }: { children: React.ReactNode }) { const logout = useCallback(async () => { setIsLoggingOut(true) - await logoutAction() + try { await logoutAction() } catch { /* stale build — continue with client-side cleanup */ } localStorage.removeItem('user') localStorage.removeItem('ciphera_token_refreshed_at') localStorage.removeItem('ciphera_last_activity') @@ -132,7 +132,15 @@ export function AuthProvider({ children }: { children: React.ReactNode }) { useEffect(() => { const init = async () => { // * 1. Check server-side session (cookies) - let session = await getSessionAction() + let session: Awaited> = null + try { + session = await getSessionAction() + } catch { + // * Stale build — browser has cached JS with old Server Action hashes. + // * Force a hard reload to fetch fresh bundles from the server. + window.location.reload() + return + } // * 2. If no access_token but refresh_token may exist, try refresh (fixes 15-min inactivity logout) if (!session && typeof window !== 'undefined') { @@ -142,7 +150,12 @@ export function AuthProvider({ children }: { children: React.ReactNode }) { credentials: 'include', }) if (refreshRes.ok) { - session = await getSessionAction() + try { + session = await getSessionAction() + } catch { + window.location.reload() + return + } } }