Handle instructions and integrate into 2FA setting

This commit is contained in:
Eric Bailey
2025-04-25 15:57:54 -05:00
parent 90cb1ac41f
commit f4482dd292
4 changed files with 82 additions and 41 deletions
@@ -1,4 +1,4 @@
import {View, TextInputProps} from 'react-native'
import {type TextInputProps,View} from 'react-native'
import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
@@ -14,6 +14,7 @@ export function normalizeCode(value: string) {
export function TokenField({
value,
onChangeText,
onSubmitEditing,
}: Pick<TextInputProps, 'value' | 'onChangeText' | 'onSubmitEditing'>) {
const {_} = useLingui()
@@ -30,6 +31,7 @@ export function TokenField({
placeholder="XXXXX-XXXXX"
value={value}
onChangeText={handleOnChangeText}
onSubmitEditing={onSubmitEditing}
/>
</TextField.Root>
</View>
@@ -21,7 +21,7 @@ import {createStaticClick, InlineLinkText} from '#/components/Link'
import {Loader} from '#/components/Loader'
import {Span, Text} from '#/components/Typography'
export function Verify(_props: {config: Exclude<Screen, {id: 'Update'}>}) {
export function Verify({config}: {config: Exclude<Screen, {id: 'Update'}>}) {
const t = useTheme()
const {_} = useLingui()
const {currentAccount} = useSession()
@@ -96,6 +96,22 @@ export function Verify(_props: {config: Exclude<Screen, {id: 'Update'}>}) {
)}
</Text>
{step === 'default' && (
<>
{config.instructions?.map((int, i) => (
<Text
key={i}
style={[
a.text_sm,
a.leading_snug,
t.atoms.text_contrast_medium,
]}>
{int}
</Text>
))}
</>
)}
<Text style={[a.text_sm, a.leading_snug, t.atoms.text_contrast_medium]}>
{step === 'sent' ? (
<Trans>
@@ -136,6 +152,26 @@ export function Verify(_props: {config: Exclude<Screen, {id: 'Update'}>}) {
)}
</View>
{step === 'sent' && (
<>
<Divider />
<Text
style={[a.text_sm, a.leading_snug, t.atoms.text_contrast_medium]}>
<Trans>
Have a code?{' '}
<InlineLinkText
label={_(msg`Enter code`)}
{...createStaticClick(() => {
setStep('token')
})}>
Click here.
</InlineLinkText>
</Trans>
</Text>
</>
)}
{step === 'default' ? (
<>
{error && <Admonition type="error"> {error} </Admonition>}
@@ -155,21 +191,29 @@ export function Verify(_props: {config: Exclude<Screen, {id: 'Update'}>}) {
/>
</Button>
<Divider />
{!config.hideInitialCodeButton && (
<>
<Divider />
<Text
style={[a.text_sm, a.leading_snug, t.atoms.text_contrast_medium]}>
<Trans>
Have a code?{' '}
<InlineLinkText
label={_(msg`Enter code`)}
{...createStaticClick(() => {
setStep('token')
})}>
Click here.
</InlineLinkText>
</Trans>
</Text>
<Text
style={[
a.text_sm,
a.leading_snug,
t.atoms.text_contrast_medium,
]}>
<Trans>
Have a code?{' '}
<InlineLinkText
label={_(msg`Enter code`)}
{...createStaticClick(() => {
setStep('token')
})}>
Click here.
</InlineLinkText>
</Trans>
</Text>
</>
)}
</>
) : step === 'token' ? (
<>
+1 -6
View File
@@ -14,13 +14,8 @@ export type Screen =
}
| {
id: ScreenID.Verify
/**
* - default flow
* - new user blockers (x5)
*/
instructions?: ReactNode[]
// onCloseWithoutVerifying,
// onCloseAfterVerifying,
hideInitialCodeButton?: boolean
}
export enum ScreenID {
@@ -1,11 +1,14 @@
import React from 'react'
import {msg} from '@lingui/macro'
import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {useAgent, useSession} from '#/state/session'
import {useDialogControl} from '#/components/Dialog'
import {ChangeEmailDialog} from '#/components/dialogs/ChangeEmailDialog'
import {VerifyEmailDialog} from '#/components/dialogs/VerifyEmailDialog'
import {
EmailDialog,
EmailDialogScreenID,
useEmailDialogControl,
} from '#/components/dialogs/EmailDialog'
import * as Prompt from '#/components/Prompt'
import {DisableEmail2FADialog} from './DisableEmail2FADialog'
import * as SettingsList from './SettingsList'
@@ -15,9 +18,8 @@ export function Email2FAToggle() {
const {currentAccount} = useSession()
const disableDialogControl = useDialogControl()
const enableDialogControl = useDialogControl()
const verifyEmailDialogControl = useDialogControl()
const changeEmailDialogControl = useDialogControl()
const agent = useAgent()
const emailDialogControl = useEmailDialogControl()
const enableEmailAuthFactor = React.useCallback(async () => {
if (currentAccount?.email) {
@@ -37,7 +39,16 @@ export function Email2FAToggle() {
disableDialogControl.open()
} else {
if (!currentAccount.emailConfirmed) {
verifyEmailDialogControl.open()
emailDialogControl.open({
id: EmailDialogScreenID.Verify,
hideInitialCodeButton: true,
instructions: [
<Trans key="2fa">
You need to verify your email address before you can enable email
2FA.
</Trans>,
],
})
return
}
enableDialogControl.open()
@@ -45,8 +56,8 @@ export function Email2FAToggle() {
}, [
currentAccount,
enableDialogControl,
verifyEmailDialogControl,
disableDialogControl,
emailDialogControl,
])
return (
@@ -59,18 +70,7 @@ export function Email2FAToggle() {
onConfirm={enableEmailAuthFactor}
confirmButtonCta={_(msg`Enable`)}
/>
<VerifyEmailDialog
control={verifyEmailDialogControl}
changeEmailControl={changeEmailDialogControl}
onCloseAfterVerifying={enableDialogControl.open}
reasonText={_(
msg`You need to verify your email address before you can enable email 2FA.`,
)}
/>
<ChangeEmailDialog
control={changeEmailDialogControl}
verifyEmailControl={verifyEmailDialogControl}
/>
<EmailDialog control={emailDialogControl} />
<SettingsList.BadgeButton
label={
currentAccount?.emailAuthFactor ? _(msg`Change`) : _(msg`Enable`)