import {useReducer, useState} from 'react' import {View} from 'react-native' import {msg, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' import {wait} from '#/lib/async/wait' import {useCleanError} from '#/lib/hooks/useCleanError' import {logger} from '#/logger' import {useSession} from '#/state/session' import {atoms as a, useTheme} from '#/alf' import {Admonition} from '#/components/Admonition' import {Button, ButtonIcon, ButtonText} from '#/components/Button' import {useDialogContext} from '#/components/Dialog' import {ResendEmailText} from '#/components/dialogs/EmailDialog/components/ResendEmailText' import { isValidCode, TokenField, } from '#/components/dialogs/EmailDialog/components/TokenField' import {useManageEmail2FA} from '#/components/dialogs/EmailDialog/data/useManageEmail2FA' import {useRequestEmailUpdate} from '#/components/dialogs/EmailDialog/data/useRequestEmailUpdate' import {Divider} from '#/components/Divider' import {Check_Stroke2_Corner0_Rounded as Check} from '#/components/icons/Check' import {Envelope_Stroke2_Corner0_Rounded as Envelope} from '#/components/icons/Envelope' import {createStaticClick, InlineLinkText} from '#/components/Link' import {Loader} from '#/components/Loader' import {Span, Text} from '#/components/Typography' type State = { error: string step: 'email' | 'token' emailStatus: 'pending' | 'success' | 'error' | 'default' tokenStatus: 'pending' | 'success' | 'error' | 'default' } type Action = | { type: 'setError' error: string } | { type: 'setStep' step: 'email' | 'token' } | { type: 'setEmailStatus' status: State['emailStatus'] } | { type: 'setTokenStatus' status: State['tokenStatus'] } function reducer(state: State, action: Action): State { switch (action.type) { case 'setError': { return { ...state, error: action.error, emailStatus: 'error', tokenStatus: 'error', } } case 'setStep': { return { ...state, error: '', step: action.step, } } case 'setEmailStatus': { return { ...state, error: '', emailStatus: action.status, } } case 'setTokenStatus': { return { ...state, error: '', tokenStatus: action.status, } } default: { return state } } } export function Disable() { const t = useTheme() const {_} = useLingui() const cleanError = useCleanError() const {currentAccount} = useSession() const {mutateAsync: requestEmailUpdate} = useRequestEmailUpdate() const {mutateAsync: manageEmail2FA} = useManageEmail2FA() const control = useDialogContext() const [token, setToken] = useState('') const [state, dispatch] = useReducer(reducer, { error: '', step: 'email', emailStatus: 'default', tokenStatus: 'default', }) const handleSendEmail = async () => { dispatch({type: 'setEmailStatus', status: 'pending'}) try { await wait(1000, requestEmailUpdate()) dispatch({type: 'setEmailStatus', status: 'success'}) setTimeout(() => { dispatch({type: 'setStep', step: 'token'}) }, 1000) } catch (e) { logger.error('Manage2FA: email update code request failed', { safeMessage: e, }) const {clean} = cleanError(e) dispatch({ type: 'setError', error: clean || _(msg`Failed to send email, please try again.`), }) } } const handleManageEmail2FA = async () => { if (!isValidCode(token)) { dispatch({ type: 'setError', error: _(msg`Please enter a valid code.`), }) return } dispatch({type: 'setTokenStatus', status: 'pending'}) try { await wait(1000, manageEmail2FA({enabled: false, token})) dispatch({type: 'setTokenStatus', status: 'success'}) setTimeout(() => { control.close() }, 1000) } catch (e) { logger.error('Manage2FA: disable email 2FA failed', {safeMessage: e}) const {clean} = cleanError(e) dispatch({ type: 'setError', error: clean || _(msg`Failed to update email 2FA settings`), }) } } return ( Disable email 2FA {state.step === 'email' ? ( <> To disable your email 2FA method, please verify your access to{' '} {currentAccount?.email} {state.error && {state.error}} Have a code?{' '} { dispatch({type: 'setStep', step: 'token'}) })}> Click here. ) : ( <> To disable your email 2FA method, please verify your access to{' '} {currentAccount?.email} {state.error && {state.error}} )} ) }