import {useState} from 'react' import {View} from 'react-native' import {Client} from '@atproto/lex-client' import {Trans, useLingui} from '@lingui/react/macro' import {cleanError, isNetworkError} from '#/lib/strings/errors' import {checkAndFormatResetCode} from '#/lib/strings/password' import {logger} from '#/logger' import {atoms as a, web} from '#/alf' import {Admonition} from '#/components/Admonition' import {Button, ButtonIcon, ButtonText} from '#/components/Button' 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 {Loader} from '#/components/Loader' import {Text} from '#/components/Typography' import {useAnalytics} from '#/analytics' import {IS_WEB} from '#/env' import {com} from '#/lexicons' 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 {t: l} = useLingui() const ax = useAnalytics() 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( l`You have entered an invalid code. It should look like XXXXX-XXXXX.`, ) ax.metric('signin:passwordResetFailure', {}) return } // TODO Better password strength check if (!password) { setError(l`Please enter a password.`) return } setError('') setIsProcessing(true) try { const client = new Client({service: serviceUrl}) await client.call(com.atproto.server.resetPassword, { token: formattedCode, password, }) onPasswordSet() ax.metric('signin:passwordResetSuccess', {}) } catch (err) { logger.warn('Failed to set new password', {error: err}) ax.metric('signin:passwordResetFailure', {}) setIsProcessing(false) if (isNetworkError(err)) { setError( l`Unable to contact your service. Please check your Internet connection.`, ) } else { setError(cleanError(err)) } } } const onBlur = () => { const formattedCode = checkAndFormatResetCode(resetCode) if (!formattedCode) { setError( l`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={l`Input code sent to your email for password reset`} /> New password void onPressNext()} editable={!isProcessing} accessibilityHint={l`Input new password`} /> {error && {error}} {IS_WEB && ( <> )} ) }