CWA-201 | added wallet tiles to wallet list page; added colors and images to wallet menu

Oleksandr Sobol committed Apr 23, 2020 at 21:36 UTC 07aaf7716711eecd1025b3a34ff1a09477caf582
11 files changed +286 -84
assets/images/2.0x/load.png
Binary files /dev/null and b/assets/images/2.0x/load.png differ
assets/images/2.0x/scanner.png
Binary files /dev/null and b/assets/images/2.0x/scanner.png differ
assets/images/2.0x/trash.png
Binary files /dev/null and b/assets/images/2.0x/trash.png differ
assets/images/3.0x/load.png
Binary files /dev/null and b/assets/images/3.0x/load.png differ
assets/images/3.0x/scanner.png
Binary files /dev/null and b/assets/images/3.0x/scanner.png differ
assets/images/3.0x/trash.png
Binary files /dev/null and b/assets/images/3.0x/trash.png differ
assets/images/load.png
Binary files /dev/null and b/assets/images/load.png differ
assets/images/scanner.png
Binary files /dev/null and b/assets/images/scanner.png differ
assets/images/trash.png
Binary files /dev/null and b/assets/images/trash.png differ
lib/src/screens/wallet_list/wallet_list_page.dart
+250 -84
@@ -6,22 +6,15 @@ import 'package:cake_wallet/routes.dart';
6 import 'package:cake_wallet/palette.dart';
7 import 'package:cake_wallet/generated/i18n.dart';
8 import 'package:cake_wallet/src/widgets/primary_button.dart';
9 -import 'package:cake_wallet/src/domain/common/wallet_description.dart';
9 import 'package:cake_wallet/src/screens/base_page.dart';
10 import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
11 import 'package:cake_wallet/src/stores/wallet_list/wallet_list_store.dart';
12 import 'package:cake_wallet/src/screens/wallet_list/wallet_menu.dart';
14 -import 'package:cake_wallet/src/widgets/picker.dart';
13
14 class WalletListPage extends BasePage {
17 - @override
18 - bool get isModalBackButton => true;
19 -
20 - @override
21 - String get title => S.current.wallet_list_title;
15
16 @override
24 - AppBarStyle get appBarStyle => AppBarStyle.withShadow;
17 + ObstructingPreferredSizeWidget appBar(BuildContext context) => null;
18
19 @override
20 Widget body(BuildContext context) => WalletListBody();
@@ -33,92 +26,265 @@ class WalletListBody extends StatefulWidget {
26 }
27
28 class WalletListBodyState extends State<WalletListBody> {
29 + final moneroIcon = Image.asset('assets/images/monero.png', height: 24, width: 24);
30 WalletListStore _walletListStore;
31
38 - void presetMenuForWallet(WalletDescription wallet, bool isCurrentWallet,
39 - BuildContext bodyContext) {
40 - final walletMenu = WalletMenu(bodyContext);
41 - final items = walletMenu.generateItemsForWalletMenu(isCurrentWallet);
42 -
43 - showDialog<void>(
44 - context: bodyContext,
45 - builder: (_) => Picker(
46 - items: items,
47 - selectedAtIndex: -1,
48 - title: S.of(context).wallet_menu,
49 - onItemSelected: (String item) => walletMenu.action(
50 - walletMenu.listItems.indexOf(item), wallet, isCurrentWallet)),
51 - );
52 - }
53 -
32 @override
33 Widget build(BuildContext context) {
34 _walletListStore = Provider.of<WalletListStore>(context);
35
58 - return ScrollableWithBottomSection(
59 - content: Container(
60 - padding: EdgeInsets.all(20),
61 - child: Observer(
62 - builder: (_) => ListView.separated(
63 - shrinkWrap: true,
64 - physics: const NeverScrollableScrollPhysics(),
65 - separatorBuilder: (_, index) => Divider(
66 - color: Theme.of(context).dividerTheme.color, height: 1.0),
67 - itemCount: _walletListStore.wallets.length,
68 - itemBuilder: (__, index) {
69 - final wallet = _walletListStore.wallets[index];
70 - final isCurrentWallet =
36 + return SafeArea(
37 + child: Container(
38 + padding: EdgeInsets.only(top: 32),
39 + color: PaletteDark.menuHeader,
40 + child: ScrollableWithBottomSection(
41 + contentPadding: EdgeInsets.only(bottom: 20),
42 + content: Container(
43 + child: Observer(
44 + builder: (_) => ListView.separated(
45 + shrinkWrap: true,
46 + physics: const NeverScrollableScrollPhysics(),
47 + separatorBuilder: (_, index) => Divider(
48 + color: PaletteDark.menuHeader, height: 16),
49 + itemCount: _walletListStore.wallets.length,
50 + itemBuilder: (__, index) {
51 + final wallet = _walletListStore.wallets[index];
52 + final screenWidth = MediaQuery.of(context).size.width;
53 +
54 + final isCurrentWallet =
55 _walletListStore.isCurrentWallet(wallet);
56
73 - return InkWell(
74 - onTap: () =>
75 - presetMenuForWallet(wallet, isCurrentWallet, context),
76 - child: Container(
77 - padding: EdgeInsets.only(left: 10.0, right: 10.0),
78 - child: ListTile(
79 - title: Text(
80 - wallet.name,
81 - style: TextStyle(
82 - color: isCurrentWallet
83 - ? Palette.cakeGreen
84 - : Theme.of(context)
85 - .primaryTextTheme
86 - .headline
87 - .color,
88 - fontSize: 18.0,
89 - fontWeight: FontWeight.w600),
57 + final walletMenu = WalletMenu(context);
58 + final items = walletMenu.generateItemsForWalletMenu(isCurrentWallet);
59 + final colors = walletMenu.generateColorsForWalletMenu(isCurrentWallet);
60 + final images = walletMenu.generateImagesForWalletMenu(isCurrentWallet);
61 +
62 + return Container(
63 + height: 108,
64 + width: double.infinity,
65 + child: CustomScrollView(
66 + scrollDirection: Axis.horizontal,
67 + slivers: <Widget>[
68 + SliverPersistentHeader(
69 + pinned: false,
70 + floating: true,
71 + delegate: WalletTile(
72 + min: screenWidth - 228,
73 + max: screenWidth,
74 + image: moneroIcon,
75 + walletName: wallet.name,
76 + walletAddress: '',
77 + isCurrent: isCurrentWallet
78 ),
91 - trailing: isCurrentWallet
92 - ? Icon(
93 - Icons.check,
94 - color: Palette.cakeGreen,
95 - size: 20.0,
96 - )
97 - : null)));
98 - }),
99 - ),
100 - ),
101 - bottomSection: Column(children: <Widget>[
102 - PrimaryIconButton(
103 - onPressed: () => Navigator.of(context).pushNamed(Routes.newWallet),
104 - iconData: Icons.add,
105 - color: Theme.of(context).primaryTextTheme.button.backgroundColor,
106 - borderColor:
79 + ),
80 + SliverList(
81 + delegate: SliverChildBuilderDelegate(
82 + (context, index) {
83 +
84 + final item = items[index];
85 + final color = colors[index];
86 + final image = images[index];
87 +
88 + final content = Center(
89 + child: Column(
90 + mainAxisSize: MainAxisSize.min,
91 + children: <Widget>[
92 + image,
93 + SizedBox(height: 5),
94 + Text(
95 + item,
96 + textAlign: TextAlign.center,
97 + style: TextStyle(
98 + fontSize: 12,
99 + color: Colors.white
100 + ),
101 + )
102 + ],
103 + ),
104 + );
105 +
106 + if (index == 0) {
107 + return GestureDetector(
108 + onTap: () => walletMenu.action(
109 + walletMenu.listItems.indexOf(item), wallet, isCurrentWallet),
110 + child: Container(
111 + height: 108,
112 + width: 108,
113 + color: PaletteDark.menuHeader,
114 + child: Container(
115 + padding: EdgeInsets.only(left: 5, right: 5),
116 + decoration: BoxDecoration(
117 + borderRadius: BorderRadius.only(
118 + topLeft: Radius.circular(12),
119 + bottomLeft: Radius.circular(12)
120 + ),
121 + color: color
122 + ),
123 + child: content,
124 + ),
125 + ),
126 + );
127 + }
128 +
129 + return GestureDetector(
130 + onTap: () => walletMenu.action(
131 + walletMenu.listItems.indexOf(item), wallet, isCurrentWallet),
132 + child: Container(
133 + height: 108,
134 + width: 108,
135 + padding: EdgeInsets.only(left: 5, right: 5),
136 + color: color,
137 + child: content,
138 + ),
139 + );
140 + },
141 + childCount: items.length
142 + )
143 + )
144 + ],
145 + ),
146 + );
147 + }),
148 + ),
149 + ),
150 + bottomSection: Column(children: <Widget>[
151 + PrimaryIconButton(
152 + onPressed: () => Navigator.of(context).pushNamed(Routes.newWallet),
153 + iconData: Icons.add,
154 + color: Theme.of(context).primaryTextTheme.button.backgroundColor,
155 + borderColor:
156 Theme.of(context).primaryTextTheme.button.decorationColor,
108 - iconColor: Palette.violet,
109 - iconBackgroundColor: Theme.of(context).primaryIconTheme.color,
110 - text: S.of(context).wallet_list_create_new_wallet),
111 - SizedBox(height: 10.0),
112 - PrimaryIconButton(
113 - onPressed: () =>
114 - Navigator.of(context).pushNamed(Routes.restoreWalletOptions),
115 - iconData: Icons.refresh,
116 - text: S.of(context).wallet_list_restore_wallet,
117 - color: Theme.of(context).accentTextTheme.button.backgroundColor,
118 - borderColor:
157 + iconColor: Palette.violet,
158 + iconBackgroundColor: Theme.of(context).primaryIconTheme.color,
159 + text: S.of(context).wallet_list_create_new_wallet),
160 + SizedBox(height: 10.0),
161 + PrimaryIconButton(
162 + onPressed: () =>
163 + Navigator.of(context).pushNamed(Routes.restoreWalletOptions),
164 + iconData: Icons.refresh,
165 + text: S.of(context).wallet_list_restore_wallet,
166 + color: Theme.of(context).accentTextTheme.button.backgroundColor,
167 + borderColor:
168 Theme.of(context).accentTextTheme.button.decorationColor,
120 - iconColor: Theme.of(context).primaryTextTheme.caption.color,
121 - iconBackgroundColor: Theme.of(context).accentIconTheme.color)
122 - ]));
169 + iconColor: Theme.of(context).primaryTextTheme.caption.color,
170 + iconBackgroundColor: Theme.of(context).accentIconTheme.color)
171 + ])),
172 + )
173 + );
174 + }
175 +}
176 +
177 +class WalletTile extends SliverPersistentHeaderDelegate {
178 + WalletTile({
179 + @required this.min,
180 + @required this.max,
181 + @required this.image,
182 + @required this.walletName,
183 + @required this.walletAddress,
184 + @required this.isCurrent
185 + });
186 +
187 + final double min;
188 + final double max;
189 + final Image image;
190 + final String walletName;
191 + final String walletAddress;
192 + final bool isCurrent;
193 +
194 + @override
195 + Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
196 +
197 + double opacity = 1 - shrinkOffset / (max - min);
198 + opacity = opacity >= 0 ? opacity : 0;
199 +
200 + double panelWidth = 12 * opacity;
201 + panelWidth = panelWidth < 12 ? 0 : 12;
202 +
203 + final currentColor = isCurrent
204 + ? Colors.white
205 + : PaletteDark.menuHeader;
206 +
207 + return Stack(
208 + fit: StackFit.expand,
209 + overflow: Overflow.visible,
210 + children: <Widget>[
211 + Positioned(
212 + top: 0,
213 + right: max - 4,
214 + child: Container(
215 + height: 108,
216 + width: 4,
217 + decoration: BoxDecoration(
218 + borderRadius: BorderRadius.only(topRight: Radius.circular(4), bottomRight: Radius.circular(4)),
219 + color: currentColor
220 + ),
221 + ),
222 + ),
223 + Positioned(
224 + top: 0,
225 + right: 12,
226 + child: Container(
227 + height: 108,
228 + width: max - 16,
229 + padding: EdgeInsets.only(left: 20, right: 20),
230 + color: PaletteDark.menuHeader,
231 + child: Column(
232 + mainAxisSize: MainAxisSize.max,
233 + mainAxisAlignment: MainAxisAlignment.center,
234 + children: <Widget>[
235 + Row(
236 + mainAxisAlignment: MainAxisAlignment.start,
237 + crossAxisAlignment: CrossAxisAlignment.center,
238 + children: <Widget>[
239 + image,
240 + SizedBox(width: 10),
241 + Text(
242 + walletName,
243 + style: TextStyle(
244 + fontSize: 22,
245 + fontWeight: FontWeight.bold,
246 + color: Colors.white
247 + ),
248 + )
249 + ],
250 + )
251 + ],
252 + ),
253 + ),
254 + ),
255 + Positioned(
256 + top: 0,
257 + right: 0,
258 + child: Opacity(
259 + opacity: opacity,
260 + child: Container(
261 + height: 108,
262 + width: panelWidth,
263 + decoration: BoxDecoration(
264 + borderRadius: BorderRadius.only(topLeft: Radius.circular(12), bottomLeft: Radius.circular(12)),
265 + gradient: LinearGradient(
266 + begin: Alignment.topCenter,
267 + end: Alignment.bottomCenter,
268 + colors: [
269 + PaletteDark.walletCardTopEndSync,
270 + PaletteDark.walletCardBottomEndSync
271 + ]
272 + )
273 + ),
274 + ),
275 + )
276 + ),
277 + ],
278 + );
279 }
280 +
281 + @override
282 + double get maxExtent => max;
283 +
284 + @override
285 + double get minExtent => min;
286 +
287 + @override
288 + bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) => true;
289 +
290 }
lib/src/screens/wallet_list/wallet_menu.dart
+36
@@ -18,6 +18,20 @@ class WalletMenu {
18 S.current.rescan
19 ];
20
21 + final List<Color> listColors = [
22 + Colors.blue,
23 + Colors.orange,
24 + Colors.red,
25 + Colors.green
26 + ];
27 +
28 + final List<Image> listImages = [
29 + Image.asset('assets/images/load.png', height: 32, width: 32, color: Colors.white),
30 + Image.asset('assets/images/eye.png', height: 32, width: 32, color: Colors.white),
31 + Image.asset('assets/images/trash.png', height: 32, width: 32, color: Colors.white),
32 + Image.asset('assets/images/scanner.png', height: 32, width: 32, color: Colors.white)
33 + ];
34 +
35 List<String> generateItemsForWalletMenu(bool isCurrentWallet) {
36 final items = List<String>();
37
@@ -29,6 +43,28 @@ class WalletMenu {
43 return items;
44 }
45
46 + List<Color> generateColorsForWalletMenu(bool isCurrentWallet) {
47 + final colors = List<Color>();
48 +
49 + if (!isCurrentWallet) colors.add(listColors[0]);
50 + if (isCurrentWallet) colors.add(listColors[1]);
51 + if (!isCurrentWallet) colors.add(listColors[2]);
52 + if (isCurrentWallet) colors.add(listColors[3]);
53 +
54 + return colors;
55 + }
56 +
57 + List<Image> generateImagesForWalletMenu(bool isCurrentWallet) {
58 + final images = List<Image>();
59 +
60 + if (!isCurrentWallet) images.add(listImages[0]);
61 + if (isCurrentWallet) images.add(listImages[1]);
62 + if (!isCurrentWallet) images.add(listImages[2]);
63 + if (isCurrentWallet) images.add(listImages[3]);
64 +
65 + return images;
66 + }
67 +
68 void action(int index, WalletDescription wallet, bool isCurrentWallet) {
69 final _walletListStore = Provider.of<WalletListStore>(context);
70