CW-427-Refactor-wallet-type-selection-UI (#968)
* refactor the asset selection screen * formatting * ui fixes * remove Ethereum related
Serhii committed
Jul 10, 2023 at 18:12 UTC
c01321008b33431b5e88ce0d0c75ad73e4fdc0a8
5 files changed
+122
-116
cw_core/lib/wallet_type.dart
+5
-5
@@ -26,7 +26,7 @@ enum WalletType {
26
litecoin,
27
28
@HiveField(4)
29
- haven
29
+ haven,
30
}
31
32
int serializeToInt(WalletType type) {
@@ -77,13 +77,13 @@ String walletTypeToString(WalletType type) {
77
String walletTypeToDisplayName(WalletType type) {
78
switch (type) {
79
case WalletType.monero:
80
- return 'Monero';
80
+ return 'Monero (XMR)';
81
case WalletType.bitcoin:
82
- return 'Bitcoin (Electrum)';
82
+ return 'Bitcoin (BTC)';
83
case WalletType.litecoin:
84
- return 'Litecoin (Electrum)';
84
+ return 'Litecoin (LTC)';
85
case WalletType.haven:
86
- return 'Haven';
86
+ return 'Haven (XHV)';
87
default:
88
return '';
89
}
lib/src/screens/new_wallet/new_wallet_type_page.dart
+69
-78
@@ -1,13 +1,14 @@
1
-import 'package:cake_wallet/utils/responsive_layout_util.dart';
2
-import 'package:cw_core/wallet_type.dart';
3
-import 'package:cake_wallet/themes/theme_base.dart';
4
-import 'package:flutter/material.dart';
1
import 'package:cake_wallet/generated/i18n.dart';
2
import 'package:cake_wallet/src/screens/base_page.dart';
3
+import 'package:cake_wallet/src/screens/new_wallet/widgets/select_button.dart';
4
import 'package:cake_wallet/src/widgets/primary_button.dart';
5
import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
9
-import 'package:cake_wallet/src/screens/new_wallet/widgets/select_button.dart';
6
+import 'package:cake_wallet/src/widgets/search_bar_widget.dart';
7
+import 'package:cake_wallet/themes/theme_base.dart';
8
+import 'package:cake_wallet/utils/responsive_layout_util.dart';
9
import 'package:cake_wallet/wallet_types.g.dart';
10
+import 'package:cw_core/wallet_type.dart';
11
+import 'package:flutter/material.dart';
12
13
class NewWalletTypePage extends BasePage {
14
NewWalletTypePage({required this.onTypeSelected});
@@ -40,92 +41,82 @@ class WalletTypeFormState extends State<WalletTypeForm> {
41
42
static const aspectRatioImage = 1.22;
43
43
- final moneroIcon = Image.asset('assets/images/monero_logo.png', height: 24, width: 24);
44
- final bitcoinIcon = Image.asset('assets/images/bitcoin.png', height: 24, width: 24);
45
- final litecoinIcon = Image.asset('assets/images/litecoin_icon.png', height: 24, width: 24);
46
- final walletTypeImage = Image.asset('assets/images/wallet_type.png');
47
- final walletTypeLightImage = Image.asset('assets/images/wallet_type_light.png');
48
- final havenIcon = Image.asset('assets/images/haven_logo.png', height: 24, width: 24);
44
+ final TextEditingController searchController = TextEditingController();
45
46
WalletType? selected;
47
List<WalletType> types;
48
+ List<WalletType> filteredTypes = [];
49
50
@override
51
void initState() {
55
- types = availableWalletTypes;
52
+ types = filteredTypes = availableWalletTypes;
53
super.initState();
54
+
55
+ searchController.addListener(() {
56
+ setState(() {
57
+ filteredTypes = List.from(types.where((type) => walletTypeToDisplayName(type)
58
+ .toLowerCase()
59
+ .contains(searchController.text.toLowerCase())));
60
+ return;
61
+ });
62
+ });
63
}
64
65
@override
66
Widget build(BuildContext context) {
61
- return ScrollableWithBottomSection(
62
- contentPadding: EdgeInsets.only(left: 24, right: 24, bottom: 24),
63
- content: Center(
67
+ return Center(
68
child: ConstrainedBox(
65
- constraints: BoxConstraints(maxWidth: ResponsiveLayoutUtil.kDesktopMaxWidthConstraint),
66
- child: Column(
67
- crossAxisAlignment: CrossAxisAlignment.center,
68
- children: <Widget>[
69
- Padding(
70
- padding: EdgeInsets.only(left: 12, right: 12),
71
- child: AspectRatio(
72
- aspectRatio: aspectRatioImage,
73
- child: FittedBox(child: widget.walletImage, fit: BoxFit.fill)),
74
- ),
75
- Padding(
76
- padding: EdgeInsets.only(top: 48),
77
- child: Text(
78
- S.of(context).choose_wallet_currency,
79
- textAlign: TextAlign.center,
80
- style: TextStyle(
81
- fontSize: 16,
82
- fontWeight: FontWeight.w500,
83
- color: Theme.of(context)
84
- .primaryTextTheme!
85
- .titleLarge!
86
- .color!),
69
+ constraints: BoxConstraints(maxWidth: ResponsiveLayoutUtil.kDesktopMaxWidthConstraint),
70
+ child: Column(
71
+ children: [
72
+ Padding(
73
+ padding: EdgeInsets.only(top: 48),
74
+ child: Text(
75
+ S.of(context).choose_wallet_currency,
76
+ textAlign: TextAlign.center,
77
+ style: TextStyle(
78
+ fontSize: 16,
79
+ fontWeight: FontWeight.w500,
80
+ color: Theme.of(context).primaryTextTheme!.titleLarge!.color!),
81
+ ),
82
),
88
- ),
89
- ...types.map((type) => Padding(
90
- padding: EdgeInsets.only(top: 24),
91
- child: SelectButton(
92
- image: _iconFor(type),
93
- text: walletTypeToDisplayName(type),
94
- isSelected: selected == type,
95
- onTap: () => setState(() => selected = type)),
96
- ))
97
- ],
98
- ),
99
- ),
100
- ),
101
- bottomSectionPadding: EdgeInsets.only(left: 24, right: 24, bottom: 24),
102
- bottomSection: PrimaryButton(
103
- onPressed: () => onTypeSelected(),
104
- text: S.of(context).seed_language_next,
105
- color: Theme.of(context)
106
- .accentTextTheme!
107
- .bodyLarge!
108
- .color!,
109
- textColor: Colors.white,
110
- isDisabled: selected == null,
111
- ),
112
- );
113
- }
114
-
115
- Image _iconFor(WalletType type) {
116
- switch (type) {
117
- case WalletType.monero:
118
- return moneroIcon;
119
- case WalletType.bitcoin:
120
- return bitcoinIcon;
121
- case WalletType.litecoin:
122
- return litecoinIcon;
123
- case WalletType.haven:
124
- return havenIcon;
125
- default:
126
- throw Exception(
127
- '_iconFor: Incorrect Wallet Type. Cannot find icon for Wallet Type: ${type.toString()}');
128
- }
83
+ Padding(
84
+ padding: const EdgeInsets.fromLTRB(24, 24, 24, 12),
85
+ child: SearchBarWidget(searchController: searchController, borderRadius: 24),
86
+ ),
87
+ Expanded(
88
+ child: ScrollableWithBottomSection(
89
+ contentPadding: EdgeInsets.only(left: 24, right: 24, bottom: 24),
90
+ content: Column(
91
+ crossAxisAlignment: CrossAxisAlignment.center,
92
+ children: <Widget>[
93
+ ...filteredTypes.map((type) => Padding(
94
+ padding: EdgeInsets.only(top: 12),
95
+ child: SelectButton(
96
+ image: Image.asset(
97
+ walletTypeToCryptoCurrency(type).iconPath ?? '',
98
+ height: 24,
99
+ width: 24),
100
+ text: walletTypeToDisplayName(type),
101
+ showTrailingIcon: false,
102
+ height: 54,
103
+ isSelected: selected == type,
104
+ onTap: () => setState(() => selected = type)),
105
+ ))
106
+ ],
107
+ ),
108
+ bottomSectionPadding: EdgeInsets.only(left: 24, right: 24, bottom: 24),
109
+ bottomSection: PrimaryButton(
110
+ onPressed: () => onTypeSelected(),
111
+ text: S.of(context).seed_language_next,
112
+ color: Theme.of(context).accentTextTheme!.bodyLarge!.color!,
113
+ textColor: Colors.white,
114
+ isDisabled: selected == null,
115
+ ),
116
+ ),
117
+ ),
118
+ ],
119
+ )));
120
}
121
122
Future<void> onTypeSelected() async {
lib/src/screens/new_wallet/widgets/select_button.dart
+6
-2
@@ -6,12 +6,16 @@ class SelectButton extends StatelessWidget {
6
required this.onTap,
7
this.image,
8
this.isSelected = false,
9
+ this.showTrailingIcon = true,
10
+ this.height = 60,
11
});
12
13
final Image? image;
14
final String text;
15
final bool isSelected;
16
final VoidCallback onTap;
17
+ final bool showTrailingIcon;
18
+ final double height;
19
20
@override
21
Widget build(BuildContext context) {
@@ -44,7 +48,7 @@ class SelectButton extends StatelessWidget {
48
onTap: onTap,
49
child: Container(
50
width: double.infinity,
47
- height: 60,
51
+ height: height,
52
padding: EdgeInsets.only(left: 30, right: 30),
53
alignment: Alignment.center,
54
decoration: BoxDecoration(
@@ -76,7 +80,7 @@ class SelectButton extends StatelessWidget {
80
)
81
],
82
),
79
- selectArrowImage
83
+ if (showTrailingIcon) selectArrowImage
84
],
85
),
86
),
lib/src/widgets/picker.dart
+2
-31
@@ -1,5 +1,6 @@
1
// ignore_for_file: deprecated_member_use
2
3
+import 'package:cake_wallet/src/widgets/search_bar_widget.dart';
4
import 'package:cake_wallet/utils/responsive_layout_util.dart';
5
import 'package:flutter/material.dart';
6
import 'package:cw_core/currency.dart';
@@ -158,37 +159,7 @@ class _PickerState<Item> extends State<Picker<Item>> {
159
if (widget.hintText != null)
160
Padding(
161
padding: const EdgeInsets.all(16),
161
- child: TextFormField(
162
- controller: searchController,
163
- style: TextStyle(
164
- color: Theme.of(context)
165
- .primaryTextTheme!
166
- .titleLarge!
167
- .color!),
168
- decoration: InputDecoration(
169
- hintText: widget.hintText,
170
- prefixIcon:
171
- Image.asset("assets/images/search_icon.png"),
172
- filled: true,
173
- fillColor: Theme.of(context)
174
- .accentTextTheme!
175
- .displaySmall!
176
- .color!,
177
- alignLabelWithHint: false,
178
- contentPadding: const EdgeInsets.symmetric(
179
- vertical: 4, horizontal: 16),
180
- enabledBorder: OutlineInputBorder(
181
- borderRadius: BorderRadius.circular(14),
182
- borderSide: const BorderSide(
183
- color: Colors.transparent,
184
- )),
185
- focusedBorder: OutlineInputBorder(
186
- borderRadius: BorderRadius.circular(14),
187
- borderSide: const BorderSide(
188
- color: Colors.transparent,
189
- )),
190
- ),
191
- ),
162
+ child: SearchBarWidget(searchController: searchController),
163
),
164
Divider(
165
color: Theme.of(context)
lib/src/widgets/search_bar_widget.dart
new
+40
@@ -0,0 +1,40 @@
1
+import 'package:flutter/material.dart';
2
+import 'package:cake_wallet/generated/i18n.dart';
3
+
4
+class SearchBarWidget extends StatelessWidget {
5
+ const SearchBarWidget({
6
+ required this.searchController,
7
+ this.hintText,
8
+ this.borderRadius = 14,
9
+ });
10
+
11
+ final TextEditingController searchController;
12
+ final String? hintText;
13
+ final double borderRadius;
14
+
15
+ @override
16
+ Widget build(BuildContext context) {
17
+ return TextFormField(
18
+ controller: searchController,
19
+ style: TextStyle(color: Theme.of(context).primaryTextTheme!.titleLarge!.color!),
20
+ decoration: InputDecoration(
21
+ hintText: hintText ?? S.of(context).search_currency,
22
+ prefixIcon: Image.asset("assets/images/search_icon.png"),
23
+ filled: true,
24
+ fillColor: Theme.of(context).accentTextTheme!.displaySmall!.color!,
25
+ alignLabelWithHint: false,
26
+ contentPadding: const EdgeInsets.symmetric(vertical: 4, horizontal: 16),
27
+ enabledBorder: OutlineInputBorder(
28
+ borderRadius: BorderRadius.circular(borderRadius),
29
+ borderSide: const BorderSide(
30
+ color: Colors.transparent,
31
+ )),
32
+ focusedBorder: OutlineInputBorder(
33
+ borderRadius: BorderRadius.circular(borderRadius),
34
+ borderSide: const BorderSide(
35
+ color: Colors.transparent,
36
+ )),
37
+ ),
38
+ );
39
+ }
40
+}