diff --git a/public/appicon/icon-144.png b/public/appicon/icon-144.png new file mode 100644 index 0000000..187c044 Binary files /dev/null and b/public/appicon/icon-144.png differ diff --git a/public/appicon/icon-36.png b/public/appicon/icon-36.png new file mode 100644 index 0000000..bbd8914 Binary files /dev/null and b/public/appicon/icon-36.png differ diff --git a/public/appicon/icon-48.png b/public/appicon/icon-48.png new file mode 100644 index 0000000..6db830c Binary files /dev/null and b/public/appicon/icon-48.png differ diff --git a/public/appicon/icon-72.png b/public/appicon/icon-72.png new file mode 100644 index 0000000..2367d35 Binary files /dev/null and b/public/appicon/icon-72.png differ diff --git a/public/appicon/icon-96.png b/public/appicon/icon-96.png new file mode 100644 index 0000000..5d6cf2f Binary files /dev/null and b/public/appicon/icon-96.png differ diff --git a/public/appicon/icon.png b/public/appicon/icon.png new file mode 100644 index 0000000..d207f2a Binary files /dev/null and b/public/appicon/icon.png differ diff --git a/public/favicon-16.png b/public/favicon-16.png new file mode 100644 index 0000000..4d1b150 Binary files /dev/null and b/public/favicon-16.png differ diff --git a/public/favicon.ico b/public/favicon.ico index b5336a4..c7be833 100644 Binary files a/public/favicon.ico and b/public/favicon.ico differ diff --git a/public/icons/auth/apple.svg b/public/icons/auth/apple.svg deleted file mode 100644 index 381f84a..0000000 --- a/public/icons/auth/apple.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - \ No newline at end of file diff --git a/public/icons/auth/microsoft.svg b/public/icons/auth/microsoft.svg deleted file mode 100644 index 89ff5b9..0000000 --- a/public/icons/auth/microsoft.svg +++ /dev/null @@ -1,2 +0,0 @@ - - \ No newline at end of file diff --git a/public/icons/gitea.svg b/public/icons/gitea.svg new file mode 100644 index 0000000..d9eb11a --- /dev/null +++ b/public/icons/gitea.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/app/(auth)/auth/callback/route.ts b/src/app/(auth)/auth/callback/route.ts new file mode 100644 index 0000000..d0912ed --- /dev/null +++ b/src/app/(auth)/auth/callback/route.ts @@ -0,0 +1,43 @@ +'use server'; +import 'server-only'; +import { SupabaseServer } from '@/utils/supabase'; +import { type EmailOtpType } from '@supabase/supabase-js'; +import { type NextRequest } from 'next/server'; +import { redirect } from 'next/navigation'; + +export const GET = async (request: NextRequest) => { + const { searchParams, origin } = new URL(request.url); + const code = searchParams.get('code'); + const token_hash = searchParams.get('token'); + const type = searchParams.get('type') as EmailOtpType | null; + const redirectTo = searchParams.get('redirect_to') ?? '/'; + const client = await SupabaseServer(); + + if (code) { + const { error } = await client.auth.exchangeCodeForSession(code); + if (error) { + console.error('OAuth error:', error); + return redirect(`/sign-in?error=${encodeURIComponent(error.message)}`); + } + return redirect(redirectTo); + } + + if (token_hash && type) { + const { error } = await client.auth.verifyOtp({ + type, + token_hash, + }); + if (!error) { + if (type === 'signup' || type === 'magiclink' || type === 'email') + return redirect('/'); + if (type === 'recovery' || type === 'email_change') + return redirect('/profile'); + if (type === 'invite') return redirect('/sign-up'); + } + return redirect( + `/?error=${encodeURIComponent(error?.message ?? 'Unknown error')}`, + ); + } + + return redirect('/'); +}; diff --git a/src/app/(auth)/auth/success/page.tsx b/src/app/(auth)/auth/success/page.tsx new file mode 100644 index 0000000..c98dc2d --- /dev/null +++ b/src/app/(auth)/auth/success/page.tsx @@ -0,0 +1,39 @@ +'use client'; + +import { useAuth } from '@/lib/hooks/context'; +import { useRouter } from 'next/navigation'; +import { useEffect } from 'react'; +import { Loader2 } from 'lucide-react'; + +const AuthSuccessPage = () => { + const { refreshUser } = useAuth(); + const router = useRouter(); + + useEffect(() => { + const handleAuthSuccess = async () => { + // Refresh the auth context to pick up the new session + await refreshUser(); + + // Small delay to ensure state is updated + setTimeout(() => { + router.push('/'); + }, 100); + }; + + handleAuthSuccess().catch((error) => { + console.error(`Error: ${error instanceof Error ? error.message : error}`); + }); + }, [refreshUser, router]); + + // Show loading while processing + return ( +
Completing sign in...
+