6
6
Text ,
7
7
View ,
8
8
ActivityIndicator ,
9
+ TouchableOpacity ,
9
10
} from "react-native" ;
10
- import { useState } from "react" ;
11
+ import { useState , useEffect } from "react" ;
11
12
import { useFacade } from "@/data/facades" ;
12
13
import { SettingsKey } from "@/data/settings/db" ;
13
14
import { Network } from "@/data/constants" ;
@@ -16,6 +17,7 @@ import { AccountFormat } from "@ironfish/sdk";
16
17
export default function MenuNetwork ( ) {
17
18
const [ modalVisible , setModalVisible ] = useState ( false ) ;
18
19
const [ isChangingNetwork , setIsChangingNetwork ] = useState ( false ) ;
20
+ const [ pendingNetwork , setPendingNetwork ] = useState < Network | null > ( null ) ;
19
21
20
22
const facade = useFacade ( ) ;
21
23
const setAppSetting = facade . setAppSetting . useMutation ( ) ;
@@ -26,8 +28,13 @@ export default function MenuNetwork() {
26
28
27
29
const currentNetwork =
28
30
networkSetting . data ?. [ SettingsKey . Network ] ?? Network . MAINNET ;
29
- const targetNetwork =
30
- currentNetwork === Network . MAINNET ? Network . TESTNET : Network . MAINNET ;
31
+
32
+ const handleNetworkPress = ( network : Network ) => {
33
+ if ( network !== currentNetwork ) {
34
+ setPendingNetwork ( network ) ;
35
+ setModalVisible ( true ) ;
36
+ }
37
+ } ;
31
38
32
39
const handleNetworkChange = async ( network : Network ) => {
33
40
setIsChangingNetwork ( true ) ;
@@ -59,6 +66,7 @@ export default function MenuNetwork() {
59
66
} finally {
60
67
setIsChangingNetwork ( false ) ;
61
68
setModalVisible ( false ) ;
69
+ setPendingNetwork ( null ) ;
62
70
}
63
71
} ;
64
72
@@ -73,59 +81,85 @@ export default function MenuNetwork() {
73
81
74
82
return (
75
83
< View style = { styles . container } >
76
- < Modal animationType = "slide" visible = { modalVisible } >
77
- < View style = { styles . container } >
78
- { isChangingNetwork ? (
79
- < >
80
- < ActivityIndicator size = "large" />
81
- < Text style = { styles . loadingText } >
82
- Changing network and re-importing accounts...
83
- </ Text >
84
- </ >
85
- ) : (
86
- < >
87
- < Text > Switch to { targetNetwork } ?</ Text >
88
- < Text >
89
- Switching networks will upload your accounts to the{ " " }
90
- { targetNetwork } server. It may take a few minutes for your
91
- accounts to sync.
92
- </ Text >
93
- < Button
94
- title = "Yes, Change Network"
95
- onPress = { ( ) => handleNetworkChange ( targetNetwork ) }
96
- />
97
- < Button
98
- title = "I changed my mind"
99
- onPress = { ( ) => setModalVisible ( false ) }
100
- />
101
- </ >
102
- ) }
84
+ < Modal animationType = "fade" visible = { modalVisible } transparent >
85
+ < View style = { styles . modalOverlay } >
86
+ < View style = { styles . modalContent } >
87
+ { isChangingNetwork ? (
88
+ < >
89
+ < ActivityIndicator size = "large" color = "#007AFF" />
90
+ < Text style = { styles . modalText } >
91
+ Changing network and re-importing accounts...
92
+ </ Text >
93
+ </ >
94
+ ) : (
95
+ < >
96
+ < Text style = { styles . modalTitle } >
97
+ Switch to { pendingNetwork } ?
98
+ </ Text >
99
+ < Text style = { styles . modalText } >
100
+ Switching networks will upload your accounts to the{ " " }
101
+ { pendingNetwork } server. It may take a few minutes for your
102
+ accounts to sync.
103
+ </ Text >
104
+ < View style = { styles . modalButtons } >
105
+ < Button
106
+ title = "Yes, Change Network"
107
+ onPress = { ( ) => handleNetworkChange ( pendingNetwork ! ) }
108
+ color = "#007AFF"
109
+ />
110
+ < Button
111
+ title = "Cancel"
112
+ onPress = { ( ) => {
113
+ setModalVisible ( false ) ;
114
+ setPendingNetwork ( null ) ;
115
+ } }
116
+ color = "#666"
117
+ />
118
+ </ View >
119
+ </ >
120
+ ) }
121
+ </ View >
103
122
</ View >
104
123
</ Modal >
105
- < View style = { styles . networkOption } >
106
- < View style = { styles . networkInfo } >
107
- < Text style = { styles . networkTitle } > Mainnet</ Text >
108
- < Text style = { styles . networkDescription } >
109
- The live blockchain network where real transactions with value
110
- occur.
111
- </ Text >
112
- { currentNetwork === Network . MAINNET && (
113
- < Text style = { styles . selectedText } > (Selected)</ Text >
114
- ) }
115
- </ View >
116
- </ View >
117
- < View style = { styles . networkOption } >
118
- < View style = { styles . networkInfo } >
119
- < Text style = { styles . networkTitle } > Testnet</ Text >
120
- < Text style = { styles . networkDescription } >
121
- A separate environment for testing without real asset risks.
122
- </ Text >
123
- { currentNetwork === Network . TESTNET && (
124
- < Text style = { styles . selectedText } > (Selected)</ Text >
125
- ) }
126
- </ View >
124
+
125
+ < View style = { styles . content } >
126
+ < TouchableOpacity
127
+ style = { [
128
+ styles . networkOption ,
129
+ currentNetwork === Network . MAINNET && styles . networkOptionSelected ,
130
+ ] }
131
+ onPress = { ( ) => handleNetworkPress ( Network . MAINNET ) }
132
+ >
133
+ < View style = { styles . networkInfo } >
134
+ < Text style = { styles . networkTitle } > Mainnet</ Text >
135
+ < Text style = { styles . networkDescription } >
136
+ The live blockchain network where real transactions with value
137
+ occur.
138
+ </ Text >
139
+ { currentNetwork === Network . MAINNET && (
140
+ < Text style = { styles . selectedText } > (Selected)</ Text >
141
+ ) }
142
+ </ View >
143
+ </ TouchableOpacity >
144
+
145
+ < TouchableOpacity
146
+ style = { [
147
+ styles . networkOption ,
148
+ currentNetwork === Network . TESTNET && styles . networkOptionSelected ,
149
+ ] }
150
+ onPress = { ( ) => handleNetworkPress ( Network . TESTNET ) }
151
+ >
152
+ < View style = { styles . networkInfo } >
153
+ < Text style = { styles . networkTitle } > Testnet</ Text >
154
+ < Text style = { styles . networkDescription } >
155
+ A separate environment for testing without real asset risks.
156
+ </ Text >
157
+ { currentNetwork === Network . TESTNET && (
158
+ < Text style = { styles . selectedText } > (Selected)</ Text >
159
+ ) }
160
+ </ View >
161
+ </ TouchableOpacity >
127
162
</ View >
128
- < Button title = "Change Network" onPress = { ( ) => setModalVisible ( true ) } />
129
163
< StatusBar style = "auto" />
130
164
</ View >
131
165
) ;
@@ -135,35 +169,90 @@ const styles = StyleSheet.create({
135
169
container : {
136
170
flex : 1 ,
137
171
backgroundColor : "#fff" ,
138
- alignItems : "center" ,
139
- justifyContent : "center" ,
140
172
} ,
141
- networkOption : {
142
- width : "100%" ,
173
+ content : {
174
+ flex : 1 ,
143
175
padding : 16 ,
144
- borderBottomWidth : 1 ,
145
- borderBottomColor : "#eee" ,
176
+ } ,
177
+ networkOption : {
178
+ backgroundColor : "#F8F9FC" ,
179
+ borderRadius : 12 ,
180
+ marginBottom : 16 ,
181
+ padding : 20 ,
182
+ shadowColor : "#000" ,
183
+ shadowOffset : {
184
+ width : 0 ,
185
+ height : 2 ,
186
+ } ,
187
+ shadowOpacity : 0.1 ,
188
+ shadowRadius : 3 ,
189
+ elevation : 3 ,
190
+ borderWidth : 2 ,
191
+ borderColor : "transparent" ,
192
+ } ,
193
+ networkOptionSelected : {
194
+ borderColor : "#007AFF" ,
195
+ backgroundColor : "#F0F7FF" ,
146
196
} ,
147
197
networkInfo : {
148
198
alignItems : "center" ,
149
199
} ,
150
200
networkTitle : {
151
- fontSize : 18 ,
152
- fontWeight : "bold " ,
201
+ fontSize : 20 ,
202
+ fontWeight : "600 " ,
153
203
marginBottom : 8 ,
204
+ color : "#000" ,
154
205
} ,
155
206
networkDescription : {
156
207
textAlign : "center" ,
157
208
color : "#666" ,
158
209
marginBottom : 8 ,
210
+ lineHeight : 20 ,
159
211
} ,
160
212
selectedText : {
161
213
color : "#007AFF" ,
162
- fontWeight : "500" ,
214
+ fontWeight : "600" ,
215
+ marginTop : 4 ,
163
216
} ,
164
217
loadingText : {
165
218
marginTop : 16 ,
166
219
fontSize : 16 ,
167
220
color : "#666" ,
221
+ textAlign : "center" ,
222
+ } ,
223
+ buttonContainer : {
224
+ padding : 16 ,
225
+ paddingBottom : 32 ,
226
+ } ,
227
+ modalOverlay : {
228
+ flex : 1 ,
229
+ backgroundColor : "rgba(0, 0, 0, 0.5)" ,
230
+ justifyContent : "center" ,
231
+ alignItems : "center" ,
232
+ } ,
233
+ modalContent : {
234
+ backgroundColor : "#fff" ,
235
+ borderRadius : 12 ,
236
+ padding : 24 ,
237
+ width : "90%" ,
238
+ maxWidth : 400 ,
239
+ alignItems : "center" ,
240
+ } ,
241
+ modalTitle : {
242
+ fontSize : 20 ,
243
+ fontWeight : "600" ,
244
+ marginBottom : 16 ,
245
+ textAlign : "center" ,
246
+ } ,
247
+ modalText : {
248
+ fontSize : 16 ,
249
+ color : "#666" ,
250
+ textAlign : "center" ,
251
+ marginBottom : 24 ,
252
+ lineHeight : 22 ,
253
+ } ,
254
+ modalButtons : {
255
+ width : "100%" ,
256
+ gap : 12 ,
168
257
} ,
169
258
} ) ;
0 commit comments