Handle instructions and integrate into 2FA setting
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import {View, TextInputProps} from 'react-native'
|
import {type TextInputProps,View} from 'react-native'
|
||||||
import {msg} from '@lingui/macro'
|
import {msg} from '@lingui/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
|
|
||||||
@@ -14,6 +14,7 @@ export function normalizeCode(value: string) {
|
|||||||
export function TokenField({
|
export function TokenField({
|
||||||
value,
|
value,
|
||||||
onChangeText,
|
onChangeText,
|
||||||
|
onSubmitEditing,
|
||||||
}: Pick<TextInputProps, 'value' | 'onChangeText' | 'onSubmitEditing'>) {
|
}: Pick<TextInputProps, 'value' | 'onChangeText' | 'onSubmitEditing'>) {
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
|
|
||||||
@@ -30,6 +31,7 @@ export function TokenField({
|
|||||||
placeholder="XXXXX-XXXXX"
|
placeholder="XXXXX-XXXXX"
|
||||||
value={value}
|
value={value}
|
||||||
onChangeText={handleOnChangeText}
|
onChangeText={handleOnChangeText}
|
||||||
|
onSubmitEditing={onSubmitEditing}
|
||||||
/>
|
/>
|
||||||
</TextField.Root>
|
</TextField.Root>
|
||||||
</View>
|
</View>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import {createStaticClick, InlineLinkText} from '#/components/Link'
|
|||||||
import {Loader} from '#/components/Loader'
|
import {Loader} from '#/components/Loader'
|
||||||
import {Span, Text} from '#/components/Typography'
|
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 t = useTheme()
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
const {currentAccount} = useSession()
|
const {currentAccount} = useSession()
|
||||||
@@ -96,6 +96,22 @@ export function Verify(_props: {config: Exclude<Screen, {id: 'Update'}>}) {
|
|||||||
)}
|
)}
|
||||||
</Text>
|
</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]}>
|
<Text style={[a.text_sm, a.leading_snug, t.atoms.text_contrast_medium]}>
|
||||||
{step === 'sent' ? (
|
{step === 'sent' ? (
|
||||||
<Trans>
|
<Trans>
|
||||||
@@ -136,6 +152,26 @@ export function Verify(_props: {config: Exclude<Screen, {id: 'Update'}>}) {
|
|||||||
)}
|
)}
|
||||||
</View>
|
</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' ? (
|
{step === 'default' ? (
|
||||||
<>
|
<>
|
||||||
{error && <Admonition type="error"> {error} </Admonition>}
|
{error && <Admonition type="error"> {error} </Admonition>}
|
||||||
@@ -155,21 +191,29 @@ export function Verify(_props: {config: Exclude<Screen, {id: 'Update'}>}) {
|
|||||||
/>
|
/>
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<Divider />
|
{!config.hideInitialCodeButton && (
|
||||||
|
<>
|
||||||
|
<Divider />
|
||||||
|
|
||||||
<Text
|
<Text
|
||||||
style={[a.text_sm, a.leading_snug, t.atoms.text_contrast_medium]}>
|
style={[
|
||||||
<Trans>
|
a.text_sm,
|
||||||
Have a code?{' '}
|
a.leading_snug,
|
||||||
<InlineLinkText
|
t.atoms.text_contrast_medium,
|
||||||
label={_(msg`Enter code`)}
|
]}>
|
||||||
{...createStaticClick(() => {
|
<Trans>
|
||||||
setStep('token')
|
Have a code?{' '}
|
||||||
})}>
|
<InlineLinkText
|
||||||
Click here.
|
label={_(msg`Enter code`)}
|
||||||
</InlineLinkText>
|
{...createStaticClick(() => {
|
||||||
</Trans>
|
setStep('token')
|
||||||
</Text>
|
})}>
|
||||||
|
Click here.
|
||||||
|
</InlineLinkText>
|
||||||
|
</Trans>
|
||||||
|
</Text>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
) : step === 'token' ? (
|
) : step === 'token' ? (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@@ -14,13 +14,8 @@ export type Screen =
|
|||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
id: ScreenID.Verify
|
id: ScreenID.Verify
|
||||||
/**
|
|
||||||
* - default flow
|
|
||||||
* - new user blockers (x5)
|
|
||||||
*/
|
|
||||||
instructions?: ReactNode[]
|
instructions?: ReactNode[]
|
||||||
// onCloseWithoutVerifying,
|
hideInitialCodeButton?: boolean
|
||||||
// onCloseAfterVerifying,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum ScreenID {
|
export enum ScreenID {
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {msg} from '@lingui/macro'
|
import {msg, Trans} from '@lingui/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
|
|
||||||
import {useAgent, useSession} from '#/state/session'
|
import {useAgent, useSession} from '#/state/session'
|
||||||
import {useDialogControl} from '#/components/Dialog'
|
import {useDialogControl} from '#/components/Dialog'
|
||||||
import {ChangeEmailDialog} from '#/components/dialogs/ChangeEmailDialog'
|
import {
|
||||||
import {VerifyEmailDialog} from '#/components/dialogs/VerifyEmailDialog'
|
EmailDialog,
|
||||||
|
EmailDialogScreenID,
|
||||||
|
useEmailDialogControl,
|
||||||
|
} from '#/components/dialogs/EmailDialog'
|
||||||
import * as Prompt from '#/components/Prompt'
|
import * as Prompt from '#/components/Prompt'
|
||||||
import {DisableEmail2FADialog} from './DisableEmail2FADialog'
|
import {DisableEmail2FADialog} from './DisableEmail2FADialog'
|
||||||
import * as SettingsList from './SettingsList'
|
import * as SettingsList from './SettingsList'
|
||||||
@@ -15,9 +18,8 @@ export function Email2FAToggle() {
|
|||||||
const {currentAccount} = useSession()
|
const {currentAccount} = useSession()
|
||||||
const disableDialogControl = useDialogControl()
|
const disableDialogControl = useDialogControl()
|
||||||
const enableDialogControl = useDialogControl()
|
const enableDialogControl = useDialogControl()
|
||||||
const verifyEmailDialogControl = useDialogControl()
|
|
||||||
const changeEmailDialogControl = useDialogControl()
|
|
||||||
const agent = useAgent()
|
const agent = useAgent()
|
||||||
|
const emailDialogControl = useEmailDialogControl()
|
||||||
|
|
||||||
const enableEmailAuthFactor = React.useCallback(async () => {
|
const enableEmailAuthFactor = React.useCallback(async () => {
|
||||||
if (currentAccount?.email) {
|
if (currentAccount?.email) {
|
||||||
@@ -37,7 +39,16 @@ export function Email2FAToggle() {
|
|||||||
disableDialogControl.open()
|
disableDialogControl.open()
|
||||||
} else {
|
} else {
|
||||||
if (!currentAccount.emailConfirmed) {
|
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
|
return
|
||||||
}
|
}
|
||||||
enableDialogControl.open()
|
enableDialogControl.open()
|
||||||
@@ -45,8 +56,8 @@ export function Email2FAToggle() {
|
|||||||
}, [
|
}, [
|
||||||
currentAccount,
|
currentAccount,
|
||||||
enableDialogControl,
|
enableDialogControl,
|
||||||
verifyEmailDialogControl,
|
|
||||||
disableDialogControl,
|
disableDialogControl,
|
||||||
|
emailDialogControl,
|
||||||
])
|
])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -59,18 +70,7 @@ export function Email2FAToggle() {
|
|||||||
onConfirm={enableEmailAuthFactor}
|
onConfirm={enableEmailAuthFactor}
|
||||||
confirmButtonCta={_(msg`Enable`)}
|
confirmButtonCta={_(msg`Enable`)}
|
||||||
/>
|
/>
|
||||||
<VerifyEmailDialog
|
<EmailDialog control={emailDialogControl} />
|
||||||
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}
|
|
||||||
/>
|
|
||||||
<SettingsList.BadgeButton
|
<SettingsList.BadgeButton
|
||||||
label={
|
label={
|
||||||
currentAccount?.emailAuthFactor ? _(msg`Change`) : _(msg`Enable`)
|
currentAccount?.emailAuthFactor ? _(msg`Change`) : _(msg`Enable`)
|
||||||
|
|||||||
Reference in New Issue
Block a user