dev
dart 240 lines 9.85 KB
Raw
1 import 'package:cake_wallet/core/wallet_name_validator.dart';
2 import 'package:cake_wallet/src/widgets/cake_image_widget.dart';
3 import 'package:cw_core/generate_name.dart';
4 import 'package:cake_wallet/generated/i18n.dart';
5 import 'package:cake_wallet/src/screens/base_page.dart';
6 import 'package:cake_wallet/src/screens/new_wallet/widgets/select_button.dart';
7 import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
8 import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
9 import 'package:cake_wallet/src/widgets/primary_button.dart';
10 import 'package:cake_wallet/src/widgets/scrollable_with_bottom_section.dart';
11 import 'package:cake_wallet/utils/responsive_layout_util.dart';
12 import 'package:cake_wallet/utils/show_pop_up.dart';
13 import 'package:cake_wallet/view_model/wallet_hardware_restore_view_model.dart';
14 import 'package:cw_core/currency_for_wallet_type.dart';
15 import 'package:flutter/material.dart';
16 import 'package:flutter_mobx/flutter_mobx.dart';
17 import 'package:mobx/mobx.dart';
18
19 class SelectHardwareWalletAccountPage extends BasePage {
20 SelectHardwareWalletAccountPage(this._walletHardwareRestoreVM);
21
22 final WalletHardwareRestoreViewModel _walletHardwareRestoreVM;
23
24 @override
25 String get title => S.current.restore_title_from_hardware_wallet;
26
27 @override
28 Widget body(BuildContext context) => SelectHardwareWalletAccountForm(_walletHardwareRestoreVM);
29 }
30
31 class SelectHardwareWalletAccountForm extends StatefulWidget {
32 SelectHardwareWalletAccountForm(this._walletHardwareRestoreVM);
33
34 final WalletHardwareRestoreViewModel _walletHardwareRestoreVM;
35
36 @override
37 _SelectHardwareWalletAccountFormState createState() =>
38 _SelectHardwareWalletAccountFormState(_walletHardwareRestoreVM);
39 }
40
41 class _SelectHardwareWalletAccountFormState extends State<SelectHardwareWalletAccountForm> {
42 _SelectHardwareWalletAccountFormState(this._walletHardwareRestoreVM)
43 : _formKey = GlobalKey<FormState>(),
44 _controller = TextEditingController();
45
46 final GlobalKey<FormState> _formKey;
47 final WalletHardwareRestoreViewModel _walletHardwareRestoreVM;
48 final TextEditingController _controller;
49
50 @override
51 void initState() {
52 super.initState();
53 _setEffects(context);
54 if (_walletHardwareRestoreVM.availableAccounts.length == 0) _loadMoreAccounts();
55 }
56
57 @override
58 Widget build(BuildContext context) {
59 return Padding(
60 padding: EdgeInsets.only(top: 24),
61 child: ScrollableWithBottomSection(
62 contentPadding: EdgeInsets.only(left: 24, right: 24, bottom: 24),
63 content: Center(
64 child: ConstrainedBox(
65 constraints:
66 BoxConstraints(maxWidth: ResponsiveLayoutUtilBase.kDesktopMaxWidthConstraint),
67 child: Column(
68 crossAxisAlignment: CrossAxisAlignment.center,
69 children: [
70 Padding(
71 padding: EdgeInsets.only(top: 0),
72 child: Form(
73 key: _formKey,
74 child: Stack(
75 alignment: Alignment.centerRight,
76 children: [
77 BaseTextFormField(
78 onChanged: (value) => _walletHardwareRestoreVM.name = value,
79 controller: _controller,
80 textStyle: Theme.of(context).textTheme.bodyMedium!.copyWith(
81 fontSize: 20.0,
82 fontWeight: FontWeight.w600,
83 ),
84 placeholderTextStyle: Theme.of(context).textTheme.bodyMedium!.copyWith(
85 fontSize: 18.0,
86 fontWeight: FontWeight.w500,
87 color: Theme.of(context).colorScheme.onSurfaceVariant,
88 ),
89 hintText: S.of(context).wallet_name,
90 // enabledBorder: UnderlineInputBorder(
91 // borderSide: BorderSide(
92 // color: Theme.of(context).colorScheme.outline,
93 // width: 100,
94 // ),
95 // ),
96 suffixIcon: Semantics(
97 label: S.of(context).generate_name,
98 child: IconButton(
99 onPressed: () async {
100 final rName = await generateName();
101 FocusManager.instance.primaryFocus?.unfocus();
102
103 setState(() {
104 _controller.text = rName;
105 _walletHardwareRestoreVM.name = rName;
106 _controller.selection = TextSelection.fromPosition(
107 TextPosition(offset: _controller.text.length));
108 });
109 },
110 icon: Container(
111 padding: const EdgeInsets.all(8),
112 decoration: BoxDecoration(
113 borderRadius: BorderRadius.circular(6.0),
114 color: Theme.of(context).colorScheme.surfaceContainerHighest,
115 ),
116 width: 34,
117 height: 34,
118 child: Image.asset(
119 'assets/images/refresh_icon.png',
120 color: Theme.of(context).colorScheme.primary,
121 ),
122 ),
123 ),
124 ),
125 validator: WalletNameValidator(),
126 ),
127 ],
128 ),
129 ),
130 ),
131 Padding(
132 padding: EdgeInsets.only(top: 20),
133 child: Container(
134 width: double.infinity,
135 child: Text(
136 S.of(context).select_hw_account_below,
137 style: Theme.of(context).textTheme.bodyMedium!.copyWith(
138 fontSize: 16,
139 fontWeight: FontWeight.w500,
140 ),
141 ),
142 ),
143 ),
144 Observer(
145 builder: (context) => Column(
146 children: _walletHardwareRestoreVM.availableAccounts.map((acc) {
147 final address = acc.address;
148 return Padding(
149 padding: EdgeInsets.only(top: 10),
150 child: SelectButton(
151 image: CakeImageWidget(
152 imageUrl: getCryptoCurrencyIconForWalletListItem(
153 _walletHardwareRestoreVM.type),
154 height: 24,
155 width: 24,
156 ),
157 text:
158 "${acc.accountIndex} - ${address.substring(0, 6)}...${address.substring(address.length - 6)}",
159 showTrailingIcon: false,
160 height: 54,
161 isSelected: _walletHardwareRestoreVM.selectedAccount == acc,
162 onTap: () =>
163 setState(() => _walletHardwareRestoreVM.selectedAccount = acc),
164 ),
165 );
166 }).toList(),
167 ),
168 ),
169 Padding(
170 padding: EdgeInsets.only(top: 10),
171 child: Observer(
172 builder: (context) {
173 return LoadingPrimaryButton(
174 onPressed: _loadMoreAccounts,
175 text: S.of(context).load_more,
176 color: Theme.of(context).colorScheme.surfaceContainer,
177 textColor: Theme.of(context).colorScheme.onSecondaryContainer,
178 isLoading: _walletHardwareRestoreVM.isLoadingMoreAccounts,
179 );
180 },
181 ),
182 ),
183 ],
184 ),
185 ),
186 ),
187 bottomSectionPadding: EdgeInsets.all(24),
188 bottomSection: Observer(
189 builder: (context) {
190 return LoadingPrimaryButton(
191 onPressed: _confirmForm,
192 text: S.of(context).seed_language_next,
193 color: Theme.of(context).colorScheme.primary,
194 textColor: Theme.of(context).colorScheme.onPrimary,
195 isDisabled: _walletHardwareRestoreVM.name.isEmpty,
196 );
197 },
198 ),
199 ),
200 );
201 }
202
203 Future<void> _loadMoreAccounts() async {
204 _walletHardwareRestoreVM.isLoadingMoreAccounts = true;
205 _walletHardwareRestoreVM.getNextAvailableAccounts(5);
206 }
207
208 Future<void> _confirmForm() async {
209 await _walletHardwareRestoreVM.create();
210 }
211
212 bool _effectsInstalled = false;
213
214 void _setEffects(BuildContext context) {
215 if (_effectsInstalled) return;
216
217 reaction((_) => _walletHardwareRestoreVM.error, (String? error) {
218 if (error != null) {
219 if (error == S.current.ledger_connection_error) Navigator.of(context).pop();
220
221 WidgetsBinding.instance.addPostFrameCallback((_) {
222 showPopUp<void>(
223 context: context,
224 builder: (BuildContext context) {
225 return AlertWithOneAction(
226 alertTitle: S.of(context).error,
227 alertContent: error,
228 buttonText: S.of(context).ok,
229 buttonAction: () {
230 _walletHardwareRestoreVM.error = null;
231 Navigator.of(context).pop();
232 });
233 });
234 });
235 }
236 });
237
238 _effectsInstalled = true;
239 }
240 }