1
+ import type { RouteProp } from '@react-navigation/native' ;
2
+ import { useRoute } from '@react-navigation/native' ;
1
3
import React , { useEffect , useState } from 'react' ;
2
4
import { ActivityIndicator , View } from 'react-native' ;
3
5
import { withOnyx } from 'react-native-onyx' ;
@@ -10,40 +12,45 @@ import PressableWithDelayToggle from '@components/Pressable/PressableWithDelayTo
10
12
import ScrollView from '@components/ScrollView' ;
11
13
import Section from '@components/Section' ;
12
14
import Text from '@components/Text' ;
15
+ import ValidateAccountMessage from '@components/ValidateAccountMessage' ;
13
16
import useLocalize from '@hooks/useLocalize' ;
14
17
import useResponsiveLayout from '@hooks/useResponsiveLayout' ;
15
18
import useTheme from '@hooks/useTheme' ;
16
19
import useThemeStyles from '@hooks/useThemeStyles' ;
17
20
import Clipboard from '@libs/Clipboard' ;
18
21
import localFileDownload from '@libs/localFileDownload' ;
19
- import type { BackToParams } from '@libs/Navigation/types' ;
22
+ import type { BackToParams , SettingsNavigatorParamList } from '@libs/Navigation/types' ;
20
23
import StepWrapper from '@pages/settings/Security/TwoFactorAuth/StepWrapper/StepWrapper' ;
21
24
import useTwoFactorAuthContext from '@pages/settings/Security/TwoFactorAuth/TwoFactorAuthContext/useTwoFactorAuth' ;
22
25
import type { BaseTwoFactorAuthFormOnyxProps } from '@pages/settings/Security/TwoFactorAuth/TwoFactorAuthForm/types' ;
23
26
import * as Session from '@userActions/Session' ;
24
27
import * as TwoFactorAuthActions from '@userActions/TwoFactorAuthActions' ;
25
28
import CONST from '@src/CONST' ;
26
29
import ONYXKEYS from '@src/ONYXKEYS' ;
30
+ import ROUTES from '@src/ROUTES' ;
31
+ import type SCREENS from '@src/SCREENS' ;
27
32
28
33
type CodesStepProps = BaseTwoFactorAuthFormOnyxProps & BackToParams ;
29
34
30
- function CodesStep ( { account, backTo} : CodesStepProps ) {
35
+ function CodesStep ( { account, user , backTo} : CodesStepProps ) {
31
36
const theme = useTheme ( ) ;
32
37
const styles = useThemeStyles ( ) ;
33
38
const { translate} = useLocalize ( ) ;
34
39
const { isExtraSmallScreenWidth, isSmallScreenWidth} = useResponsiveLayout ( ) ;
35
40
const [ error , setError ] = useState ( '' ) ;
41
+ const isUserValidated = user ?. validated ;
42
+ const route = useRoute < RouteProp < SettingsNavigatorParamList , typeof SCREENS . SETTINGS . TWO_FACTOR_AUTH > > ( ) ;
36
43
37
44
const { setStep} = useTwoFactorAuthContext ( ) ;
38
45
39
46
useEffect ( ( ) => {
40
47
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
41
- if ( account ?. requiresTwoFactorAuth || account ?. recoveryCodes ) {
48
+ if ( account ?. requiresTwoFactorAuth || account ?. recoveryCodes || ! isUserValidated ) {
42
49
return ;
43
50
}
44
51
Session . toggleTwoFactorAuth ( true ) ;
45
52
// eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps -- We want to run this when component mounts
46
- } , [ ] ) ;
53
+ } , [ isUserValidated ] ) ;
47
54
48
55
return (
49
56
< StepWrapper
@@ -57,70 +64,73 @@ function CodesStep({account, backTo}: CodesStepProps) {
57
64
onBackButtonPress = { ( ) => TwoFactorAuthActions . quitAndNavigateBack ( backTo ) }
58
65
>
59
66
< ScrollView contentContainerStyle = { styles . flexGrow1 } >
60
- < Section
61
- title = { translate ( 'twoFactorAuth.keepCodesSafe' ) }
62
- icon = { Illustrations . ShieldYellow }
63
- containerStyles = { [ styles . twoFactorAuthSection ] }
64
- iconContainerStyles = { [ styles . ml6 ] }
65
- >
66
- < View style = { styles . mv3 } >
67
- < Text > { translate ( 'twoFactorAuth.codesLoseAccess' ) } </ Text >
68
- </ View >
69
- < View style = { styles . twoFactorAuthCodesBox ( { isExtraSmallScreenWidth, isSmallScreenWidth} ) } >
70
- { account ?. isLoading ? (
71
- < View style = { styles . twoFactorLoadingContainer } >
72
- < ActivityIndicator color = { theme . spinner } />
73
- </ View >
74
- ) : (
75
- < >
76
- < View style = { styles . twoFactorAuthCodesContainer } >
77
- { ! ! account ?. recoveryCodes &&
78
- account ?. recoveryCodes ?. split ( ', ' ) . map ( ( code ) => (
79
- < Text
80
- style = { styles . twoFactorAuthCode }
81
- key = { code }
82
- >
83
- { code }
84
- </ Text >
85
- ) ) }
67
+ { isUserValidated && (
68
+ < Section
69
+ title = { translate ( 'twoFactorAuth.keepCodesSafe' ) }
70
+ icon = { Illustrations . ShieldYellow }
71
+ containerStyles = { [ styles . twoFactorAuthSection ] }
72
+ iconContainerStyles = { [ styles . ml6 ] }
73
+ >
74
+ < View style = { styles . mv3 } >
75
+ < Text > { translate ( 'twoFactorAuth.codesLoseAccess' ) } </ Text >
76
+ </ View >
77
+ < View style = { styles . twoFactorAuthCodesBox ( { isExtraSmallScreenWidth, isSmallScreenWidth} ) } >
78
+ { account ?. isLoading ? (
79
+ < View style = { styles . twoFactorLoadingContainer } >
80
+ < ActivityIndicator color = { theme . spinner } />
86
81
</ View >
87
- < View style = { styles . twoFactorAuthCodesButtonsContainer } >
88
- < PressableWithDelayToggle
89
- text = { translate ( 'twoFactorAuth.copy' ) }
90
- textChecked = { translate ( 'common.copied' ) }
91
- icon = { Expensicons . Copy }
92
- inline = { false }
93
- onPress = { ( ) => {
94
- Clipboard . setString ( account ?. recoveryCodes ?? '' ) ;
95
- setError ( '' ) ;
96
- TwoFactorAuthActions . setCodesAreCopied ( ) ;
97
- } }
98
- styles = { [ styles . button , styles . buttonMedium , styles . twoFactorAuthCodesButton ] }
99
- textStyles = { [ styles . buttonMediumText ] }
100
- accessible = { false }
101
- tooltipText = ""
102
- tooltipTextChecked = ""
103
- />
104
- < PressableWithDelayToggle
105
- text = { translate ( 'common.download' ) }
106
- icon = { Expensicons . Download }
107
- onPress = { ( ) => {
108
- localFileDownload ( 'two-factor-auth-codes' , account ?. recoveryCodes ?? '' ) ;
109
- setError ( '' ) ;
110
- TwoFactorAuthActions . setCodesAreCopied ( ) ;
111
- } }
112
- inline = { false }
113
- styles = { [ styles . button , styles . buttonMedium , styles . twoFactorAuthCodesButton ] }
114
- textStyles = { [ styles . buttonMediumText ] }
115
- accessible = { false }
116
- tooltipText = ""
117
- tooltipTextChecked = ""
118
- />
119
- </ View >
120
- </ >
121
- ) }
122
- </ View >
123
- </ Section >
82
+ ) : (
83
+ < >
84
+ < View style = { styles . twoFactorAuthCodesContainer } >
85
+ { ! ! account ?. recoveryCodes &&
86
+ account ?. recoveryCodes ?. split ( ', ' ) . map ( ( code ) => (
87
+ < Text
88
+ style = { styles . twoFactorAuthCode }
89
+ key = { code }
90
+ >
91
+ { code }
92
+ </ Text >
93
+ ) ) }
94
+ </ View >
95
+ < View style = { styles . twoFactorAuthCodesButtonsContainer } >
96
+ < PressableWithDelayToggle
97
+ text = { translate ( 'twoFactorAuth.copy' ) }
98
+ textChecked = { translate ( 'common.copied' ) }
99
+ icon = { Expensicons . Copy }
100
+ inline = { false }
101
+ onPress = { ( ) => {
102
+ Clipboard . setString ( account ?. recoveryCodes ?? '' ) ;
103
+ setError ( '' ) ;
104
+ TwoFactorAuthActions . setCodesAreCopied ( ) ;
105
+ } }
106
+ styles = { [ styles . button , styles . buttonMedium , styles . twoFactorAuthCodesButton ] }
107
+ textStyles = { [ styles . buttonMediumText ] }
108
+ accessible = { false }
109
+ tooltipText = ""
110
+ tooltipTextChecked = ""
111
+ />
112
+ < PressableWithDelayToggle
113
+ text = { translate ( 'common.download' ) }
114
+ icon = { Expensicons . Download }
115
+ onPress = { ( ) => {
116
+ localFileDownload ( 'two-factor-auth-codes' , account ?. recoveryCodes ?? '' ) ;
117
+ setError ( '' ) ;
118
+ TwoFactorAuthActions . setCodesAreCopied ( ) ;
119
+ } }
120
+ inline = { false }
121
+ styles = { [ styles . button , styles . buttonMedium , styles . twoFactorAuthCodesButton ] }
122
+ textStyles = { [ styles . buttonMediumText ] }
123
+ accessible = { false }
124
+ tooltipText = ""
125
+ tooltipTextChecked = ""
126
+ />
127
+ </ View >
128
+ </ >
129
+ ) }
130
+ </ View >
131
+ </ Section >
132
+ ) }
133
+ { ! isUserValidated && < ValidateAccountMessage backTo = { ROUTES . SETTINGS_2FA . getRoute ( route ?. params ?. backTo ) } /> }
124
134
< FixedFooter style = { [ styles . mtAuto , styles . pt5 ] } >
125
135
{ ! ! error && (
126
136
< FormHelpMessage
@@ -132,6 +142,7 @@ function CodesStep({account, backTo}: CodesStepProps) {
132
142
< Button
133
143
success
134
144
large
145
+ isDisabled = { ! isUserValidated }
135
146
text = { translate ( 'common.next' ) }
136
147
onPress = { ( ) => {
137
148
if ( ! account ?. codesAreCopied ) {
@@ -151,4 +162,7 @@ CodesStep.displayName = 'CodesStep';
151
162
152
163
export default withOnyx < CodesStepProps , BaseTwoFactorAuthFormOnyxProps > ( {
153
164
account : { key : ONYXKEYS . ACCOUNT } ,
165
+ user : {
166
+ key : ONYXKEYS . USER ,
167
+ } ,
154
168
} ) ( CodesStep ) ;
0 commit comments