import { useEffect, useState } from 'react'; import { View, Text, Pressable, ActivityIndicator } from 'react-native'; import { useRouter, useLocalSearchParams } from 'expo-router'; import { SafeAreaView } from 'react-native-safe-area-context'; import { useTranslation } from 'react-i18next'; import { supabase } from '../../lib/supabase'; import { useAuthStore } from '../../stores/auth'; /** * Deep-link landing screen for email-confirmation OAuth callbacks. * Invoked when the system opens rebreak://auth/confirm?access_token=...&refresh_token=... * * Strategy: extract tokens from URL params (Expo Router surfaces them), * call setSession, then route to app. If params are missing, poll getSession() * (covers the case where supabase-js processed the hash before we got here). */ export default function ConfirmScreen() { const router = useRouter(); const { t } = useTranslation(); const params = useLocalSearchParams<{ access_token?: string; refresh_token?: string; error?: string; error_description?: string; }>(); const [statusMsg, setStatusMsg] = useState(t('auth.confirming')); const [errorMsg, setErrorMsg] = useState(null); useEffect(() => { handleConfirm(); }, []); async function handleConfirm() { if (params.error) { setErrorMsg(params.error_description ?? params.error ?? t('auth.confirmFailed')); return; } if (params.access_token && params.refresh_token) { const { data, error } = await supabase.auth.setSession({ access_token: params.access_token, refresh_token: params.refresh_token, }); if (error) { setErrorMsg(error.message); return; } useAuthStore.setState({ session: data.session, user: data.session?.user ?? null }); setStatusMsg(t('auth.confirmSuccess')); router.replace('/(app)'); return; } // Fallback: poll up to 20s for a session (supabase-js may have processed hash already) const maxWait = 20_000; const interval = 500; const start = Date.now(); while (Date.now() - start < maxWait) { const { data } = await supabase.auth.getSession(); if (data.session) { useAuthStore.setState({ session: data.session, user: data.session.user }); setStatusMsg(t('auth.confirmSuccess')); router.replace('/(app)'); return; } await new Promise((r) => setTimeout(r, interval)); } setErrorMsg(t('auth.confirmTimeout')); } return ( {!errorMsg ? ( <> {statusMsg} ) : ( <> {errorMsg} router.replace('/signin')} className="bg-neutral-100 border border-neutral-200 px-6 py-3 rounded-xl" > {t('auth.backToLoginPlain')} )} ); }