mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
at ruby-v 297 lines 9.2 kB view raw
1import React from 'react' 2import {View} from 'react-native' 3import {msg, Trans} from '@lingui/macro' 4import {useLingui} from '@lingui/react' 5 6import {cleanError} from '#/lib/strings/errors' 7import {logger} from '#/logger' 8import {useModalControls} from '#/state/modals' 9import {useAgent, useSession} from '#/state/session' 10import {ErrorMessage} from '#/view/com/util/error/ErrorMessage' 11import {atoms as a, useBreakpoints} from '#/alf' 12import {Button, ButtonText} from '#/components/Button' 13import * as Dialog from '#/components/Dialog' 14import * as TextField from '#/components/forms/TextField' 15import {InlineLinkText} from '#/components/Link' 16import {Loader} from '#/components/Loader' 17import {Text} from '#/components/Typography' 18 19export function VerifyEmailDialog({ 20 control, 21 onCloseWithoutVerifying, 22 onCloseAfterVerifying, 23 reasonText, 24}: { 25 control: Dialog.DialogControlProps 26 onCloseWithoutVerifying?: () => void 27 onCloseAfterVerifying?: () => void 28 reasonText?: string 29}) { 30 const agent = useAgent() 31 32 const [didVerify, setDidVerify] = React.useState(false) 33 34 return ( 35 <Dialog.Outer 36 control={control} 37 onClose={async () => { 38 if (!didVerify) { 39 onCloseWithoutVerifying?.() 40 return 41 } 42 43 try { 44 await agent.resumeSession(agent.session!) 45 onCloseAfterVerifying?.() 46 } catch (e: unknown) { 47 logger.error(String(e)) 48 return 49 } 50 }}> 51 <Dialog.Handle /> 52 <Inner 53 control={control} 54 setDidVerify={setDidVerify} 55 reasonText={reasonText} 56 /> 57 </Dialog.Outer> 58 ) 59} 60 61export function Inner({ 62 control, 63 setDidVerify, 64 reasonText, 65}: { 66 control: Dialog.DialogControlProps 67 setDidVerify: (value: boolean) => void 68 reasonText?: string 69}) { 70 const {_} = useLingui() 71 const {currentAccount} = useSession() 72 const agent = useAgent() 73 const {openModal} = useModalControls() 74 const {gtMobile} = useBreakpoints() 75 76 const [currentStep, setCurrentStep] = React.useState< 77 'StepOne' | 'StepTwo' | 'StepThree' 78 >('StepOne') 79 const [confirmationCode, setConfirmationCode] = React.useState('') 80 const [isProcessing, setIsProcessing] = React.useState(false) 81 const [error, setError] = React.useState('') 82 83 const uiStrings = { 84 StepOne: { 85 title: _(msg`Verify Your Email`), 86 message: '', 87 }, 88 StepTwo: { 89 title: _(msg`Enter Code`), 90 message: _( 91 msg`An email has been sent! Please enter the confirmation code included in the email below.`, 92 ), 93 }, 94 StepThree: { 95 title: _(msg`Success!`), 96 message: _(msg`Thank you! Your email has been successfully verified.`), 97 }, 98 } 99 100 const onSendEmail = async () => { 101 setError('') 102 setIsProcessing(true) 103 try { 104 await agent.com.atproto.server.requestEmailConfirmation() 105 setCurrentStep('StepTwo') 106 } catch (e: unknown) { 107 setError(cleanError(e)) 108 } finally { 109 setIsProcessing(false) 110 } 111 } 112 113 const onVerifyEmail = async () => { 114 setError('') 115 setIsProcessing(true) 116 try { 117 await agent.com.atproto.server.confirmEmail({ 118 email: (currentAccount?.email || '').trim(), 119 token: confirmationCode.trim(), 120 }) 121 } catch (e: unknown) { 122 setError(cleanError(String(e))) 123 setIsProcessing(false) 124 return 125 } 126 127 setIsProcessing(false) 128 setDidVerify(true) 129 setCurrentStep('StepThree') 130 } 131 132 return ( 133 <Dialog.ScrollableInner 134 label={_(msg`Verify email dialog`)} 135 style={[ 136 gtMobile ? {width: 'auto', maxWidth: 400, minWidth: 200} : a.w_full, 137 ]}> 138 <Dialog.Close /> 139 <View style={[a.gap_xl]}> 140 <View style={[a.gap_sm]}> 141 <Text style={[a.font_heavy, a.text_2xl]}> 142 {uiStrings[currentStep].title} 143 </Text> 144 {error ? ( 145 <View style={[a.rounded_sm, a.overflow_hidden]}> 146 <ErrorMessage message={error} /> 147 </View> 148 ) : null} 149 {currentStep === 'StepOne' ? ( 150 <View> 151 {reasonText ? ( 152 <View style={[a.gap_sm]}> 153 <Text style={[a.text_md, a.leading_snug]}>{reasonText}</Text> 154 <Text style={[a.text_md, a.leading_snug]}> 155 Don't have access to{' '} 156 <Text style={[a.text_md, a.leading_snug, a.font_bold]}> 157 {currentAccount?.email} 158 </Text> 159 ?{' '} 160 <InlineLinkText 161 to="#" 162 label={_(msg`Change email address`)} 163 style={[a.text_md, a.leading_snug]} 164 onPress={e => { 165 e.preventDefault() 166 control.close(() => { 167 openModal({name: 'change-email'}) 168 }) 169 return false 170 }}> 171 <Trans>Change your email address</Trans> 172 </InlineLinkText> 173 . 174 </Text> 175 </View> 176 ) : ( 177 <Text style={[a.text_md, a.leading_snug]}> 178 <Trans> 179 You'll receive an email at{' '} 180 <Text style={[a.text_md, a.leading_snug, a.font_bold]}> 181 {currentAccount?.email} 182 </Text>{' '} 183 to verify it's you. 184 </Trans>{' '} 185 <InlineLinkText 186 to="#" 187 label={_(msg`Change email address`)} 188 style={[a.text_md, a.leading_snug]} 189 onPress={e => { 190 e.preventDefault() 191 control.close(() => { 192 openModal({name: 'change-email'}) 193 }) 194 return false 195 }}> 196 <Trans>Need to change it?</Trans> 197 </InlineLinkText> 198 </Text> 199 )} 200 </View> 201 ) : ( 202 <Text style={[a.text_md, a.leading_snug]}> 203 {uiStrings[currentStep].message} 204 </Text> 205 )} 206 </View> 207 {currentStep === 'StepTwo' ? ( 208 <View> 209 <TextField.LabelText> 210 <Trans>Confirmation Code</Trans> 211 </TextField.LabelText> 212 <TextField.Root> 213 <TextField.Input 214 label={_(msg`Confirmation code`)} 215 placeholder="XXXXX-XXXXX" 216 onChangeText={setConfirmationCode} 217 /> 218 </TextField.Root> 219 </View> 220 ) : null} 221 <View style={[a.gap_sm, gtMobile && [a.flex_row_reverse, a.ml_auto]]}> 222 {currentStep === 'StepOne' ? ( 223 <> 224 <Button 225 label={_(msg`Send confirmation email`)} 226 variant="solid" 227 color="primary" 228 size="large" 229 disabled={isProcessing} 230 onPress={onSendEmail}> 231 <ButtonText> 232 <Trans>Send Confirmation</Trans> 233 </ButtonText> 234 {isProcessing ? ( 235 <Loader size="sm" style={[{color: 'white'}]} /> 236 ) : null} 237 </Button> 238 <Button 239 label={_(msg`I Have a Code`)} 240 variant="solid" 241 color="secondary" 242 size="large" 243 disabled={isProcessing} 244 onPress={() => setCurrentStep('StepTwo')}> 245 <ButtonText> 246 <Trans>I Have a Code</Trans> 247 </ButtonText> 248 </Button> 249 </> 250 ) : currentStep === 'StepTwo' ? ( 251 <> 252 <Button 253 label={_(msg`Confirm`)} 254 variant="solid" 255 color="primary" 256 size="large" 257 disabled={isProcessing} 258 onPress={onVerifyEmail}> 259 <ButtonText> 260 <Trans>Confirm</Trans> 261 </ButtonText> 262 {isProcessing ? ( 263 <Loader size="sm" style={[{color: 'white'}]} /> 264 ) : null} 265 </Button> 266 <Button 267 label={_(msg`Resend Email`)} 268 variant="solid" 269 color="secondary" 270 size="large" 271 disabled={isProcessing} 272 onPress={() => { 273 setConfirmationCode('') 274 setCurrentStep('StepOne') 275 }}> 276 <ButtonText> 277 <Trans>Resend Email</Trans> 278 </ButtonText> 279 </Button> 280 </> 281 ) : currentStep === 'StepThree' ? ( 282 <Button 283 label={_(msg`Confirm`)} 284 variant="solid" 285 color="primary" 286 size="large" 287 onPress={() => control.close()}> 288 <ButtonText> 289 <Trans>Close</Trans> 290 </ButtonText> 291 </Button> 292 ) : null} 293 </View> 294 </View> 295 </Dialog.ScrollableInner> 296 ) 297}