dev
dart 196 lines 7.24 KB
Raw
1 import "package:cake_wallet/generated/i18n.dart";
2 import "package:cake_wallet/new-ui/widgets/currency_picker/currency_picker_args.dart";
3 import "package:cake_wallet/new-ui/widgets/currency_picker/currency_picker_list_container.dart";
4 import "package:cake_wallet/new-ui/widgets/currency_picker/currency_picker_row.dart";
5 import "package:cake_wallet/new-ui/widgets/currency_picker/currency_picker_search_field.dart";
6 import "package:cake_wallet/new-ui/widgets/currency_picker/picker_section_header.dart";
7 import "package:cake_wallet/reactions/wallet_utils.dart";
8 import "package:cw_core/crypto_currency.dart";
9 import "package:cw_core/currency_for_wallet_type.dart";
10 import "package:cw_core/wallet_type.dart";
11 import "package:flutter/material.dart";
12
13 class SingleNetworkCurrencyPicker extends StatefulWidget {
14 const SingleNetworkCurrencyPicker({
15 required this.args,
16 super.key,
17 });
18
19 final CurrencyPickerArgs args;
20
21 @override
22 State<SingleNetworkCurrencyPicker> createState() => _SingleNetworkCurrencyPickerState();
23 }
24
25 class _SingleNetworkCurrencyPickerState extends State<SingleNetworkCurrencyPicker> {
26 CurrencyPickerArgs get _args => widget.args;
27 WalletType get _network => _args.filterByNetwork!;
28 final TextEditingController _searchController = TextEditingController();
29
30 @override
31 void initState() {
32 super.initState();
33 _searchController.addListener(() => setState(() {}));
34 }
35
36 @override
37 void dispose() {
38 _searchController.dispose();
39 super.dispose();
40 }
41
42 void _selectCurrency(CryptoCurrency currency) {
43 _args.onSelected(currency);
44 Navigator.of(context).maybePop();
45 }
46
47 CurrencyPickerBalance? _balanceFor(CryptoCurrency c) => balanceForAsset(_args.balanceByAsset, c);
48
49 double _fiatValueFor(CryptoCurrency c) => _balanceFor(c)?.fiatValue ?? 0;
50
51 @override
52 Widget build(BuildContext context) {
53 final native = walletTypeToCryptoCurrency(_network);
54 final query = _searchController.text.trim();
55 final tokens = _args.items
56 .where(
57 (c) =>
58 c != native &&
59 cryptoCurrencyOrTokenToWalletType(c) == _network &&
60 currencyMatchesQuery(c, query),
61 )
62 .toList();
63
64 final insertOrder = {for (var i = 0; i < tokens.length; i++) tokens[i]: i};
65 tokens.sort((a, b) {
66 final av = _fiatValueFor(a);
67 final bv = _fiatValueFor(b);
68 if (bv != av) {
69 return bv.compareTo(av);
70 }
71 return (insertOrder[a] ?? 0).compareTo(insertOrder[b] ?? 0);
72 });
73 final nativeMatches = currencyMatchesQuery(native, query);
74
75 final showSectionHeaders = _network != WalletType.bitcoin;
76
77 return Column(
78 mainAxisSize: MainAxisSize.max,
79 children: [
80 Expanded(
81 child: (nativeMatches || tokens.isNotEmpty)
82 ? ListView(
83 padding: const EdgeInsets.fromLTRB(16, 8, 16, 16),
84 children: showSectionHeaders
85 ? [
86 if (nativeMatches) ...[
87 PickerSectionHeader(title: S.of(context).picker_section_gas_token),
88 CurrencyPickerListContainer(
89 rows: [
90 CurrencyPickerRow(
91 currency: native,
92 isSelected: _args.selected == native,
93 trailing: _BalanceTrailing(balance: _balanceFor(native)),
94 onTap: () => _selectCurrency(native),
95 ),
96 ],
97 ),
98 const SizedBox(height: 16),
99 ],
100 if (tokens.isNotEmpty) ...[
101 PickerSectionHeader(
102 title: S
103 .of(context)
104 .picker_section_tokens_standard(tokenStandardFor(_network)),
105 ),
106 CurrencyPickerListContainer(
107 rows: [
108 for (final t in tokens)
109 CurrencyPickerRow(
110 currency: t,
111 isSelected: _args.selected == t,
112 trailing: _BalanceTrailing(balance: _balanceFor(t)),
113 onTap: () => _selectCurrency(t),
114 ),
115 ],
116 ),
117 ],
118 ]
119 : [
120 CurrencyPickerListContainer(
121 rows: [
122 if (nativeMatches)
123 CurrencyPickerRow(
124 currency: native,
125 isSelected: _args.selected == native,
126 trailing: _BalanceTrailing(balance: _balanceFor(native)),
127 onTap: () => _selectCurrency(native),
128 ),
129 for (final t in tokens)
130 CurrencyPickerRow(
131 currency: t,
132 isSelected: _args.selected == t,
133 trailing: _BalanceTrailing(balance: _balanceFor(t)),
134 onTap: () => _selectCurrency(t),
135 ),
136 ],
137 ),
138 ],
139 )
140 : Center(
141 child: Padding(
142 padding: const EdgeInsets.all(24),
143 child: Text(
144 S.of(context).picker_no_matches,
145 textAlign: TextAlign.center,
146 style: Theme.of(context).textTheme.bodyMedium?.copyWith(
147 color: Theme.of(context).colorScheme.onSurfaceVariant,
148 ),
149 ),
150 ),
151 ),
152 ),
153 CurrencyPickerSearchField(
154 controller: _searchController,
155 hintText: S.of(context).search,
156 ),
157 ],
158 );
159 }
160 }
161
162 class _BalanceTrailing extends StatelessWidget {
163 const _BalanceTrailing({required this.balance});
164
165 final CurrencyPickerBalance? balance;
166
167 @override
168 Widget build(BuildContext context) {
169 final colors = Theme.of(context).colorScheme;
170 final amount = balance?.amount ?? "—";
171 final fiat = balance?.fiat;
172 return Column(
173 crossAxisAlignment: CrossAxisAlignment.end,
174 mainAxisSize: MainAxisSize.min,
175 children: [
176 Text(
177 amount,
178 style: Theme.of(context).textTheme.bodyMedium?.copyWith(
179 fontWeight: FontWeight.w500,
180 ),
181 ),
182 if (fiat != null && fiat.isNotEmpty)
183 Padding(
184 padding: const EdgeInsets.only(top: 2),
185 child: Text(
186 fiat,
187 style: Theme.of(context).textTheme.bodySmall?.copyWith(
188 fontWeight: FontWeight.w400,
189 color: colors.onSurfaceVariant,
190 ),
191 ),
192 ),
193 ],
194 );
195 }
196 }