diff options
author | Samuel Newman <mozzius@protonmail.com> | 2024-11-08 22:42:18 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-11-08 22:42:18 +0000 |
commit | 5da3f29498fda9ab1181df19a718e37099cb2cf6 (patch) | |
tree | 4989300fe333edc3ad1c12c7b0d03e6ff5112ee3 /src/screens/Settings/components/DisableEmail2FADialog.tsx | |
parent | e8a03058bb993bda993e78d24877884d39666d63 (diff) | |
download | voidsky-5da3f29498fda9ab1181df19a718e37099cb2cf6.tar.zst |
[Settings] Ungate, and remove old settings (#6144)
* move export car dialog * move disableemail2fadialog * delete old settings screens * fix type error * Update Navigation.tsx * Delete AccountDropdownBtn.tsx * remove old change handle modal * delete add app paswords * forgot to actually delete the change handle modal
Diffstat (limited to 'src/screens/Settings/components/DisableEmail2FADialog.tsx')
-rw-r--r-- | src/screens/Settings/components/DisableEmail2FADialog.tsx | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/src/screens/Settings/components/DisableEmail2FADialog.tsx b/src/screens/Settings/components/DisableEmail2FADialog.tsx new file mode 100644 index 000000000..1378759b0 --- /dev/null +++ b/src/screens/Settings/components/DisableEmail2FADialog.tsx @@ -0,0 +1,201 @@ +import React, {useState} from 'react' +import {View} from 'react-native' +import {msg, Trans} from '@lingui/macro' +import {useLingui} from '@lingui/react' + +import {cleanError} from '#/lib/strings/errors' +import {isNative} from '#/platform/detection' +import {useAgent, useSession} from '#/state/session' +import {ErrorMessage} from '#/view/com/util/error/ErrorMessage' +import * as Toast from '#/view/com/util/Toast' +import {atoms as a, useBreakpoints, useTheme} from '#/alf' +import {Button, ButtonIcon, ButtonText} from '#/components/Button' +import * as Dialog from '#/components/Dialog' +import * as TextField from '#/components/forms/TextField' +import {Lock_Stroke2_Corner0_Rounded as Lock} from '#/components/icons/Lock' +import {Loader} from '#/components/Loader' +import {P, Text} from '#/components/Typography' + +enum Stages { + Email, + ConfirmCode, +} + +export function DisableEmail2FADialog({ + control, +}: { + control: Dialog.DialogOuterProps['control'] +}) { + const {_} = useLingui() + const t = useTheme() + const {gtMobile} = useBreakpoints() + const {currentAccount} = useSession() + const agent = useAgent() + + const [stage, setStage] = useState<Stages>(Stages.Email) + const [confirmationCode, setConfirmationCode] = useState<string>('') + const [isProcessing, setIsProcessing] = useState<boolean>(false) + const [error, setError] = useState<string>('') + + const onSendEmail = async () => { + setError('') + setIsProcessing(true) + try { + await agent.com.atproto.server.requestEmailUpdate() + setStage(Stages.ConfirmCode) + } catch (e) { + setError(cleanError(String(e))) + } finally { + setIsProcessing(false) + } + } + + const onConfirmDisable = async () => { + setError('') + setIsProcessing(true) + try { + if (currentAccount?.email) { + await agent.com.atproto.server.updateEmail({ + email: currentAccount!.email, + token: confirmationCode.trim(), + emailAuthFactor: false, + }) + await agent.resumeSession(agent.session!) + Toast.show(_(msg`Email 2FA disabled`)) + } + control.close() + } catch (e) { + const errMsg = String(e) + if (errMsg.includes('Token is invalid')) { + setError(_(msg`Invalid 2FA confirmation code.`)) + } else { + setError(cleanError(errMsg)) + } + } finally { + setIsProcessing(false) + } + } + + return ( + <Dialog.Outer control={control}> + <Dialog.Handle /> + <Dialog.ScrollableInner + accessibilityDescribedBy="dialog-description" + accessibilityLabelledBy="dialog-title"> + <View style={[a.relative, a.gap_md, a.w_full]}> + <Text + nativeID="dialog-title" + style={[a.text_2xl, a.font_bold, t.atoms.text]}> + <Trans>Disable Email 2FA</Trans> + </Text> + <P nativeID="dialog-description"> + {stage === Stages.ConfirmCode ? ( + <Trans> + An email has been sent to{' '} + {currentAccount?.email || '(no email)'}. It includes a + confirmation code which you can enter below. + </Trans> + ) : ( + <Trans> + To disable the email 2FA method, please verify your access to + the email address. + </Trans> + )} + </P> + + {error ? <ErrorMessage message={error} /> : undefined} + + {stage === Stages.Email ? ( + <View + style={[ + a.gap_sm, + gtMobile && [a.flex_row, a.justify_end, a.gap_md], + ]}> + <Button + testID="sendEmailButton" + variant="solid" + color="primary" + size={gtMobile ? 'small' : 'large'} + onPress={onSendEmail} + label={_(msg`Send verification email`)} + disabled={isProcessing}> + <ButtonText> + <Trans>Send verification email</Trans> + </ButtonText> + {isProcessing && <ButtonIcon icon={Loader} />} + </Button> + <Button + testID="haveCodeButton" + variant="ghost" + color="primary" + size={gtMobile ? 'small' : 'large'} + onPress={() => setStage(Stages.ConfirmCode)} + label={_(msg`I have a code`)} + disabled={isProcessing}> + <ButtonText> + <Trans>I have a code</Trans> + </ButtonText> + </Button> + </View> + ) : stage === Stages.ConfirmCode ? ( + <View> + <View style={[a.mb_md]}> + <TextField.LabelText> + <Trans>Confirmation code</Trans> + </TextField.LabelText> + <TextField.Root> + <TextField.Icon icon={Lock} /> + <Dialog.Input + testID="confirmationCode" + label={_(msg`Confirmation code`)} + autoCapitalize="none" + autoFocus + autoCorrect={false} + autoComplete="off" + value={confirmationCode} + onChangeText={setConfirmationCode} + onSubmitEditing={onConfirmDisable} + editable={!isProcessing} + /> + </TextField.Root> + </View> + <View + style={[ + a.gap_sm, + gtMobile && [a.flex_row, a.justify_end, a.gap_md], + ]}> + <Button + testID="resendCodeBtn" + variant="ghost" + color="primary" + size={gtMobile ? 'small' : 'large'} + onPress={onSendEmail} + label={_(msg`Resend email`)} + disabled={isProcessing}> + <ButtonText> + <Trans>Resend email</Trans> + </ButtonText> + </Button> + <Button + testID="confirmBtn" + variant="solid" + color="primary" + size={gtMobile ? 'small' : 'large'} + onPress={onConfirmDisable} + label={_(msg`Confirm`)} + disabled={isProcessing}> + <ButtonText> + <Trans>Confirm</Trans> + </ButtonText> + {isProcessing && <ButtonIcon icon={Loader} />} + </Button> + </View> + </View> + ) : undefined} + + {!gtMobile && isNative && <View style={{height: 40}} />} + </View> + </Dialog.ScrollableInner> + </Dialog.Outer> + ) +} |