dev
dart 266 lines 9.27 KB
Raw
1 import 'package:cake_wallet/view_model/bridge/bridge_receiving_wallet_option.dart';
2 import 'package:cake_wallet/generated/i18n.dart';
3 import 'package:cake_wallet/new-ui/pages/bridge/bridge_confirm_sheet.dart';
4 import 'package:cake_wallet/new-ui/pages/bridge/bridge_receive_address_input_page.dart';
5 import 'package:cake_wallet/new-ui/widgets/keyboard_hide_overlay.dart';
6 import 'package:cake_wallet/new-ui/widgets/receive_page/receive_top_bar.dart';
7 import 'package:cake_wallet/src/widgets/cake_image_widget.dart';
8 import 'package:cake_wallet/src/widgets/new_list_row/list_Item_style_wrapper.dart';
9 import 'package:cake_wallet/view_model/bridge/bridge_view_model.dart';
10 import 'package:flutter/material.dart';
11 import 'package:flutter_mobx/flutter_mobx.dart';
12 import 'package:modal_bottom_sheet/modal_bottom_sheet.dart';
13
14 class BridgeReceivingWalletPage extends StatefulWidget {
15 const BridgeReceivingWalletPage(this.bridgeViewModel);
16
17 final BridgeViewModel bridgeViewModel;
18
19 @override
20 State<BridgeReceivingWalletPage> createState() => _BridgeReceivingWalletPageState();
21 }
22
23 class _BridgeReceivingWalletPageState extends State<BridgeReceivingWalletPage> {
24 BridgeViewModel get bridgeViewModel => widget.bridgeViewModel;
25
26 @override
27 void initState() {
28 super.initState();
29 bridgeViewModel.loadReceivingWalletOptions();
30 }
31
32 @override
33 Widget build(BuildContext context) {
34 return KeyboardHideOverlay(
35 unfocusOnTap: true,
36 child: Container(
37 decoration: BoxDecoration(
38 color: Theme.of(context).colorScheme.surface,
39 borderRadius: const BorderRadius.vertical(top: Radius.circular(16)),
40 ),
41 child: Column(
42 children: [
43 ModalTopBar(
44 title: 'Receiving Wallet',
45 leadingIcon: const Icon(Icons.arrow_back_ios_new, size: 18),
46 leadingSemanticLabel: S.of(context).seed_alert_back,
47 onLeadingPressed: () => Navigator.of(context).pop(),
48 ),
49 const SizedBox(height: 48),
50 Expanded(
51 child: SafeArea(
52 child: Padding(
53 padding: const EdgeInsets.symmetric(horizontal: 18),
54 child: Observer(
55 builder: (_) {
56 final chain = bridgeViewModel.destinationChainInfo;
57
58 final chainName = chain?.name ?? '';
59
60 return Column(
61 crossAxisAlignment: CrossAxisAlignment.stretch,
62 children: [
63 const SizedBox(height: 8),
64 Center(
65 child: CakeImageWidget(
66 borderRadius: 8,
67 imageUrl: chainName.isNotEmpty
68 ? 'assets/new-ui/crypto_full_icons/${chainName.toLowerCase()}.svg'
69 : null,
70 width: 72,
71 height: 72,
72 ),
73 ),
74 const SizedBox(height: 20),
75 Text(
76 'Select a $chainName wallet or address to send '
77 'the bridged USDT0 to.',
78 textAlign: TextAlign.center,
79 style: Theme.of(context).textTheme.bodyMedium?.copyWith(
80 fontWeight: FontWeight.w400,
81 fontSize: 14,
82 letterSpacing: -0.07,
83 color: Theme.of(context).colorScheme.onSurfaceVariant,
84 ),
85 ),
86 const SizedBox(height: 24),
87 if (bridgeViewModel.isBridgeReceivingWalletListLoading)
88 const Expanded(
89 child: Center(
90 child: CircularProgressIndicator(),
91 ),
92 )
93 else
94 Expanded(
95 child: ListView(
96 padding: const EdgeInsets.only(bottom: 16),
97 children: _receivingListRows(context),
98 ),
99 ),
100 ],
101 );
102 },
103 ),
104 ),
105 ),
106 ),
107 ],
108 ),
109 ),
110 );
111 }
112
113 List<Widget> _receivingListRows(BuildContext context) {
114 final options = bridgeViewModel.bridgeReceivingWalletOptions;
115 final rows = <Widget>[];
116
117 for (int i = 0; i < options.length; i++) {
118 final option = options[i];
119
120 if (i > 0) rows.add(const SizedBox(height: 12));
121
122 rows.add(
123 _BridgeReceivingWalletRow(
124 option: option,
125 onTap: () {
126 bridgeViewModel.setRecipientAddress(option.address, destWalletName: option.name);
127
128 showMaterialModalBottomSheet<void>(
129 context: context,
130 backgroundColor: Colors.transparent,
131 builder: (ctx) => BridgeConfirmSheet(bridgeViewModel),
132 );
133 },
134 ),
135 );
136 }
137
138 if (options.isNotEmpty) rows.add(const SizedBox(height: 12));
139
140 rows.add(
141 ListItemStyleWrapper(
142 isFirstInSection: true,
143 isLastInSection: true,
144 height: 48,
145 contentPadding: const EdgeInsets.all(12),
146 onTap: () {
147 showMaterialModalBottomSheet(
148 context: context,
149 backgroundColor: Colors.transparent,
150 builder: (ctx) => BridgeReceiveAddressInputPage(bridgeViewModel: bridgeViewModel),
151 );
152 },
153 builder: (ctx, textStyle, _) {
154 final scheme = Theme.of(ctx).colorScheme;
155 return Row(
156 children: [
157 Icon(
158 Icons.edit_outlined,
159 size: 24,
160 color: scheme.primary,
161 ),
162 const SizedBox(width: 12),
163 Expanded(
164 child: Text(
165 'Input an Address',
166 style: textStyle.copyWith(
167 color: scheme.primary,
168 fontSize: 15,
169 fontWeight: FontWeight.w500,
170 letterSpacing: -0.3,
171 ),
172 ),
173 ),
174 ],
175 );
176 },
177 ),
178 );
179
180 return rows;
181 }
182 }
183
184 class _BridgeReceivingWalletRow extends StatelessWidget {
185 const _BridgeReceivingWalletRow({
186 required this.option,
187 required this.onTap,
188 });
189
190 final BridgeReceivingWalletOption option;
191 final VoidCallback onTap;
192
193 @override
194 Widget build(BuildContext context) {
195 final hasGroupRow = option.groupLabel != null;
196
197 return ListItemStyleWrapper(
198 onTap: onTap,
199 isFirstInSection: true,
200 isLastInSection: true,
201 height: hasGroupRow ? 62.0 : 48.0,
202 builder: (ctx, textStyle, labelStyle) {
203 return Row(
204 crossAxisAlignment: CrossAxisAlignment.center,
205 children: [
206 Expanded(
207 child: Column(
208 mainAxisAlignment: MainAxisAlignment.center,
209 crossAxisAlignment: CrossAxisAlignment.start,
210 children: [
211 Text(
212 option.name,
213 style: textStyle.copyWith(letterSpacing: -0.07),
214 maxLines: 1,
215 overflow: TextOverflow.ellipsis,
216 ),
217 if (hasGroupRow) ...[
218 const SizedBox(height: 4),
219 Row(
220 children: [
221 Icon(
222 Icons.account_balance_wallet_outlined,
223 size: 16,
224 color: Theme.of(ctx).colorScheme.onSurfaceVariant,
225 ),
226 const SizedBox(width: 6),
227 Expanded(
228 child: Text(
229 option.groupLabel!,
230 style: labelStyle.copyWith(
231 fontSize: 12,
232 letterSpacing: -0.06,
233 color: Theme.of(ctx).colorScheme.onSurfaceVariant,
234 ),
235 maxLines: 1,
236 overflow: TextOverflow.ellipsis,
237 ),
238 ),
239 if (option.isCurrent) ...[
240 const SizedBox(width: 8),
241 Text(
242 'Current',
243 style: textStyle.copyWith(
244 fontSize: 12,
245 color: Theme.of(ctx).colorScheme.primary,
246 letterSpacing: -0.06,
247 ),
248 ),
249 ],
250 ],
251 ),
252 ],
253 ],
254 ),
255 ),
256 CakeImageWidget(
257 imageUrl: 'assets/new-ui/arrow_forward.svg',
258 height: 16,
259 color: Theme.of(ctx).colorScheme.onSurfaceVariant,
260 ),
261 ],
262 );
263 },
264 );
265 }
266 }