1
1
import React , { ReactElement , useCallback , useEffect , useState } from 'react' ;
2
- import { StyleSheet , View } from 'react-native' ;
2
+ import { Image , StyleSheet , View } from 'react-native' ;
3
3
import { Trans , useTranslation } from 'react-i18next' ;
4
4
5
- import { Display , BodyM } from '../../styles/text' ;
6
- import { View as ThemedView } from '../../styles/components' ;
7
- import { IColors } from '../../styles/colors' ;
8
- import { restoreRemoteBackups , startWalletServices } from '../../utils/startup' ;
9
- import { showToast } from '../../utils/notifications' ;
10
- import { sleep } from '../../utils/helpers' ;
11
- import { updateUser } from '../../store/slices/user' ;
5
+ import Dialog from '../../components/Dialog' ;
12
6
import SafeAreaInset from '../../components/SafeAreaInset' ;
7
+ import { SlashtagsProvider } from '../../components/SlashtagsProvider' ;
13
8
import Button from '../../components/buttons/Button' ;
14
- import Dialog from '../../components/Dialog' ;
15
- import LoadingWalletScreen from './Loading' ;
16
9
import { useAppDispatch , useAppSelector } from '../../hooks/redux' ;
17
10
import { useProfile , useSlashtags } from '../../hooks/slashtags' ;
18
- import { setOnboardingProfileStep } from '../../store/slices/slashtags ' ;
11
+ import { OnboardingStackScreenProps } from '../../navigation/types ' ;
19
12
import { onboardingProfileStepSelector } from '../../store/reselect/slashtags' ;
20
- import { Image } from 'react-native' ;
13
+ import { requiresRemoteRestoreSelector } from '../../store/reselect/user' ;
14
+ import { walletExistsSelector } from '../../store/reselect/wallet' ;
15
+ import { setOnboardingProfileStep } from '../../store/slices/slashtags' ;
16
+ import { updateUser } from '../../store/slices/user' ;
17
+ import { View as ThemedView } from '../../styles/components' ;
18
+ import { BodyM , Display } from '../../styles/text' ;
19
+ import { sleep } from '../../utils/helpers' ;
20
+ import { showToast } from '../../utils/notifications' ;
21
+ import {
22
+ createNewWallet ,
23
+ restoreRemoteBackups ,
24
+ restoreSeed ,
25
+ startWalletServices ,
26
+ } from '../../utils/startup' ;
27
+ import LoadingWalletScreen from './Loading' ;
21
28
22
29
const checkImageSrc = require ( '../../assets/illustrations/check.png' ) ;
23
30
const crossImageSrc = require ( '../../assets/illustrations/cross.png' ) ;
24
31
25
- let attemptedAutoRestore = false ;
32
+ // prettier-ignore
33
+ export type TCreateWalletParams = {
34
+ action : 'create' ;
35
+ bip39Passphrase ?: string ;
36
+ } | {
37
+ action : 'restore' ;
38
+ mnemonic : string ;
39
+ bip39Passphrase ?: string ;
40
+ } | undefined ;
26
41
27
- const RestoringScreen = ( ) : ReactElement => {
42
+ const CreateWallet = ( {
43
+ navigation,
44
+ route,
45
+ } : OnboardingStackScreenProps < 'CreateWallet' > ) : ReactElement => {
46
+ const params = route . params ;
28
47
const { t } = useTranslation ( 'onboarding' ) ;
29
- const { url } = useSlashtags ( ) ;
30
- const { profile } = useProfile ( url ) ;
31
48
const dispatch = useAppDispatch ( ) ;
32
- const onboardingStep = useAppSelector ( onboardingProfileStepSelector ) ;
33
- const [ showRestored , setShowRestored ] = useState ( false ) ;
34
- const [ showFailed , setShowFailed ] = useState ( false ) ;
35
- const [ proceedWBIsLoading , setProceedWBIsLoading ] = useState ( false ) ;
49
+ const requiresRemoteRestore = useAppSelector ( requiresRemoteRestoreSelector ) ;
50
+ const walletExists = useAppSelector ( walletExistsSelector ) ;
51
+ const [ status , setStatus ] = useState < 'loading' | 'success' | 'failed' > (
52
+ 'loading' ,
53
+ ) ;
36
54
const [ tryAgainCount , setTryAgainCount ] = useState ( 0 ) ;
55
+ const [ proceedWBIsLoading , setProceedWBIsLoading ] = useState ( false ) ;
37
56
const [ showCautionDialog , setShowCautionDialog ] = useState ( false ) ;
38
57
39
- const onRemoteRestore = useCallback ( async ( ) : Promise < void > => {
40
- attemptedAutoRestore = true ;
41
- setShowFailed ( false ) ;
42
- setShowRestored ( false ) ;
58
+ const handleCreate = useCallback (
59
+ async ( bip39Passphrase ?: string ) => {
60
+ await sleep ( 500 ) ; // wait for animation to start
61
+ const res = await createNewWallet ( { bip39Passphrase } ) ;
62
+ if ( res . isErr ( ) ) {
63
+ showToast ( {
64
+ type : 'warning' ,
65
+ title : t ( 'error_create' ) ,
66
+ description : res . error . message ,
67
+ } ) ;
68
+ navigation . goBack ( ) ;
69
+ }
70
+ } ,
71
+ [ t , navigation ] ,
72
+ ) ;
73
+
74
+ const handleRestore = useCallback (
75
+ async ( mnemonic : string , bip39Passphrase ?: string ) => {
76
+ await sleep ( 500 ) ; // wait for animation to start
77
+ const res = await restoreSeed ( {
78
+ mnemonic,
79
+ bip39Passphrase,
80
+ } ) ;
81
+ if ( res . isErr ( ) ) {
82
+ showToast ( {
83
+ type : 'warning' ,
84
+ title : t ( 'restore_error_title' ) ,
85
+ description : res . error . message ,
86
+ } ) ;
87
+ navigation . goBack ( ) ;
88
+ }
89
+ } ,
90
+ [ t , navigation ] ,
91
+ ) ;
43
92
93
+ const handleRemoteRestore = useCallback ( async ( ) : Promise < void > => {
94
+ setStatus ( 'loading' ) ;
44
95
const res = await restoreRemoteBackups ( ) ;
45
96
await sleep ( 1000 ) ;
46
- if ( res . isErr ( ) ) {
47
- return setShowFailed ( true ) ;
48
- }
49
-
50
- setShowRestored ( true ) ;
97
+ setStatus ( res . isErr ( ) ? 'failed' : 'success' ) ;
51
98
} , [ ] ) ;
52
99
53
100
const proceedWithoutBackup = useCallback ( async ( ) => {
@@ -69,41 +116,46 @@ const RestoringScreen = (): ReactElement => {
69
116
} , [ t , dispatch ] ) ;
70
117
71
118
useEffect ( ( ) => {
72
- if ( attemptedAutoRestore ) {
119
+ if ( walletExists || ! params ) {
73
120
return ;
74
121
}
75
122
76
- onRemoteRestore ( ) . then ( ) ;
77
- } , [ onRemoteRestore ] ) ;
123
+ if ( params . action === 'create' ) {
124
+ handleCreate ( params . bip39Passphrase ) ;
125
+ } else {
126
+ handleRestore ( params . mnemonic , params . bip39Passphrase ) ;
127
+ }
128
+ } , [ walletExists , params , handleCreate , handleRestore ] ) ;
78
129
79
130
useEffect ( ( ) => {
80
- // If the user has a name, we can assume they have completed the profile onboarding
81
- if ( onboardingStep !== 'Done' && profile . name ) {
82
- dispatch ( setOnboardingProfileStep ( 'Done' ) ) ;
131
+ if ( ! walletExists || ! requiresRemoteRestore ) {
132
+ return ;
83
133
}
84
- } , [ profile . name , onboardingStep , dispatch ] ) ;
85
134
86
- let color : keyof IColors = 'brand' ;
87
- let content = < LoadingWalletScreen isRestoring = { true } /> ;
135
+ handleRemoteRestore ( ) ;
136
+ } , [ walletExists , requiresRemoteRestore , handleRemoteRestore ] ) ;
137
+
138
+ let content = < LoadingWalletScreen isRestoring = { requiresRemoteRestore } /> ;
88
139
89
- if ( showRestored || showFailed ) {
90
- color = showRestored ? 'green' : 'red' ;
140
+ if ( status === 'success' || status === 'failed' ) {
141
+ const success = status === 'success' ;
142
+ const color = success ? 'green' : 'red' ;
91
143
const title = t (
92
- showRestored ? 'restore_success_header' : 'restore_failed_header' ,
144
+ success ? 'restore_success_header' : 'restore_failed_header' ,
93
145
) ;
94
146
const subtitle = t (
95
- showRestored ? 'restore_success_text' : 'restore_failed_text' ,
147
+ success ? 'restore_success_text' : 'restore_failed_text' ,
96
148
) ;
97
- const imageSrc = showRestored ? checkImageSrc : crossImageSrc ;
98
- const buttonText = t ( showRestored ? 'get_started' : 'try_again' ) ;
149
+ const imageSrc = success ? checkImageSrc : crossImageSrc ;
150
+ const buttonText = t ( success ? 'get_started' : 'try_again' ) ;
99
151
100
152
const onPress = ( ) : void => {
101
- if ( showRestored ) {
102
- //App.tsx will show wallet now
153
+ if ( success ) {
154
+ // App.tsx will show wallet now
103
155
dispatch ( updateUser ( { requiresRemoteRestore : false } ) ) ;
104
156
} else {
105
- onRemoteRestore ( ) . then ( ) . catch ( console . error ) ;
106
- setTryAgainCount ( tryAgainCount + 1 ) ;
157
+ setTryAgainCount ( ( v ) => v + 1 ) ;
158
+ handleRemoteRestore ( ) ;
107
159
}
108
160
} ;
109
161
@@ -126,10 +178,10 @@ const RestoringScreen = (): ReactElement => {
126
178
< Button
127
179
size = "large"
128
180
text = { buttonText }
129
- testID = { showRestored ? 'GetStartedButton' : 'TryAgainButton' }
181
+ testID = { success ? 'GetStartedButton' : 'TryAgainButton' }
130
182
onPress = { onPress }
131
183
/>
132
- { tryAgainCount > 1 && showFailed && (
184
+ { tryAgainCount > 1 && ! success && (
133
185
< Button
134
186
style = { styles . proceedButton }
135
187
text = { t ( 'restore_no_backup_button' ) }
@@ -155,13 +207,33 @@ const RestoringScreen = (): ReactElement => {
155
207
/>
156
208
157
209
< SafeAreaInset type = "bottom" minPadding = { 16 } />
210
+
211
+ < SlashtagsProvider >
212
+ < SkipSlashtagsOnboading />
213
+ </ SlashtagsProvider >
158
214
</ View >
159
215
) ;
160
216
}
161
217
162
218
return < ThemedView style = { styles . root } > { content } </ ThemedView > ;
163
219
} ;
164
220
221
+ // this component is used to skip the slashtags onboarding process if profile is already created
222
+ const SkipSlashtagsOnboading = ( ) : ReactElement => {
223
+ const dispatch = useAppDispatch ( ) ;
224
+ const onboardingStep = useAppSelector ( onboardingProfileStepSelector ) ;
225
+ const { url } = useSlashtags ( ) ;
226
+ const { profile } = useProfile ( url ) ;
227
+
228
+ useEffect ( ( ) => {
229
+ if ( onboardingStep !== 'Done' && profile . name ) {
230
+ dispatch ( setOnboardingProfileStep ( 'Done' ) ) ;
231
+ }
232
+ } , [ profile . name , onboardingStep , dispatch ] ) ;
233
+
234
+ return < > </ > ;
235
+ } ;
236
+
165
237
const styles = StyleSheet . create ( {
166
238
root : {
167
239
flex : 1 ,
@@ -195,4 +267,4 @@ const styles = StyleSheet.create({
195
267
} ,
196
268
} ) ;
197
269
198
- export default RestoringScreen ;
270
+ export default CreateWallet ;
0 commit comments