Skip to content

Commit f6490a3

Browse files
committed
fix: auth init timeout + clearer login errors
1 parent cfbac62 commit f6490a3

2 files changed

Lines changed: 62 additions & 8 deletions

File tree

‎src/lib/supabase/AuthProvider.tsx‎

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,15 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
2727
let mounted = true;
2828

2929
const init = async () => {
30+
// In some browser/extension states (blocked storage, stalled refresh),
31+
// auth initialization can hang long enough to look like a blank screen.
32+
// Fail open to the login route if it takes too long.
33+
const initTimeoutId = window.setTimeout(() => {
34+
if (!mounted) return;
35+
console.warn('[Auth] init timeout: continuing without session');
36+
setLoading(false);
37+
}, 4000);
38+
3039
try {
3140
const { data, error } = await supabase.auth.getSession();
3241
if (!mounted) return;
@@ -43,6 +52,7 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
4352
if (!mounted) return;
4453
setSession(null);
4554
} finally {
55+
window.clearTimeout(initTimeoutId);
4656
if (mounted) setLoading(false);
4757
}
4858
};
@@ -82,8 +92,8 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
8292
resetSettingsStore();
8393
}
8494

85-
void hydrateSessionStore();
86-
void hydrateSettingsStore();
95+
hydrateSessionStore().catch((err) => console.warn('[Auth] hydrateSessionStore failed:', err));
96+
hydrateSettingsStore().catch((err) => console.warn('[Auth] hydrateSettingsStore failed:', err));
8797
});
8898

8999
return () => {
@@ -97,7 +107,7 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
97107
user: session?.user ?? null,
98108
loading,
99109
signInWithGoogle: async () => {
100-
await supabase.auth.signInWithOAuth({
110+
const { error } = await supabase.auth.signInWithOAuth({
101111
provider: 'google',
102112
options: {
103113
redirectTo: `${window.location.origin}/app`,
@@ -108,6 +118,7 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
108118
},
109119
},
110120
});
121+
if (error) throw error;
111122
},
112123
signOut: async () => {
113124
await supabase.auth.signOut();

‎src/pages/LoginPage.tsx‎

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,51 @@
1-
import { useEffect } from 'react';
1+
import { useEffect, useState } from 'react';
22
import { useLocation, useNavigate } from 'react-router-dom';
33
import { Button } from '@/components/ui/button';
44
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
5-
import { Sparkles } from 'lucide-react';
5+
import { Loader2, Sparkles } from 'lucide-react';
66
import { useAuth } from '@/lib/supabase/AuthProvider';
7+
import { useToast } from '@/hooks/use-toast';
8+
import { SUPABASE_URL } from '@/lib/supabase/client';
79

810
export default function LoginPage() {
911
const { user, signInWithGoogle } = useAuth();
1012
const navigate = useNavigate();
1113
const location = useLocation();
1214
const from = (location.state as { from?: { pathname?: string } } | null)?.from?.pathname || '/app';
15+
const { toast } = useToast();
16+
const [signingIn, setSigningIn] = useState(false);
1317

1418
useEffect(() => {
1519
if (user) navigate(from, { replace: true });
1620
}, [user, navigate, from]);
1721

22+
const handleSignIn = async () => {
23+
setSigningIn(true);
24+
try {
25+
await signInWithGoogle();
26+
} catch (err) {
27+
toast({
28+
title: 'Login Error',
29+
description: err instanceof Error ? err.message : 'Failed to start Google sign-in',
30+
variant: 'destructive',
31+
});
32+
setSigningIn(false);
33+
}
34+
};
35+
36+
const handleResetAuth = () => {
37+
try {
38+
const ref = new URL(SUPABASE_URL).hostname.split('.')[0];
39+
const prefix = `sb-${ref}-`;
40+
for (const key of Object.keys(localStorage)) {
41+
if (key.startsWith(prefix)) localStorage.removeItem(key);
42+
}
43+
} catch (err) {
44+
console.warn('[Auth] Failed to reset local auth state:', err);
45+
}
46+
window.location.reload();
47+
};
48+
1849
return (
1950
<div className="min-h-screen flex items-center justify-center bg-background px-4">
2051
<Card className="w-full max-w-md">
@@ -26,9 +57,21 @@ export default function LoginPage() {
2657
<CardDescription>Google sign-in is required to use the app.</CardDescription>
2758
</CardHeader>
2859
<CardContent>
29-
<Button className="w-full" onClick={() => void signInWithGoogle()}>
30-
Continue with Google
31-
</Button>
60+
<div className="space-y-3">
61+
<Button className="w-full" onClick={() => void handleSignIn()} disabled={signingIn}>
62+
{signingIn ? (
63+
<>
64+
<Loader2 className="h-4 w-4 mr-2 animate-spin" />
65+
Redirecting...
66+
</>
67+
) : (
68+
'Continue with Google'
69+
)}
70+
</Button>
71+
<Button className="w-full" variant="outline" onClick={handleResetAuth} disabled={signingIn}>
72+
Having trouble? Reset login
73+
</Button>
74+
</div>
3275
</CardContent>
3376
</Card>
3477
</div>

0 commit comments

Comments
 (0)