import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Spinner } from '@/components/ui/spinner'; import { Text } from '@/components/ui/text'; import { useToast } from '@/components/ui/toast'; import { View } from '@/components/ui/view'; import { AuthScreen } from '@/components/auth/auth-screen'; import { supabase } from '@/lib/supabase'; import { router } from 'expo-router'; import { Lock } from 'lucide-react-native'; import { useEffect, useState } from 'react'; function describePasswordProblem(password: string): string | undefined { if (password.length < 8) return 'At least 8 characters.'; if (!/[a-z]/.test(password)) return 'Include a lowercase letter.'; if (!/[A-Z]/.test(password)) return 'Include an uppercase letter.'; if (!/[0-9]/.test(password)) return 'Include a digit.'; return undefined; } /** * Reached by opening the recovery link, not by navigation. * * By the time this renders, the deep-link handler has already exchanged the * code for a session — so the user is technically signed in, and `updateUser` * needs no old password. The screen still lives under `(auth)` because the * route guards will move on the moment the password is set. */ export default function ResetPasswordScreen() { const [ready, setReady] = useState(false); const [password, setPassword] = useState(''); const [touched, setTouched] = useState(false); const [loading, setLoading] = useState(false); const toast = useToast(); const problem = describePasswordProblem(password); useEffect(() => { // The exchange is in flight when this mounts on a cold start. Wait for a // session rather than showing a form that would fail on submit. const { data: { subscription }, } = supabase.auth.onAuthStateChange((_event, session) => { if (session) setReady(true); }); supabase.auth.getSession().then(({ data }) => { if (data.session) setReady(true); }); return () => subscription.unsubscribe(); }, []); const submit = async () => { setTouched(true); if (problem) return; setLoading(true); const { error } = await supabase.auth.updateUser({ password }); setLoading(false); if (error) { toast.error('Could not update your password', error.message); return; } toast.success('Password updated', 'You are signed in.'); // The session is already valid, so the guards send us into the app. }; if (!ready) { return ( If this does not move, the link may have expired. Request a new one. ); } return ( setTouched(true)} error={touched ? problem : undefined} secureTextEntry autoCapitalize='none' autoComplete='new-password' textContentType='newPassword' autoFocus /> ); }