mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
1import React, {useState} from 'react'
2import {ActivityIndicator, Keyboard, View} from 'react-native'
3import {type ComAtprotoServerDescribeServer} from '@atproto/api'
4import {msg, Trans} from '@lingui/macro'
5import {useLingui} from '@lingui/react'
6import * as EmailValidator from 'email-validator'
7
8import {isNetworkError} from '#/lib/strings/errors'
9import {cleanError} from '#/lib/strings/errors'
10import {logger} from '#/logger'
11import {Agent} from '#/state/session/agent'
12import {atoms as a, useTheme} from '#/alf'
13import {Button, ButtonText} from '#/components/Button'
14import {FormError} from '#/components/forms/FormError'
15import {HostingProvider} from '#/components/forms/HostingProvider'
16import * as TextField from '#/components/forms/TextField'
17import {At_Stroke2_Corner0_Rounded as At} from '#/components/icons/At'
18import {Text} from '#/components/Typography'
19import {FormContainer} from './FormContainer'
20
21type ServiceDescription = ComAtprotoServerDescribeServer.OutputSchema
22
23export const ForgotPasswordForm = ({
24 error,
25 serviceUrl,
26 serviceDescription,
27 setError,
28 setServiceUrl,
29 onPressBack,
30 onEmailSent,
31}: {
32 error: string
33 serviceUrl: string
34 serviceDescription: ServiceDescription | undefined
35 setError: (v: string) => void
36 setServiceUrl: (v: string) => void
37 onPressBack: () => void
38 onEmailSent: () => void
39}) => {
40 const t = useTheme()
41 const [isProcessing, setIsProcessing] = useState<boolean>(false)
42 const [email, setEmail] = useState<string>('')
43 const {_} = useLingui()
44
45 const onPressSelectService = React.useCallback(() => {
46 Keyboard.dismiss()
47 }, [])
48
49 const onPressNext = async () => {
50 if (!EmailValidator.validate(email)) {
51 return setError(_(msg`Your email appears to be invalid.`))
52 }
53
54 setError('')
55 setIsProcessing(true)
56
57 try {
58 const agent = new Agent(null, {service: serviceUrl})
59 await agent.com.atproto.server.requestPasswordReset({email})
60 onEmailSent()
61 } catch (e: any) {
62 const errMsg = e.toString()
63 logger.warn('Failed to request password reset', {error: e})
64 setIsProcessing(false)
65 if (isNetworkError(e)) {
66 setError(
67 _(
68 msg`Unable to contact your service. Please check your Internet connection.`,
69 ),
70 )
71 } else {
72 setError(cleanError(errMsg))
73 }
74 }
75 }
76
77 return (
78 <FormContainer
79 testID="forgotPasswordForm"
80 titleText={<Trans>Reset password</Trans>}>
81 <View>
82 <TextField.LabelText>
83 <Trans>Hosting provider</Trans>
84 </TextField.LabelText>
85 <HostingProvider
86 serviceUrl={serviceUrl}
87 onSelectServiceUrl={setServiceUrl}
88 onOpenDialog={onPressSelectService}
89 />
90 </View>
91 <View>
92 <TextField.LabelText>
93 <Trans>Email address</Trans>
94 </TextField.LabelText>
95 <TextField.Root>
96 <TextField.Icon icon={At} />
97 <TextField.Input
98 testID="forgotPasswordEmail"
99 label={_(msg`Enter your email address`)}
100 autoCapitalize="none"
101 autoFocus
102 autoCorrect={false}
103 autoComplete="email"
104 value={email}
105 onChangeText={setEmail}
106 editable={!isProcessing}
107 accessibilityHint={_(msg`Sets email for password reset`)}
108 />
109 </TextField.Root>
110 </View>
111
112 <Text style={[t.atoms.text_contrast_high, a.leading_snug]}>
113 <Trans>
114 Enter the email you used to create your account. We'll send you a
115 "reset code" so you can set a new password.
116 </Trans>
117 </Text>
118
119 <FormError error={error} />
120
121 <View style={[a.flex_row, a.align_center, a.pt_md]}>
122 <Button
123 label={_(msg`Back`)}
124 variant="solid"
125 color="secondary"
126 size="large"
127 onPress={onPressBack}>
128 <ButtonText>
129 <Trans>Back</Trans>
130 </ButtonText>
131 </Button>
132 <View style={a.flex_1} />
133 {!serviceDescription || isProcessing ? (
134 <ActivityIndicator />
135 ) : (
136 <Button
137 label={_(msg`Next`)}
138 variant="solid"
139 color={'primary'}
140 size="large"
141 onPress={onPressNext}>
142 <ButtonText>
143 <Trans>Next</Trans>
144 </ButtonText>
145 </Button>
146 )}
147 {!serviceDescription || isProcessing ? (
148 <Text style={[t.atoms.text_contrast_high, a.pl_md]}>
149 <Trans>Processing...</Trans>
150 </Text>
151 ) : undefined}
152 </View>
153 <View
154 style={[
155 t.atoms.border_contrast_medium,
156 a.border_t,
157 a.pt_2xl,
158 a.mt_md,
159 a.flex_row,
160 a.justify_center,
161 ]}>
162 <Button
163 testID="skipSendEmailButton"
164 onPress={onEmailSent}
165 label={_(msg`Go to next`)}
166 accessibilityHint={_(msg`Navigates to the next screen`)}
167 size="large"
168 variant="ghost"
169 color="secondary">
170 <ButtonText>
171 <Trans>Already have a code?</Trans>
172 </ButtonText>
173 </Button>
174 </View>
175 </FormContainer>
176 )
177}