import {useState} from 'react' import {ActivityIndicator, View} from 'react-native' import {msg, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' import {logEvent} from '#/lib/statsig/statsig' import {isNetworkError} from '#/lib/strings/errors' import {cleanError} from '#/lib/strings/errors' import {checkAndFormatResetCode} from '#/lib/strings/password' import {logger} from '#/logger' import {Agent} from '#/state/session/agent' import {atoms as a, useTheme} from '#/alf' import {Button, ButtonText} from '#/components/Button' import {FormError} from '#/components/forms/FormError' import * as TextField from '#/components/forms/TextField' import {Lock_Stroke2_Corner0_Rounded as Lock} from '#/components/icons/Lock' import {Ticket_Stroke2_Corner0_Rounded as Ticket} from '#/components/icons/Ticket' import {Text} from '#/components/Typography' import {FormContainer} from './FormContainer' export const SetNewPasswordForm = ({ error, serviceUrl, setError, onPressBack, onPasswordSet, }: { error: string serviceUrl: string setError: (v: string) => void onPressBack: () => void onPasswordSet: () => void }) => { const {_} = useLingui() const t = useTheme() const [isProcessing, setIsProcessing] = useState(false) const [resetCode, setResetCode] = useState('') const [password, setPassword] = useState('') const onPressNext = async () => { // Check that the code is correct. We do this again just incase the user enters the code after their pw and we // don't get to call onBlur first const formattedCode = checkAndFormatResetCode(resetCode) if (!formattedCode) { setError( _( msg`You have entered an invalid code. It should look like XXXXX-XXXXX.`, ), ) logEvent('signin:passwordResetFailure', {}) return } // TODO Better password strength check if (!password) { setError(_(msg`Please enter a password.`)) return } setError('') setIsProcessing(true) try { const agent = new Agent(null, {service: serviceUrl}) await agent.com.atproto.server.resetPassword({ token: formattedCode, password, }) onPasswordSet() logEvent('signin:passwordResetSuccess', {}) } catch (e: any) { const errMsg = e.toString() logger.warn('Failed to set new password', {error: e}) logEvent('signin:passwordResetFailure', {}) setIsProcessing(false) if (isNetworkError(e)) { setError( _( msg`Unable to contact your service. Please check your Internet connection.`, ), ) } else { setError(cleanError(errMsg)) } } } const onBlur = () => { const formattedCode = checkAndFormatResetCode(resetCode) if (!formattedCode) { setError( _( msg`You have entered an invalid code. It should look like XXXXX-XXXXX.`, ), ) return } setResetCode(formattedCode) } return ( Set new password}> You will receive an email with a "reset code." Enter that code here, then enter your new password. Reset code setError('')} onBlur={onBlur} editable={!isProcessing} accessibilityHint={_( msg`Input code sent to your email for password reset`, )} /> New password {isProcessing ? ( ) : ( )} {isProcessing ? ( Updating... ) : undefined} ) }