Cw 09 implement picker screen with ability to search (#250)
* Added new picker screen with search bar and currency icons
Serhii committed
Mar 31, 2022 at 17:16 UTC
1cd90cf57d0149bd72f1ed77c5ed1bc320720421
40 files changed
+578
-279
assets/images/ada_icon.png
Binary files /dev/null and b/assets/images/ada_icon.png differ
assets/images/bch_icon.png
Binary files /dev/null and b/assets/images/bch_icon.png differ
assets/images/bitcoin_icon.png
Binary files /dev/null and b/assets/images/bitcoin_icon.png differ
assets/images/bnb_icon.png
Binary files /dev/null and b/assets/images/bnb_icon.png differ
assets/images/btc.png
Binary files /dev/null and b/assets/images/btc.png differ
assets/images/dai_icon.png
Binary files /dev/null and b/assets/images/dai_icon.png differ
assets/images/dash_icon.png
Binary files /dev/null and b/assets/images/dash_icon.png differ
assets/images/eos_icon.png
Binary files /dev/null and b/assets/images/eos_icon.png differ
assets/images/eth_icon.png
Binary files /dev/null and b/assets/images/eth_icon.png differ
assets/images/litecoin-ltc_icon.png
Binary files /dev/null and b/assets/images/litecoin-ltc_icon.png differ
assets/images/litecoin_img.png
Binary files /dev/null and b/assets/images/litecoin_img.png differ
assets/images/monero_icon.png
Binary files /dev/null and b/assets/images/monero_icon.png differ
assets/images/trx_icon.png
Binary files /dev/null and b/assets/images/trx_icon.png differ
assets/images/usdt_icon.png
Binary files /dev/null and b/assets/images/usdt_icon.png differ
assets/images/usdterc20_icon.png
Binary files /dev/null and b/assets/images/usdterc20_icon.png differ
assets/images/usdterc_icon.png
Binary files /dev/null and b/assets/images/usdterc_icon.png differ
assets/images/xlm_icon.png
Binary files /dev/null and b/assets/images/xlm_icon.png differ
assets/images/xrp_icon.png
Binary files /dev/null and b/assets/images/xrp_icon.png differ
lib/src/screens/exchange/exchange_page.dart
+2
-2
@@ -206,8 +206,8 @@ class ExchangePage extends BasePage {
206
onCurrencySelected: (currency) {
207
// FIXME: need to move it into view model
208
if (currency == CryptoCurrency.xmr &&
209
- exchangeViewModel.wallet.type ==
210
- WalletType.bitcoin) {
209
+ exchangeViewModel.wallet.type !=
210
+ WalletType.monero) {
211
showPopUp<void>(
212
context: context,
213
builder: (dialogContext) {
lib/src/screens/exchange/widgets/currency_picker.dart
+179
-145
@@ -1,176 +1,210 @@
1
import 'dart:ui';
2
+import 'package:cake_wallet/generated/i18n.dart';
3
import 'package:cake_wallet/palette.dart';
4
+import 'package:cake_wallet/src/screens/exchange/widgets/currency_utils.dart';
5
+import 'package:cake_wallet/src/screens/exchange/widgets/picker_item.dart';
6
import 'package:flutter/cupertino.dart';
7
import 'package:flutter/material.dart';
8
import 'package:cw_core/crypto_currency.dart';
9
import 'package:cake_wallet/src/widgets/alert_background.dart';
7
-import 'package:cake_wallet/src/widgets/alert_close_button.dart';
8
-import 'package:cake_wallet/src/widgets/cake_scrollbar.dart';
10
+import 'currency_picker_widget.dart';
11
12
class CurrencyPicker extends StatefulWidget {
11
- CurrencyPicker({
12
- @required this.selectedAtIndex,
13
- @required this.items,
14
- @required this.title,
15
- @required this.onItemSelected,
16
- });
13
+ CurrencyPicker(
14
+ {@required this.selectedAtIndex,
15
+ @required this.items,
16
+ @required this.title,
17
+ @required this.onItemSelected,
18
+ this.isMoneroWallet = false,
19
+ this.isConvertFrom = false});
20
18
- final int selectedAtIndex;
21
+ int selectedAtIndex;
22
final List<CryptoCurrency> items;
23
final String title;
24
final Function(CryptoCurrency) onItemSelected;
25
+ final bool isMoneroWallet;
26
+ final bool isConvertFrom;
27
28
@override
24
- CurrencyPickerState createState() => CurrencyPickerState(
25
- selectedAtIndex,
26
- items,
27
- title,
28
- onItemSelected
29
- );
29
+ CurrencyPickerState createState() => CurrencyPickerState(items);
30
}
31
32
class CurrencyPickerState extends State<CurrencyPicker> {
33
- CurrencyPickerState(
34
- this.selectedAtIndex,
35
- this.items,
36
- this.title,
37
- this.onItemSelected): itemsCount = items.length;
33
+ CurrencyPickerState(this.items)
34
+ : isSearchBarActive = false,
35
+ textFieldValue = '',
36
+ subPickerItemsList = [],
37
+ appBarTextStyle = TextStyle(
38
+ fontSize: 20,
39
+ fontFamily: 'Lato',
40
+ backgroundColor: Colors.transparent,
41
+ color: Colors.white);
42
39
- final int selectedAtIndex;
40
- final List<CryptoCurrency> items;
41
- final String title;
42
- final Function(CryptoCurrency) onItemSelected;
43
+ @override
44
+ void initState() {
45
+ pickerItemsList = CryptoCurrency.all
46
+ .map((CryptoCurrency cur) => PickerItem<CryptoCurrency>(cur,
47
+ title: CurrencyUtils.titleForCurrency(cur),
48
+ iconPath: CurrencyUtils.iconPathForCurrency(cur),
49
+ tag: CurrencyUtils.tagForCurrency(cur),
50
+ description: CurrencyUtils.descriptionForCurrency(cur)))
51
+ .toList();
52
+ cleanSubPickerItemsList();
53
+ super.initState();
54
+ }
55
44
- final closeButton = Image.asset('assets/images/close.png',
45
- color: Palette.darkBlueCraiola,
46
- );
47
- final int crossAxisCount = 3;
48
- final int maxNumberItemsInAlert = 12;
49
- final int itemsCount;
50
- final double backgroundHeight = 280;
51
- final double thumbHeight = 72;
52
- ScrollController controller = ScrollController();
53
- double fromTop = 0;
56
+ List<PickerItem<CryptoCurrency>> pickerItemsList;
57
+ List<CryptoCurrency> items;
58
+ bool isSearchBarActive;
59
+ String textFieldValue;
60
+ List<PickerItem<CryptoCurrency>> subPickerItemsList;
61
+ TextStyle appBarTextStyle;
62
55
- @override
56
- Widget build(BuildContext context) {
57
- controller.addListener(() {
58
- fromTop = controller.hasClients
59
- ? (controller.offset / controller.position.maxScrollExtent * (backgroundHeight - thumbHeight))
60
- : 0;
61
- setState(() {});
63
+ void cleanSubPickerItemsList() {
64
+ subPickerItemsList = pickerItemsList
65
+ .where((element) => items.contains(element.original))
66
+ .toList();
67
+ }
68
+
69
+ void currencySearchBySubstring(
70
+ String subString, List<PickerItem<CryptoCurrency>> list) {
71
+ setState(() {
72
+ if (subString.isNotEmpty) {
73
+ subPickerItemsList = subPickerItemsList
74
+ .where((element) =>
75
+ element.title.contains(subString.toUpperCase()) ||
76
+ element.description.contains(subString.toLowerCase()))
77
+ .toList();
78
+ } else {
79
+ cleanSubPickerItemsList();
80
+ }
81
});
82
+ }
83
84
+ @override
85
+ Widget build(BuildContext context) {
86
return AlertBackground(
65
- child: Stack(
66
- alignment: Alignment.center,
67
- children: <Widget>[
68
- Column(
69
- mainAxisSize: MainAxisSize.min,
70
- children: <Widget>[
71
- Container(
72
- padding: EdgeInsets.only(left: 24, right: 24),
73
- child: Text(
74
- title,
75
- textAlign: TextAlign.center,
76
- style: TextStyle(
77
- fontSize: 18,
78
- fontFamily: 'Lato',
79
- fontWeight: FontWeight.bold,
80
- decoration: TextDecoration.none,
81
- color: Colors.white
87
+ child: SafeArea(
88
+ child: Scaffold(
89
+ resizeToAvoidBottomInset: false,
90
+ backgroundColor: Colors.transparent,
91
+ body: Column(
92
+ children: [
93
+ Padding(
94
+ padding: EdgeInsets.symmetric(horizontal: 26.0, vertical: 0),
95
+ child: Row(
96
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
97
+ children: [
98
+ isSearchBarActive
99
+ ? Expanded(
100
+ child: Row(
101
+ mainAxisAlignment:
102
+ MainAxisAlignment.spaceBetween,
103
+ children: [
104
+ InkWell(
105
+ child: Text(
106
+ S.of(context).cancel,
107
+ style: appBarTextStyle,
108
+ ),
109
+ onTap: () {
110
+ setState(() {
111
+ isSearchBarActive = false;
112
+ textFieldValue = '';
113
+ cleanSubPickerItemsList();
114
+ });
115
+ }),
116
+ Container(
117
+ width: 100.0,
118
+ child: CupertinoTextField(
119
+ autofocus: true,
120
+ placeholder:
121
+ S.of(context).search + '...',
122
+ placeholderStyle: appBarTextStyle,
123
+ decoration: BoxDecoration(
124
+ color: Colors.transparent),
125
+ cursorColor: Colors.white,
126
+ cursorHeight: 23.0,
127
+ style: appBarTextStyle,
128
+ onChanged: (value) {
129
+ this.textFieldValue = value;
130
+ cleanSubPickerItemsList();
131
+ currencySearchBySubstring(
132
+ textFieldValue,
133
+ subPickerItemsList);
134
+ }),
135
+ )
136
+ ],
137
+ ),
138
+ )
139
+ : Text(
140
+ widget.title,
141
+ style: appBarTextStyle,
142
+ ),
143
+ IconButton(
144
+ splashRadius: 23,
145
+ icon: Icon(Icons.search, color: Colors.white),
146
+ onPressed: () {
147
+ setState(() {
148
+ isSearchBarActive = true;
149
+ });
150
+ },
151
+ )
152
+ ]),
153
+ ),
154
+ Expanded(
155
+ flex: 12,
156
+ child: Padding(
157
+ padding: const EdgeInsets.symmetric(
158
+ horizontal: 26.0, vertical: 26.0),
159
+ child: Container(
160
+ child: CurrencyPickerWidget(
161
+ crossAxisCount: 2,
162
+ selectedAtIndex: widget.selectedAtIndex,
163
+ itemsCount: subPickerItemsList.length,
164
+ pickerItemsList: subPickerItemsList,
165
+ pickListItem: (int index) {
166
+ setState(() {
167
+ widget.selectedAtIndex = index;
168
+ });
169
+ widget
170
+ .onItemSelected(subPickerItemsList[index].original);
171
+ if (widget.isConvertFrom &&
172
+ !widget.isMoneroWallet &&
173
+ (subPickerItemsList[index].original ==
174
+ CryptoCurrency.xmr)) {
175
+ } else {
176
+ Navigator.of(context).pop();
177
+ }
178
+ },
179
),
180
),
181
),
85
- Padding(
86
- padding: EdgeInsets.only(top: 24),
87
- child: GestureDetector(
88
- onTap: () => null,
89
- child: ClipRRect(
90
- borderRadius: BorderRadius.all(Radius.circular(14)),
91
- child: Container(
92
- height: 320,
93
- width: 300,
94
- color: Theme.of(context).accentTextTheme.title.backgroundColor,
95
- child: Stack(
96
- alignment: Alignment.center,
97
- children: <Widget>[
98
- GridView.count(
99
- padding: EdgeInsets.all(0),
100
- controller: controller,
101
- crossAxisCount: crossAxisCount,
102
- childAspectRatio: 1.25,
103
- crossAxisSpacing: 1,
104
- mainAxisSpacing: 1,
105
- children: List.generate(
106
- itemsCount
107
- + getExtraEmptyTilesCount(crossAxisCount, itemsCount),
108
- (index) {
109
-
110
- if (index >= itemsCount) {
111
- return Container(
112
- color: Theme.of(context).accentTextTheme.title.color,
113
- );
114
- }
115
-
116
- final item = items[index];
117
- final isItemSelected = index == selectedAtIndex;
118
-
119
- final color = isItemSelected
120
- ? Theme.of(context).textTheme.body2.color
121
- : Theme.of(context).accentTextTheme.title.color;
122
- final textColor = isItemSelected
123
- ? Palette.blueCraiola
124
- : Theme.of(context).primaryTextTheme.title.color;
125
-
126
- return GestureDetector(
127
- onTap: () {
128
- if (onItemSelected == null) {
129
- return;
130
- }
131
- Navigator.of(context).pop();
132
- onItemSelected(item);
133
- },
134
- child: Container(
135
- color: color,
136
- child: Center(
137
- child: Text(
138
- item.toString(),
139
- style: TextStyle(
140
- fontSize: 15,
141
- fontFamily: 'Lato',
142
- fontWeight: FontWeight.w600,
143
- decoration: TextDecoration.none,
144
- color: textColor
145
- ),
146
- ),
147
- ),
148
- ),
149
- );
150
- })
151
- ),
152
- if (itemsCount > maxNumberItemsInAlert)
153
- CakeScrollbar(
154
- backgroundHeight: backgroundHeight,
155
- thumbHeight: thumbHeight,
156
- fromTop: fromTop
157
- )
158
- ],
159
- )
182
+ ),
183
+ Expanded(
184
+ flex: 2,
185
+ child: Container(
186
+ width: 42.0,
187
+ alignment: Alignment.topCenter,
188
+ child: FittedBox(
189
+ child: FloatingActionButton(
190
+ elevation: 0,
191
+ backgroundColor: Colors.white,
192
+ onPressed: () {
193
+ Navigator.of(context).pop();
194
+ },
195
+ child: Icon(
196
+ Icons.close_outlined,
197
+ color: Palette.darkBlueCraiola,
198
+ size: 30.0,
199
),
200
),
201
),
163
- )
164
- ],
165
- ),
166
- AlertCloseButton(image: closeButton)
167
- ],
168
- )
202
+ ),
203
+ ),
204
+ ],
205
+ ),
206
+ ),
207
+ ),
208
);
209
}
171
-
172
- int getExtraEmptyTilesCount(int crossAxisCount, int itemsCount) {
173
- final int tilesInNewRowCount = itemsCount % crossAxisCount;
174
- return tilesInNewRowCount == 0 ? 0 : crossAxisCount - tilesInNewRowCount;
175
- }
176
-}
\ No newline at end of file
210
+}
lib/src/screens/exchange/widgets/currency_picker_item_widget.dart
new
+93
@@ -0,0 +1,93 @@
1
+import 'package:flutter/material.dart';
2
+import 'package:cake_wallet/palette.dart';
3
+
4
+class PickerItemWidget extends StatelessWidget {
5
+ const PickerItemWidget(
6
+ {this.iconPath, this.title, this.isSelected, this.tag, this.onTap});
7
+
8
+ final String iconPath;
9
+ final String title;
10
+ final bool isSelected;
11
+ final String tag;
12
+ final void Function() onTap;
13
+
14
+ @override
15
+ Widget build(BuildContext context) {
16
+ return GestureDetector(
17
+ onTap: onTap,
18
+ child: Container(
19
+ color: isSelected
20
+ ? Theme.of(context).textTheme.bodyText1.color
21
+ : Theme.of(context).accentTextTheme.headline6.color,
22
+ child: Center(
23
+ child: Padding(
24
+ padding: const EdgeInsets.all(8.0),
25
+ child: Row(
26
+ mainAxisAlignment: MainAxisAlignment.center,
27
+ children: [
28
+ Expanded(
29
+ child: Container(
30
+ child: Image.asset(
31
+ iconPath,
32
+ height: 32.0,
33
+ width: 32.0,
34
+ ),
35
+ ),
36
+ ),
37
+ Expanded(
38
+ child: Stack(
39
+ clipBehavior: Clip.none,
40
+ alignment: Alignment.centerLeft,
41
+ children: [
42
+ Text(
43
+ title,
44
+ style: TextStyle(
45
+ color: isSelected
46
+ ? Palette.blueCraiola
47
+ : Theme.of(context).primaryTextTheme.title.color,
48
+ fontSize: 18.0,
49
+ fontFamily: 'Lato',
50
+ ),
51
+ ),
52
+ tag != null
53
+ ? Positioned(
54
+ top: -20.0,
55
+ right: 7.0,
56
+ child: Container(
57
+ width: 35.0,
58
+ height: 18.0,
59
+ child: Center(
60
+ child: Text(
61
+ tag,
62
+ style: TextStyle(
63
+ fontSize: 7.0,
64
+ fontFamily: 'Lato',
65
+ color: Theme.of(context)
66
+ .textTheme
67
+ .body1
68
+ .color),
69
+ ),
70
+ ),
71
+ decoration: BoxDecoration(
72
+ borderRadius: BorderRadius.circular(6.0),
73
+ //border: Border.all(color: ),
74
+ color: Theme.of(context)
75
+ .textTheme
76
+ .body1
77
+ .decorationColor,
78
+ ),
79
+ ),
80
+ )
81
+ : Container(),
82
+ ],
83
+ ),
84
+ ),
85
+ ],
86
+ ),
87
+ ),
88
+ ),
89
+ ),
90
+ );
91
+ ;
92
+ }
93
+}
lib/src/screens/exchange/widgets/currency_picker_widget.dart
new
+61
@@ -0,0 +1,61 @@
1
+import 'package:flutter/material.dart';
2
+import 'package:cw_core/crypto_currency.dart';
3
+import 'picker_item.dart';
4
+import 'currency_picker_item_widget.dart';
5
+
6
+class CurrencyPickerWidget extends StatelessWidget {
7
+ const CurrencyPickerWidget({
8
+ @required this.crossAxisCount,
9
+ @required this.selectedAtIndex,
10
+ @required this.itemsCount,
11
+ @required this.pickerItemsList,
12
+ @required this.pickListItem,
13
+ });
14
+
15
+ final int crossAxisCount;
16
+ final int selectedAtIndex;
17
+ final int itemsCount;
18
+ final Function pickListItem;
19
+ final List<PickerItem<CryptoCurrency>> pickerItemsList;
20
+
21
+ @override
22
+ Widget build(BuildContext context) {
23
+ return LayoutBuilder(
24
+ builder: (BuildContext context, BoxConstraints constraints) {
25
+ return Container(
26
+ decoration: BoxDecoration(
27
+ color: Theme.of(context).accentTextTheme.headline6.backgroundColor,
28
+ borderRadius: BorderRadius.circular(14.0),
29
+ ),
30
+ child: ClipRRect(
31
+ borderRadius: BorderRadius.circular(14.0),
32
+ child: Scrollbar(
33
+ showTrackOnHover: true,
34
+ isAlwaysShown: true,
35
+ thickness: 6.0,
36
+ radius: Radius.circular(3),
37
+ child: GridView.builder(
38
+ gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
39
+ crossAxisCount: crossAxisCount,
40
+ crossAxisSpacing: 1,
41
+ mainAxisExtent: constraints.maxHeight / 8,
42
+ mainAxisSpacing: 1),
43
+ itemCount: pickerItemsList.length,
44
+ itemBuilder: (BuildContext ctx, index) {
45
+ return PickerItemWidget(
46
+ onTap: () {
47
+ pickListItem(index);
48
+ },
49
+ title: pickerItemsList[index].title,
50
+ iconPath: pickerItemsList[index].iconPath,
51
+ isSelected: index == selectedAtIndex,
52
+ tag: pickerItemsList[index].tag,
53
+ );
54
+ }),
55
+ ),
56
+ ),
57
+ );
58
+ },
59
+ );
60
+ }
61
+}
lib/src/screens/exchange/widgets/currency_utils.dart
new
+99
@@ -0,0 +1,99 @@
1
+import 'package:cw_core/crypto_currency.dart';
2
+
3
+class CurrencyUtils {
4
+ static String tagForCurrency(CryptoCurrency cur) {
5
+ switch (cur) {
6
+ case CryptoCurrency.bnb:
7
+ return 'BEP2';
8
+ case CryptoCurrency.dai:
9
+ return 'ETH';
10
+ case CryptoCurrency.usdt:
11
+ return 'OMNI';
12
+ case CryptoCurrency.usdterc20:
13
+ return 'ETH';
14
+ default:
15
+ return null;
16
+ }
17
+ }
18
+
19
+ static String iconPathForCurrency(CryptoCurrency cur) {
20
+ switch (cur) {
21
+ case CryptoCurrency.xmr:
22
+ return 'assets/images/monero_icon.png';
23
+ case CryptoCurrency.ada:
24
+ return 'assets/images/ada_icon.png';
25
+ case CryptoCurrency.bch:
26
+ return 'assets/images/bch_icon.png';
27
+ case CryptoCurrency.bnb:
28
+ return 'assets/images/bnb_icon.png';
29
+ case CryptoCurrency.btc:
30
+ return 'assets/images/btc.png';
31
+ case CryptoCurrency.dai:
32
+ return 'assets/images/dai_icon.png';
33
+ case CryptoCurrency.dash:
34
+ return 'assets/images/dash_icon.png';
35
+ case CryptoCurrency.eos:
36
+ return 'assets/images/eos_icon.png';
37
+ case CryptoCurrency.eth:
38
+ return 'assets/images/eth_icon.png';
39
+ case CryptoCurrency.ltc:
40
+ return 'assets/images/litecoin-ltc_icon.png';
41
+ case CryptoCurrency.trx:
42
+ return 'assets/images/trx_icon.png';
43
+ case CryptoCurrency.usdt:
44
+ return 'assets/images/usdt_icon.png';
45
+ case CryptoCurrency.usdterc20:
46
+ return 'assets/images/usdterc20_icon.png';
47
+ case CryptoCurrency.xlm:
48
+ return 'assets/images/xlm_icon.png';
49
+ case CryptoCurrency.xrp:
50
+ return 'assets/images/xrp_icon.png';
51
+ default:
52
+ return null;
53
+ }
54
+ }
55
+
56
+ static String titleForCurrency(CryptoCurrency cur) {
57
+ switch (cur) {
58
+ case CryptoCurrency.bnb:
59
+ return 'BNB';
60
+ case CryptoCurrency.usdterc20:
61
+ return 'USDT';
62
+ default:
63
+ return cur.title;
64
+ }
65
+ }
66
+
67
+ static String descriptionForCurrency(CryptoCurrency cur) {
68
+ switch (cur) {
69
+ case CryptoCurrency.xmr:
70
+ return 'monero';
71
+ case CryptoCurrency.ada:
72
+ return 'cardano';
73
+ case CryptoCurrency.bch:
74
+ return 'bitcoin cash';
75
+ case CryptoCurrency.bnb:
76
+ return 'binance bep2';
77
+ case CryptoCurrency.btc:
78
+ return 'bitcoin';
79
+ case CryptoCurrency.dai:
80
+ return 'dai eth';
81
+ case CryptoCurrency.eth:
82
+ return 'ethereum';
83
+ case CryptoCurrency.ltc:
84
+ return 'litecoin';
85
+ case CryptoCurrency.trx:
86
+ return 'tron';
87
+ case CryptoCurrency.usdt:
88
+ return 'usdt omni';
89
+ case CryptoCurrency.usdterc20:
90
+ return 'tether ERC20 eth';
91
+ case CryptoCurrency.xlm:
92
+ return 'lumens';
93
+ case CryptoCurrency.xrp:
94
+ return 'ripple';
95
+ default:
96
+ return cur.title;
97
+ }
98
+ }
99
+}
lib/src/screens/exchange/widgets/exchange_card.dart
+112
-115
@@ -306,126 +306,121 @@ class ExchangeCardState extends State<ExchangeCard> {
306
? Padding(
307
padding: EdgeInsets.only(top: 20),
308
child: AddressTextField(
309
- focusNode: widget.addressFocusNode,
310
- controller: addressController,
311
- placeholder: widget.hasRefundAddress
312
- ? S.of(context).refund_address
313
- : null,
314
- options: [
315
- AddressTextFieldOption.paste,
316
- AddressTextFieldOption.qrCode,
317
- AddressTextFieldOption.addressBook,
318
- ],
319
- isBorderExist: false,
320
- textStyle: TextStyle(
321
- fontSize: 16,
322
- fontWeight: FontWeight.w600,
323
- color: Colors.white),
324
- hintStyle: TextStyle(
325
- fontSize: 16,
326
- fontWeight: FontWeight.w600,
327
- color: Theme.of(context)
328
- .accentTextTheme
329
- .display4
330
- .decorationColor),
331
- buttonColor: widget.addressButtonsColor,
332
- validator: widget.addressTextFieldValidator,
333
- onPushPasteButton: widget.onPushPasteButton,
334
- onPushAddressBookButton: widget.onPushAddressBookButton
335
- ),
309
+ focusNode: widget.addressFocusNode,
310
+ controller: addressController,
311
+ placeholder: widget.hasRefundAddress
312
+ ? S.of(context).refund_address
313
+ : null,
314
+ options: [
315
+ AddressTextFieldOption.paste,
316
+ AddressTextFieldOption.qrCode,
317
+ AddressTextFieldOption.addressBook,
318
+ ],
319
+ isBorderExist: false,
320
+ textStyle: TextStyle(
321
+ fontSize: 16,
322
+ fontWeight: FontWeight.w600,
323
+ color: Colors.white),
324
+ hintStyle: TextStyle(
325
+ fontSize: 16,
326
+ fontWeight: FontWeight.w600,
327
+ color: Theme.of(context)
328
+ .accentTextTheme
329
+ .display4
330
+ .decorationColor),
331
+ buttonColor: widget.addressButtonsColor,
332
+ validator: widget.addressTextFieldValidator,
333
+ onPushPasteButton: widget.onPushPasteButton,
334
+ onPushAddressBookButton: widget.onPushAddressBookButton),
335
)
336
: Padding(
337
padding: EdgeInsets.only(top: 10),
338
child: Builder(
340
- builder: (context) => Stack(
341
- children: <Widget> [
342
- BaseTextFormField(
343
- controller: addressController,
344
- readOnly: true,
345
- borderColor: Colors.transparent,
346
- suffixIcon: SizedBox(
347
- width: _isMoneroWallet ? 80 : 36
348
- ),
349
- textStyle: TextStyle(
350
- fontSize: 16,
351
- fontWeight: FontWeight.w600,
352
- color: Colors.white),
353
- validator: widget.addressTextFieldValidator
354
- ),
355
- Positioned(
356
- top: 2,
357
- right: 0,
358
- child: SizedBox(
359
- width: _isMoneroWallet ? 80 : 36,
360
- child: Row(
361
- children: <Widget>[
362
- if (_isMoneroWallet) Padding(
363
- padding: EdgeInsets.only(left: 10),
364
- child: Container(
365
- width: 34,
366
- height: 34,
367
- padding: EdgeInsets.only(top: 0),
368
- child: InkWell(
369
- onTap: () async {
370
- final contact = await Navigator
371
- .of(context, rootNavigator: true)
372
- .pushNamed(
373
- Routes.pickerAddressBook);
339
+ builder: (context) => Stack(children: <Widget>[
340
+ BaseTextFormField(
341
+ controller: addressController,
342
+ readOnly: true,
343
+ borderColor: Colors.transparent,
344
+ suffixIcon:
345
+ SizedBox(width: _isMoneroWallet ? 80 : 36),
346
+ textStyle: TextStyle(
347
+ fontSize: 16,
348
+ fontWeight: FontWeight.w600,
349
+ color: Colors.white),
350
+ validator: widget.addressTextFieldValidator),
351
+ Positioned(
352
+ top: 2,
353
+ right: 0,
354
+ child: SizedBox(
355
+ width: _isMoneroWallet ? 80 : 36,
356
+ child: Row(children: <Widget>[
357
+ if (_isMoneroWallet)
358
+ Padding(
359
+ padding: EdgeInsets.only(left: 10),
360
+ child: Container(
361
+ width: 34,
362
+ height: 34,
363
+ padding: EdgeInsets.only(top: 0),
364
+ child: InkWell(
365
+ onTap: () async {
366
+ final contact =
367
+ await Navigator.of(context,
368
+ rootNavigator: true)
369
+ .pushNamed(Routes
370
+ .pickerAddressBook);
371
375
- if (contact is ContactBase &&
376
- contact.address != null) {
377
- setState(() =>
378
- addressController.text =
379
- contact.address);
380
- widget.onPushAddressBookButton
381
- ?.call(context);
382
- }
383
- },
384
- child: Container(
385
- padding: EdgeInsets.all(8),
386
- decoration: BoxDecoration(
387
- color: widget
388
- .addressButtonsColor,
389
- borderRadius: BorderRadius
390
- .all(Radius.circular(6))),
391
- child: Image.asset(
392
- 'assets/images/open_book.png',
393
- color: Theme.of(context)
394
- .primaryTextTheme
395
- .display1
396
- .decorationColor,
397
- )),
398
- )),
399
- ),
400
- Padding(
401
- padding: EdgeInsets.only(left: 2),
402
- child: Container(
403
- width: 34,
404
- height: 34,
405
- padding: EdgeInsets.only(top: 0),
406
- child: InkWell(
407
- onTap: () {
408
- Clipboard.setData(
409
- ClipboardData(
410
- text: addressController.text));
411
- showBar<void>(
412
- context, S.of(context)
413
- .copied_to_clipboard);
414
- },
415
- child: Container(
416
- padding: EdgeInsets
417
- .fromLTRB(8, 8, 0, 8),
418
- color: Colors.transparent,
419
- child: copyImage),
420
- ))
421
- )
422
- ]
423
- )
424
- )
425
- )
426
- ]
427
- )
428
- ),
372
+ if (contact is ContactBase &&
373
+ contact.address != null) {
374
+ setState(() =>
375
+ addressController.text =
376
+ contact.address);
377
+ widget.onPushAddressBookButton
378
+ ?.call(context);
379
+ }
380
+ },
381
+ child: Container(
382
+ padding: EdgeInsets.all(8),
383
+ decoration: BoxDecoration(
384
+ color: widget
385
+ .addressButtonsColor,
386
+ borderRadius:
387
+ BorderRadius.all(
388
+ Radius.circular(
389
+ 6))),
390
+ child: Image.asset(
391
+ 'assets/images/open_book.png',
392
+ color: Theme.of(context)
393
+ .primaryTextTheme
394
+ .display1
395
+ .decorationColor,
396
+ )),
397
+ )),
398
+ ),
399
+ Padding(
400
+ padding: EdgeInsets.only(left: 2),
401
+ child: Container(
402
+ width: 34,
403
+ height: 34,
404
+ padding: EdgeInsets.only(top: 0),
405
+ child: InkWell(
406
+ onTap: () {
407
+ Clipboard.setData(ClipboardData(
408
+ text: addressController
409
+ .text));
410
+ showBar<void>(
411
+ context,
412
+ S
413
+ .of(context)
414
+ .copied_to_clipboard);
415
+ },
416
+ child: Container(
417
+ padding: EdgeInsets.fromLTRB(
418
+ 8, 8, 0, 8),
419
+ color: Colors.transparent,
420
+ child: copyImage),
421
+ )))
422
+ ])))
423
+ ])),
424
),
425
]),
426
);
@@ -437,6 +432,8 @@ class ExchangeCardState extends State<ExchangeCard> {
432
selectedAtIndex: widget.currencies.indexOf(_selectedCurrency),
433
items: widget.currencies,
434
title: S.of(context).change_currency,
435
+ isMoneroWallet: _isMoneroWallet,
436
+ isConvertFrom: widget.hasRefundAddress,
437
onItemSelected: (CryptoCurrency item) =>
438
widget.onCurrencySelected != null
439
? widget.onCurrencySelected(item)
lib/src/screens/exchange/widgets/picker_item.dart
new
+10
@@ -0,0 +1,10 @@
1
+class PickerItem<T> {
2
+ PickerItem(this.original,
3
+ {this.title, this.iconPath, this.tag, this.description});
4
+
5
+ final String title;
6
+ final String iconPath;
7
+ final String tag;
8
+ final T original;
9
+ final String description;
10
+}
lib/src/widgets/standard_list.dart
+8
-3
@@ -69,18 +69,22 @@ class SectionHeaderListRow extends StatelessWidget {
69
}
70
71
class StandardListSeparator extends StatelessWidget {
72
- StandardListSeparator({this.padding});
72
+
73
+ StandardListSeparator({this.padding,this.height=1});
74
75
final EdgeInsets padding;
76
+ final double height;
77
+
78
+
79
80
@override
81
Widget build(BuildContext context) {
82
return Container(
79
- height: 1,
83
+ height: height,
84
padding: padding,
85
color: Theme.of(context).backgroundColor,
86
child: Container(
83
- height: 1,
87
+ height: height,
88
color: Theme.of(context).primaryTextTheme.title.backgroundColor));
89
}
90
}
@@ -98,6 +102,7 @@ class StandardList extends StatelessWidget {
102
StandardListSeparator(padding: EdgeInsets.only(left: 24)),
103
itemCount: itemCount,
104
itemBuilder: itemBuilder);
105
+
106
}
107
}
108
res/values/strings_de.arb
+1
-1
@@ -524,7 +524,7 @@
524
"third_intro_title" : "Yat spielt gut mit anderen",
525
"third_intro_content" : "Yats leben auch außerhalb von Cake Wallet. Jede Wallet-Adresse auf der Welt kann durch ein Yat ersetzt werden!",
526
"learn_more" : "Erfahren Sie mehr",
527
-
527
+ "search": "Suche",
528
"new_template" : "neue Vorlage",
529
"electrum_address_disclaimer": "Wir generieren jedes Mal neue Adressen, wenn Sie eine verwenden, aber vorherige Adressen funktionieren weiterhin"
530
}
res/values/strings_en.arb
+1
-1
@@ -524,7 +524,7 @@
524
"third_intro_title" : "Yat plays nicely with others",
525
"third_intro_content" : "Yats live outside of Cake Wallet, too. Any wallet address on earth can be replaced with a Yat!",
526
"learn_more" : "Learn More",
527
-
527
+ "search": "Search",
528
"new_template" : "New Template",
529
"electrum_address_disclaimer": "We generate new addresses each time you use one, but previous addresses continue to work"
530
}
\ No newline at end of file
res/values/strings_es.arb
+1
-1
@@ -524,7 +524,7 @@
524
"third_intro_title" : "Yat juega muy bien con otras",
525
"third_intro_content" : "Los Yats también viven fuera de Cake Wallet. Cualquier dirección de billetera en la tierra se puede reemplazar con un Yat!",
526
"learn_more" : "Aprende más",
527
-
527
+ "search": "Búsqueda",
528
"new_template" : "Nueva plantilla",
529
"electrum_address_disclaimer": "Generamos nuevas direcciones cada vez que usa una, pero las direcciones anteriores siguen funcionando"
530
}
\ No newline at end of file
res/values/strings_hi.arb
+1
-1
@@ -524,7 +524,7 @@
524
"third_intro_title" : "Yat दूसरों के साथ अच्छा खेलता है",
525
"third_intro_content" : "Yats Cake Wallet के बाहर भी रहता है। धरती पर किसी भी वॉलेट पते को Yat से बदला जा सकता है!",
526
"learn_more" : "और अधिक जानें",
527
-
527
+ "search": "खोज",
528
"new_template" : "नया टेम्पलेट",
529
"electrum_address_disclaimer": "हर बार जब आप एक का उपयोग करते हैं तो हम नए पते उत्पन्न करते हैं, लेकिन पिछले पते काम करना जारी रखते हैं"
530
}
\ No newline at end of file
res/values/strings_hr.arb
+1
-1
@@ -524,7 +524,7 @@
524
"third_intro_title" : "Yat se lijepo igra s drugima",
525
"third_intro_content" : "Yats žive i izvan Cake Wallet -a. Bilo koja adresa novčanika na svijetu može se zamijeniti Yat!",
526
"learn_more" : "Saznajte više",
527
-
527
+ "search": "Traži",
528
"new_template" : "novi predložak",
529
"electrum_address_disclaimer": "Minden egyes alkalommal új címeket generálunk, de a korábbi címek továbbra is működnek"
530
}
\ No newline at end of file
res/values/strings_it.arb
+1
-1
@@ -524,7 +524,7 @@
524
"third_intro_title" : "Yat gioca bene con gli altri",
525
"third_intro_content" : "Anche Yats vive fuori da Cake Wallet. Qualsiasi indirizzo di portafoglio sulla terra può essere sostituito con un Yat!",
526
"learn_more" : "Impara di più",
527
-
527
+ "search": "Ricerca",
528
"new_template" : "Nuovo modello",
529
"electrum_address_disclaimer": "Generiamo nuovi indirizzi ogni volta che ne utilizzi uno, ma gli indirizzi precedenti continuano a funzionare"
530
}
\ No newline at end of file
res/values/strings_ja.arb
+1
-1
@@ -524,7 +524,7 @@
524
"third_intro_title" : "Yatは他の人とうまく遊ぶ",
525
"third_intro_content" : "YatsはCakeWalletの外にも住んでいます。 地球上のどのウォレットアドレスもYatに置き換えることができます!",
526
"learn_more" : "もっと詳しく知る",
527
-
527
+ "search": "検索",
528
"new_template" : "新しいテンプレート",
529
"electrum_address_disclaimer": "使用するたびに新しいアドレスが生成されますが、以前のアドレスは引き続き機能します"
530
}
\ No newline at end of file
res/values/strings_ko.arb
+1
-1
@@ -524,7 +524,7 @@
524
"third_intro_title" : "Yat는 다른 사람들과 잘 놉니다.",
525
"third_intro_content" : "Yats는 Cake Wallet 밖에서도 살고 있습니다. 지구상의 모든 지갑 주소는 Yat!",
526
"learn_more" : "더 알아보기",
527
-
527
+ "search": "찾다",
528
"new_template" : "새 템플릿",
529
"electrum_address_disclaimer": "사용할 때마다 새 주소가 생성되지만 이전 주소는 계속 작동합니다."
530
}
\ No newline at end of file
res/values/strings_nl.arb
+1
-1
@@ -524,7 +524,7 @@
524
"third_intro_title" : "Yat speelt leuk met anderen",
525
"third_intro_content" : "Yats wonen ook buiten Cake Wallet. Elk portemonnee-adres op aarde kan worden vervangen door een Yat!",
526
"learn_more" : "Kom meer te weten",
527
-
527
+ "search": "Zoekopdracht",
528
"new_template" : "Nieuwe sjabloon",
529
"electrum_address_disclaimer": "We generate new addresses each time you use one, but previous addresses continue to work"
530
}
\ No newline at end of file
res/values/strings_pl.arb
+1
-1
@@ -527,7 +527,7 @@
527
"third_intro_title" : "Yat ładnie bawi się z innymi",
528
"third_intro_content" : "Yats mieszkają również poza Cake Wallet. Każdy adres portfela na ziemi można zastąpić Yat!",
529
"learn_more" : "Ucz się więcej",
530
-
530
+ "search": "Szukaj",
531
"new_template" : "Nowy szablon",
532
"electrum_address_disclaimer": "Za każdym razem, gdy korzystasz z jednego z nich, generujemy nowe adresy, ale poprzednie adresy nadal działają"
533
}
\ No newline at end of file
res/values/strings_pt.arb
+1
-1
@@ -524,7 +524,7 @@
524
"third_intro_title" : "Yat joga bem com os outros",
525
"third_intro_content" : "Yats também mora fora da Cake Wallet. Qualquer endereço de carteira na Terra pode ser substituído por um Yat!",
526
"learn_more" : "Saber mais",
527
-
527
+ "search": "Procurar",
528
"new_template" : "Novo modelo",
529
"electrum_address_disclaimer": "Geramos novos endereços cada vez que você usa um, mas os endereços anteriores continuam funcionando"
530
}
\ No newline at end of file
res/values/strings_ru.arb
+1
-1
@@ -524,7 +524,7 @@
524
"third_intro_title" : "Yat хорошо взаимодействует с другими",
525
"third_intro_content" : "Yat находятся за пределами Cake Wallet. Любой адрес кошелька на земле можно заменить на Yat!",
526
"learn_more" : "Узнать больше",
527
-
527
+ "search": "Поиск",
528
"new_template" : "Новый шаблон",
529
"electrum_address_disclaimer": "Мы генерируем новые адреса каждый раз, когда вы их используете, но предыдущие адреса продолжают работать."
530
}
\ No newline at end of file
res/values/strings_uk.arb
+1
-1
@@ -523,7 +523,7 @@
523
"third_intro_title" : "Yat добре взаємодіє з іншими",
524
"third_intro_content" : "Yat знаходиться за межами Cake Wallet. Будь-яку адресу гаманця на землі можна замінити на Yat!",
525
"learn_more" : "Дізнатися більше",
526
-
526
+ "search": "Пошук",
527
"new_template" : "Новий шаблон",
528
"electrum_address_disclaimer": "Ми створюємо нові адреси щоразу, коли ви використовуєте їх, але попередні адреси продовжують працювати"
529
}
\ No newline at end of file
res/values/strings_zh.arb
+1
-1
@@ -522,7 +522,7 @@
522
"third_intro_title" : "Yat 和別人玩得很好",
523
"third_intro_content" : "Yats 也住在 Cake Wallet 之外。 地球上任何一個錢包地址都可以用一個Yat來代替!",
524
"learn_more" : "了解更多",
525
-
525
+ "search": "搜索",
526
"new_template" : "新模板",
527
"electrum_address_disclaimer": "每次您使用一个地址时,我们都会生成新地址,但之前的地址仍然有效"
528
}
\ No newline at end of file