CWA-198 | moved ButtonHeader class to button_header.dart, fixed containers and bounds height for date_section_raw, trade_raw and transaction_raw, changed animation time for trade_history panel

Oleksandr Sobol committed Apr 21, 2020 at 17:31 UTC 52d5dedaf82b95f3a7cb12db4263c391d297325b
5 files changed +308 -297
lib/src/screens/dashboard/widgets/button_header.dart new
+297
@@ -0,0 +1,297 @@
1 +import 'package:cake_wallet/src/domain/exchange/exchange_provider_description.dart';
2 +import 'package:cake_wallet/src/stores/action_list/action_list_store.dart';
3 +import 'package:flutter/cupertino.dart';
4 +import 'package:flutter/material.dart';
5 +import 'package:cake_wallet/palette.dart';
6 +import 'package:cake_wallet/generated/i18n.dart';
7 +import 'package:flutter_mobx/flutter_mobx.dart';
8 +import 'package:provider/provider.dart';
9 +import 'package:cake_wallet/routes.dart';
10 +import 'package:date_range_picker/date_range_picker.dart' as date_rage_picker;
11 +
12 +class ButtonHeader extends SliverPersistentHeaderDelegate {
13 + final sendImage = Image.asset('assets/images/send.png');
14 + final exchangeImage = Image.asset('assets/images/exchange.png');
15 + final buyImage = Image.asset('assets/images/coins.png');
16 + final filterButton = Image.asset('assets/images/filter_button.png');
17 +
18 + @override
19 + Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
20 + final actionListStore = Provider.of<ActionListStore>(context);
21 + final historyPanelWidth = MediaQuery.of(context).size.width;
22 +
23 + double buttonsOpacity = 1 - shrinkOffset / (maxExtent - minExtent);
24 + double buttonsHeight = maxExtent - minExtent - shrinkOffset;
25 +
26 + buttonsOpacity = buttonsOpacity >= 0 ? buttonsOpacity : 0;
27 + buttonsHeight = buttonsHeight >= 0 ? buttonsHeight : 0;
28 +
29 + return Stack(
30 + fit: StackFit.expand,
31 + overflow: Overflow.visible,
32 + children: <Widget>[
33 + Opacity(
34 + opacity: buttonsOpacity,
35 + child: Container(
36 + height: buttonsHeight,
37 + padding: EdgeInsets.only(left: 44, right: 44),
38 + child: Row(
39 + children: <Widget>[
40 + Flexible(
41 + child: actionButton(
42 + context: context,
43 + image: sendImage,
44 + title: S.of(context).send,
45 + route: Routes.send
46 + )
47 + ),
48 + Flexible(
49 + child: actionButton(
50 + context: context,
51 + image: exchangeImage,
52 + title: S.of(context).exchange,
53 + route: Routes.exchange
54 + )
55 + ),
56 + Flexible(
57 + child: actionButton(
58 + context: context,
59 + image: buyImage,
60 + title: S.of(context).buy,
61 + route: ''
62 + )
63 + )
64 + ],
65 + ),
66 + ),
67 + ),
68 + Positioned(
69 + top: buttonsHeight,
70 + left: 0,
71 + child: Container(
72 + width: historyPanelWidth,
73 + height: 66,
74 + padding: EdgeInsets.only(top: 20, left: 20, right: 20, bottom: 10),
75 + decoration: BoxDecoration(
76 + borderRadius: BorderRadius.only(topLeft: Radius.circular(20), topRight: Radius.circular(20)),
77 + color: PaletteDark.historyPanel,
78 + ),
79 + child: Stack(
80 + alignment: Alignment.center,
81 + children: <Widget>[
82 + Text(
83 + S.of(context).trade_history_title,
84 + style: TextStyle(
85 + fontSize: 20,
86 + color: Colors.white
87 + ),
88 + ),
89 + Positioned(
90 + right: 0,
91 + child: PopupMenuButton<int>(
92 + itemBuilder: (context) => [
93 + PopupMenuItem(
94 + enabled: false,
95 + value: -1,
96 + child: Text(S.of(context).transactions,
97 + style: TextStyle(
98 + fontWeight: FontWeight.bold,
99 + color: Theme.of(context).primaryTextTheme.caption.color))),
100 + PopupMenuItem(
101 + value: 0,
102 + child: Observer(
103 + builder: (_) => Row(
104 + mainAxisAlignment:
105 + MainAxisAlignment
106 + .spaceBetween,
107 + children: [
108 + Text(S.of(context).incoming),
109 + Checkbox(
110 + value: actionListStore
111 + .transactionFilterStore
112 + .displayIncoming,
113 + onChanged: (value) =>
114 + actionListStore
115 + .transactionFilterStore
116 + .toggleIncoming(),
117 + )
118 + ]))),
119 + PopupMenuItem(
120 + value: 1,
121 + child: Observer(
122 + builder: (_) => Row(
123 + mainAxisAlignment:
124 + MainAxisAlignment
125 + .spaceBetween,
126 + children: [
127 + Text(S.of(context).outgoing),
128 + Checkbox(
129 + value: actionListStore
130 + .transactionFilterStore
131 + .displayOutgoing,
132 + onChanged: (value) =>
133 + actionListStore
134 + .transactionFilterStore
135 + .toggleOutgoing(),
136 + )
137 + ]))),
138 + PopupMenuItem(
139 + value: 2,
140 + child:
141 + Text(S.of(context).transactions_by_date)),
142 + PopupMenuDivider(),
143 + PopupMenuItem(
144 + enabled: false,
145 + value: -1,
146 + child: Text(S.of(context).trades,
147 + style: TextStyle(
148 + fontWeight: FontWeight.bold,
149 + color: Theme.of(context).primaryTextTheme.caption.color))),
150 + PopupMenuItem(
151 + value: 3,
152 + child: Observer(
153 + builder: (_) => Row(
154 + mainAxisAlignment:
155 + MainAxisAlignment
156 + .spaceBetween,
157 + children: [
158 + Text('XMR.TO'),
159 + Checkbox(
160 + value: actionListStore
161 + .tradeFilterStore
162 + .displayXMRTO,
163 + onChanged: (value) =>
164 + actionListStore
165 + .tradeFilterStore
166 + .toggleDisplayExchange(
167 + ExchangeProviderDescription
168 + .xmrto),
169 + )
170 + ]))),
171 + PopupMenuItem(
172 + value: 4,
173 + child: Observer(
174 + builder: (_) => Row(
175 + mainAxisAlignment:
176 + MainAxisAlignment
177 + .spaceBetween,
178 + children: [
179 + Text('Change.NOW'),
180 + Checkbox(
181 + value: actionListStore
182 + .tradeFilterStore
183 + .displayChangeNow,
184 + onChanged: (value) =>
185 + actionListStore
186 + .tradeFilterStore
187 + .toggleDisplayExchange(
188 + ExchangeProviderDescription
189 + .changeNow),
190 + )
191 + ]))),
192 + PopupMenuItem(
193 + value: 5,
194 + child: Observer(
195 + builder: (_) => Row(
196 + mainAxisAlignment:
197 + MainAxisAlignment
198 + .spaceBetween,
199 + children: [
200 + Text('MorphToken'),
201 + Checkbox(
202 + value: actionListStore
203 + .tradeFilterStore
204 + .displayMorphToken,
205 + onChanged: (value) =>
206 + actionListStore
207 + .tradeFilterStore
208 + .toggleDisplayExchange(
209 + ExchangeProviderDescription
210 + .morphToken),
211 + )
212 + ])))
213 + ],
214 + child: filterButton,
215 + onSelected: (item) async {
216 + if (item == 2) {
217 + final List<DateTime> picked =
218 + await date_rage_picker.showDatePicker(
219 + context: context,
220 + initialFirstDate: DateTime.now()
221 + .subtract(Duration(days: 1)),
222 + initialLastDate: (DateTime.now()),
223 + firstDate: DateTime(2015),
224 + lastDate: DateTime.now()
225 + .add(Duration(days: 1)));
226 +
227 + if (picked != null && picked.length == 2) {
228 + actionListStore.transactionFilterStore
229 + .changeStartDate(picked.first);
230 + actionListStore.transactionFilterStore
231 + .changeEndDate(picked.last);
232 + }
233 + }
234 + },
235 + ),
236 + )
237 + ],
238 + ),
239 + )
240 + )
241 + ],
242 + );
243 + }
244 +
245 + @override
246 + double get maxExtent => 174;
247 +
248 + @override
249 + double get minExtent => 66;
250 +
251 + @override
252 + bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) => true;
253 +
254 + Widget actionButton({
255 + BuildContext context,
256 + @required Image image,
257 + @required String title,
258 + @required String route}) {
259 +
260 + return Container(
261 + width: MediaQuery.of(context).size.width,
262 + child: Column(
263 + mainAxisAlignment: MainAxisAlignment.start,
264 + crossAxisAlignment: CrossAxisAlignment.center,
265 + children: <Widget>[
266 + GestureDetector(
267 + onTap: () {
268 + if (route.isNotEmpty) {
269 + Navigator.of(context, rootNavigator: true).pushNamed(route);
270 + }
271 + },
272 + child: Container(
273 + height: 48,
274 + width: 48,
275 + alignment: Alignment.center,
276 + decoration: BoxDecoration(
277 + color: Colors.white,
278 + shape: BoxShape.circle
279 + ),
280 + child: image,
281 + ),
282 + ),
283 + Padding(
284 + padding: EdgeInsets.only(top: 10),
285 + child: Text(
286 + title,
287 + style: TextStyle(
288 + fontSize: 16,
289 + color: PaletteDark.walletCardText
290 + ),
291 + ),
292 + )
293 + ],
294 + ),
295 + );
296 + }
297 +}
\ No newline at end of file
lib/src/screens/dashboard/widgets/date_section_raw.dart
+1
@@ -36,6 +36,7 @@ class DateSectionRaw extends StatelessWidget {
36 }
37
38 return Container(
39 + height: 36,
40 padding: EdgeInsets.only(top: 10, bottom: 10, left: 20, right: 20),
41 alignment: Alignment.center,
42 decoration: BoxDecoration(
lib/src/screens/dashboard/widgets/trade_history_panel.dart
+6 -295
@@ -1,5 +1,4 @@
1 import 'package:cake_wallet/src/domain/common/balance_display_mode.dart';
2 -import 'package:cake_wallet/src/domain/exchange/exchange_provider_description.dart';
2 import 'package:cake_wallet/src/stores/action_list/action_list_store.dart';
3 import 'package:cake_wallet/src/stores/action_list/date_section_item.dart';
4 import 'package:cake_wallet/src/stores/action_list/trade_list_item.dart';
@@ -8,7 +7,6 @@ import 'package:cake_wallet/src/stores/settings/settings_store.dart';
7 import 'package:flutter/cupertino.dart';
8 import 'package:flutter/material.dart';
9 import 'package:cake_wallet/palette.dart';
11 -import 'package:cake_wallet/generated/i18n.dart';
10 import 'package:flutter_mobx/flutter_mobx.dart';
11 import 'package:intl/intl.dart';
12 import 'package:provider/provider.dart';
@@ -16,7 +14,7 @@ import 'package:cake_wallet/routes.dart';
14 import 'date_section_raw.dart';
15 import 'trade_row.dart';
16 import 'transaction_raw.dart';
19 -import 'package:date_range_picker/date_range_picker.dart' as date_rage_picker;
17 +import 'button_header.dart';
18
19 class TradeHistoryPanel extends StatefulWidget {
20 @override
@@ -58,7 +56,7 @@ class TradeHistoryPanelState extends State<TradeHistoryPanel> {
56 child: AnimatedContainer(
57 width: MediaQuery.of(context).size.width,
58 height: panelHeight,
61 - duration: Duration(milliseconds: 500),
59 + duration: Duration(milliseconds: 1000),
60 curve: Curves.fastOutSlowIn,
61 child: CustomScrollView(
62 slivers: <Widget>[
@@ -75,7 +73,7 @@ class TradeHistoryPanelState extends State<TradeHistoryPanel> {
73 : actionListStore.items;
74 final itemsCount = items.length + 1;
75 final symbol = settingsStore.fiatCurrency.toString();
78 - double freeSpaceHeight = MediaQuery.of(context).size.height - 496; // FIXME
76 + double freeSpaceHeight = MediaQuery.of(context).size.height - 496;
77
78 return SliverList(
79 key: _listKey,
@@ -95,12 +93,12 @@ class TradeHistoryPanelState extends State<TradeHistoryPanel> {
93 final item = items[index];
94
95 if (item is DateSectionItem) {
98 - freeSpaceHeight -= 32; // FIXME
96 + freeSpaceHeight -= 38;
97 return DateSectionRaw(date: item.date);
98 }
99
100 if (item is TransactionListItem) {
103 - freeSpaceHeight -= 45; // FIXME
101 + freeSpaceHeight -= 58;
102 final transaction = item.transaction;
103 final savedDisplayMode = settingsStore.balanceDisplayMode;
104 final formattedAmount =
@@ -125,7 +123,7 @@ class TradeHistoryPanelState extends State<TradeHistoryPanel> {
123 }
124
125 if (item is TradeListItem) {
128 - freeSpaceHeight -= 45; // FIXME
126 + freeSpaceHeight -= 58;
127 final trade = item.trade;
128 final savedDisplayMode = settingsStore.balanceDisplayMode;
129 final formattedAmount = trade.amount != null
@@ -159,291 +157,4 @@ class TradeHistoryPanelState extends State<TradeHistoryPanel> {
157 ),
158 );
159 }
162 -}
163 -
164 -class ButtonHeader extends SliverPersistentHeaderDelegate {
165 - final sendImage = Image.asset('assets/images/send.png');
166 - final exchangeImage = Image.asset('assets/images/exchange.png');
167 - final buyImage = Image.asset('assets/images/coins.png');
168 - final filterButton = Image.asset('assets/images/filter_button.png');
169 -
170 - @override
171 - Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
172 - final actionListStore = Provider.of<ActionListStore>(context);
173 - final historyPanelWidth = MediaQuery.of(context).size.width;
174 -
175 - double buttonsOpacity = 1 - shrinkOffset / (maxExtent - minExtent);
176 - double buttonsHeight = maxExtent - minExtent - shrinkOffset;
177 -
178 - buttonsOpacity = buttonsOpacity >= 0 ? buttonsOpacity : 0;
179 - buttonsHeight = buttonsHeight >= 0 ? buttonsHeight : 0;
180 -
181 - return Stack(
182 - fit: StackFit.expand,
183 - overflow: Overflow.visible,
184 - children: <Widget>[
185 - Opacity(
186 - opacity: buttonsOpacity,
187 - child: Container(
188 - height: buttonsHeight,
189 - padding: EdgeInsets.only(left: 44, right: 44),
190 - child: Row(
191 - children: <Widget>[
192 - Flexible(
193 - child: actionButton(
194 - context: context,
195 - image: sendImage,
196 - title: S.of(context).send,
197 - route: Routes.send
198 - )
199 - ),
200 - Flexible(
201 - child: actionButton(
202 - context: context,
203 - image: exchangeImage,
204 - title: S.of(context).exchange,
205 - route: Routes.exchange
206 - )
207 - ),
208 - Flexible(
209 - child: actionButton(
210 - context: context,
211 - image: buyImage,
212 - title: S.of(context).buy,
213 - route: ''
214 - )
215 - )
216 - ],
217 - ),
218 - ),
219 - ),
220 - Positioned(
221 - top: buttonsHeight,
222 - left: 0,
223 - child: Container(
224 - width: historyPanelWidth,
225 - height: 66,
226 - padding: EdgeInsets.only(top: 20, left: 20, right: 20, bottom: 10),
227 - decoration: BoxDecoration(
228 - borderRadius: BorderRadius.only(topLeft: Radius.circular(20), topRight: Radius.circular(20)),
229 - color: PaletteDark.historyPanel,
230 - ),
231 - child: Stack(
232 - alignment: Alignment.center,
233 - children: <Widget>[
234 - Text(
235 - S.of(context).trade_history_title,
236 - style: TextStyle(
237 - fontSize: 20,
238 - color: Colors.white
239 - ),
240 - ),
241 - Positioned(
242 - right: 0,
243 - child: PopupMenuButton<int>(
244 - itemBuilder: (context) => [
245 - PopupMenuItem(
246 - enabled: false,
247 - value: -1,
248 - child: Text(S.of(context).transactions,
249 - style: TextStyle(
250 - fontWeight: FontWeight.bold,
251 - color: Theme.of(context).primaryTextTheme.caption.color))),
252 - PopupMenuItem(
253 - value: 0,
254 - child: Observer(
255 - builder: (_) => Row(
256 - mainAxisAlignment:
257 - MainAxisAlignment
258 - .spaceBetween,
259 - children: [
260 - Text(S.of(context).incoming),
261 - Checkbox(
262 - value: actionListStore
263 - .transactionFilterStore
264 - .displayIncoming,
265 - onChanged: (value) =>
266 - actionListStore
267 - .transactionFilterStore
268 - .toggleIncoming(),
269 - )
270 - ]))),
271 - PopupMenuItem(
272 - value: 1,
273 - child: Observer(
274 - builder: (_) => Row(
275 - mainAxisAlignment:
276 - MainAxisAlignment
277 - .spaceBetween,
278 - children: [
279 - Text(S.of(context).outgoing),
280 - Checkbox(
281 - value: actionListStore
282 - .transactionFilterStore
283 - .displayOutgoing,
284 - onChanged: (value) =>
285 - actionListStore
286 - .transactionFilterStore
287 - .toggleOutgoing(),
288 - )
289 - ]))),
290 - PopupMenuItem(
291 - value: 2,
292 - child:
293 - Text(S.of(context).transactions_by_date)),
294 - PopupMenuDivider(),
295 - PopupMenuItem(
296 - enabled: false,
297 - value: -1,
298 - child: Text(S.of(context).trades,
299 - style: TextStyle(
300 - fontWeight: FontWeight.bold,
301 - color: Theme.of(context).primaryTextTheme.caption.color))),
302 - PopupMenuItem(
303 - value: 3,
304 - child: Observer(
305 - builder: (_) => Row(
306 - mainAxisAlignment:
307 - MainAxisAlignment
308 - .spaceBetween,
309 - children: [
310 - Text('XMR.TO'),
311 - Checkbox(
312 - value: actionListStore
313 - .tradeFilterStore
314 - .displayXMRTO,
315 - onChanged: (value) =>
316 - actionListStore
317 - .tradeFilterStore
318 - .toggleDisplayExchange(
319 - ExchangeProviderDescription
320 - .xmrto),
321 - )
322 - ]))),
323 - PopupMenuItem(
324 - value: 4,
325 - child: Observer(
326 - builder: (_) => Row(
327 - mainAxisAlignment:
328 - MainAxisAlignment
329 - .spaceBetween,
330 - children: [
331 - Text('Change.NOW'),
332 - Checkbox(
333 - value: actionListStore
334 - .tradeFilterStore
335 - .displayChangeNow,
336 - onChanged: (value) =>
337 - actionListStore
338 - .tradeFilterStore
339 - .toggleDisplayExchange(
340 - ExchangeProviderDescription
341 - .changeNow),
342 - )
343 - ]))),
344 - PopupMenuItem(
345 - value: 5,
346 - child: Observer(
347 - builder: (_) => Row(
348 - mainAxisAlignment:
349 - MainAxisAlignment
350 - .spaceBetween,
351 - children: [
352 - Text('MorphToken'),
353 - Checkbox(
354 - value: actionListStore
355 - .tradeFilterStore
356 - .displayMorphToken,
357 - onChanged: (value) =>
358 - actionListStore
359 - .tradeFilterStore
360 - .toggleDisplayExchange(
361 - ExchangeProviderDescription
362 - .morphToken),
363 - )
364 - ])))
365 - ],
366 - child: filterButton,
367 - onSelected: (item) async {
368 - if (item == 2) {
369 - final List<DateTime> picked =
370 - await date_rage_picker.showDatePicker(
371 - context: context,
372 - initialFirstDate: DateTime.now()
373 - .subtract(Duration(days: 1)),
374 - initialLastDate: (DateTime.now()),
375 - firstDate: DateTime(2015),
376 - lastDate: DateTime.now()
377 - .add(Duration(days: 1)));
378 -
379 - if (picked != null && picked.length == 2) {
380 - actionListStore.transactionFilterStore
381 - .changeStartDate(picked.first);
382 - actionListStore.transactionFilterStore
383 - .changeEndDate(picked.last);
384 - }
385 - }
386 - },
387 - ),
388 - )
389 - ],
390 - ),
391 - )
392 - )
393 - ],
394 - );
395 - }
396 -
397 - @override
398 - double get maxExtent => 174;
399 -
400 - @override
401 - double get minExtent => 66;
402 -
403 - @override
404 - bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) => true;
405 -
406 - Widget actionButton({
407 - BuildContext context,
408 - @required Image image,
409 - @required String title,
410 - @required String route}) {
411 -
412 - return Container(
413 - width: MediaQuery.of(context).size.width,
414 - child: Column(
415 - mainAxisAlignment: MainAxisAlignment.start,
416 - crossAxisAlignment: CrossAxisAlignment.center,
417 - children: <Widget>[
418 - GestureDetector(
419 - onTap: () {
420 - if (route.isNotEmpty) {
421 - Navigator.of(context, rootNavigator: true).pushNamed(route);
422 - }
423 - },
424 - child: Container(
425 - height: 48,
426 - width: 48,
427 - alignment: Alignment.center,
428 - decoration: BoxDecoration(
429 - color: Colors.white,
430 - shape: BoxShape.circle
431 - ),
432 - child: image,
433 - ),
434 - ),
435 - Padding(
436 - padding: EdgeInsets.only(top: 10),
437 - child: Text(
438 - title,
439 - style: TextStyle(
440 - fontSize: 16,
441 - color: PaletteDark.walletCardText
442 - ),
443 - ),
444 - )
445 - ],
446 - ),
447 - );
448 - }
160 }
\ No newline at end of file
lib/src/screens/dashboard/widgets/trade_row.dart
+2 -1
@@ -26,10 +26,11 @@ class TradeRow extends StatelessWidget {
26 return InkWell(
27 onTap: onTap,
28 child: Container(
29 + height: 56,
30 decoration: BoxDecoration(
31 color: PaletteDark.historyPanel,
32 border: Border.all(
32 - width: 0.5,
33 + width: 1,
34 color: PaletteDark.historyPanel
35 ),
36 ),
lib/src/screens/dashboard/widgets/transaction_raw.dart
+2 -1
@@ -24,10 +24,11 @@ class TransactionRow extends StatelessWidget {
24 return InkWell(
25 onTap: onTap,
26 child: Container(
27 + height: 56,
28 decoration: BoxDecoration(
29 color: PaletteDark.historyPanel,
30 border: Border.all(
30 - width: 0.5,
31 + width: 1,
32 color: PaletteDark.historyPanel
33 ),
34 ),