mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
at samuel/fancy-queue 274 lines 8.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 <Text style={[a.text_md, a.leading_snug]}> 150 {currentStep === 'StepOne' ? ( 151 <> 152 {!reasonText ? ( 153 <> 154 <Trans> 155 You'll receive an email at{' '} 156 <Text style={[a.text_md, a.leading_snug, a.font_bold]}> 157 {currentAccount?.email} 158 </Text>{' '} 159 to verify it's you. 160 </Trans>{' '} 161 <InlineLinkText 162 to="#" 163 label={_(msg`Change email address`)} 164 style={[a.text_md, a.leading_snug]} 165 onPress={e => { 166 e.preventDefault() 167 control.close(() => { 168 openModal({name: 'change-email'}) 169 }) 170 return false 171 }}> 172 <Trans>Need to change it?</Trans> 173 </InlineLinkText> 174 </> 175 ) : ( 176 reasonText 177 )} 178 </> 179 ) : ( 180 uiStrings[currentStep].message 181 )} 182 </Text> 183 </View> 184 {currentStep === 'StepTwo' ? ( 185 <View> 186 <TextField.LabelText> 187 <Trans>Confirmation Code</Trans> 188 </TextField.LabelText> 189 <TextField.Root> 190 <TextField.Input 191 label={_(msg`Confirmation code`)} 192 placeholder="XXXXX-XXXXX" 193 onChangeText={setConfirmationCode} 194 /> 195 </TextField.Root> 196 </View> 197 ) : null} 198 <View style={[a.gap_sm, gtMobile && [a.flex_row_reverse, a.ml_auto]]}> 199 {currentStep === 'StepOne' ? ( 200 <> 201 <Button 202 label={_(msg`Send confirmation email`)} 203 variant="solid" 204 color="primary" 205 size="large" 206 disabled={isProcessing} 207 onPress={onSendEmail}> 208 <ButtonText> 209 <Trans>Send Confirmation</Trans> 210 </ButtonText> 211 {isProcessing ? ( 212 <Loader size="sm" style={[{color: 'white'}]} /> 213 ) : null} 214 </Button> 215 <Button 216 label={_(msg`I Have a Code`)} 217 variant="solid" 218 color="secondary" 219 size="large" 220 disabled={isProcessing} 221 onPress={() => setCurrentStep('StepTwo')}> 222 <ButtonText> 223 <Trans>I Have a Code</Trans> 224 </ButtonText> 225 </Button> 226 </> 227 ) : currentStep === 'StepTwo' ? ( 228 <> 229 <Button 230 label={_(msg`Confirm`)} 231 variant="solid" 232 color="primary" 233 size="large" 234 disabled={isProcessing} 235 onPress={onVerifyEmail}> 236 <ButtonText> 237 <Trans>Confirm</Trans> 238 </ButtonText> 239 {isProcessing ? ( 240 <Loader size="sm" style={[{color: 'white'}]} /> 241 ) : null} 242 </Button> 243 <Button 244 label={_(msg`Resend Email`)} 245 variant="solid" 246 color="secondary" 247 size="large" 248 disabled={isProcessing} 249 onPress={() => { 250 setConfirmationCode('') 251 setCurrentStep('StepOne') 252 }}> 253 <ButtonText> 254 <Trans>Resend Email</Trans> 255 </ButtonText> 256 </Button> 257 </> 258 ) : currentStep === 'StepThree' ? ( 259 <Button 260 label={_(msg`Confirm`)} 261 variant="solid" 262 color="primary" 263 size="large" 264 onPress={() => control.close()}> 265 <ButtonText> 266 <Trans>Close</Trans> 267 </ButtonText> 268 </Button> 269 ) : null} 270 </View> 271 </View> 272 </Dialog.ScrollableInner> 273 ) 274}