CAKE-15 | created header row, transaction page, balance view model, formatted item list, wallet balance; applied new design to trade and transaction rows; applied transaction page to dashboard page; applied balance view model, trade store, trade filter store and transaction filter store to dashboard view model; changed trade list item and transaction list item
Oleksandr Sobol committed
Jul 23, 2020 at 15:20 UTC
bdfe208d20bbd33962666275d331d6cb14bacd48
27 files changed
+937
-1311
lib/bitcoin/bitcoin_transaction_info.dart
+8
-2
@@ -4,6 +4,7 @@ import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin;
4
import 'package:bitcoin_flutter/src/payments/index.dart' show PaymentData;
5
import 'package:cake_wallet/src/domain/common/transaction_direction.dart';
6
import 'package:cake_wallet/src/domain/common/transaction_info.dart';
7
+import 'package:cake_wallet/src/domain/common/format_amount.dart';
8
9
class BitcoinTransactionInfo extends TransactionInfo {
10
BitcoinTransactionInfo(
@@ -62,11 +63,16 @@ class BitcoinTransactionInfo extends TransactionInfo {
63
64
final String id;
65
66
+ String _fiatAmount;
67
+
68
+ @override
69
+ String amountFormatted() => '${formatAmount(bitcoinAmountToString(amount: amount))} BTC';
70
+
71
@override
66
- String amountFormatted() => bitcoinAmountToString(amount: amount);
72
+ String fiatAmount() => _fiatAmount ?? '';
73
74
@override
69
- String fiatAmount() => '\$ 24.5';
75
+ void changeFiatAmount(String amount) => _fiatAmount = formatAmount(amount);
76
77
Map<String, dynamic> toJson() {
78
final m = Map<String, dynamic>();
lib/di.dart
+30
-4
@@ -1,6 +1,7 @@
1
import 'package:cake_wallet/core/contact_service.dart';
2
import 'package:cake_wallet/src/domain/common/contact.dart';
3
import 'package:cake_wallet/src/domain/common/node.dart';
4
+import 'package:cake_wallet/src/domain/exchange/trade.dart';
5
import 'package:cake_wallet/src/screens/contact/contact_list_page.dart';
6
import 'package:cake_wallet/src/screens/contact/contact_page.dart';
7
import 'package:cake_wallet/src/screens/nodes/node_create_or_edit_page.dart';
@@ -11,7 +12,7 @@ import 'package:cake_wallet/src/screens/wallet_keys/wallet_keys_page.dart';
12
import 'package:cake_wallet/store/contact_list_store.dart';
13
import 'package:cake_wallet/store/node_list_store.dart';
14
import 'package:cake_wallet/store/settings_store.dart';
14
-import 'package:cake_wallet/store/settings_store.dart';
15
+import 'package:cake_wallet/src/stores/price/price_store.dart';
16
import 'package:cake_wallet/core/auth_service.dart';
17
import 'package:cake_wallet/core/key_service.dart';
18
import 'package:cake_wallet/monero/monero_wallet.dart';
@@ -31,7 +32,8 @@ import 'package:cake_wallet/view_model/node_list/node_list_view_model.dart';
32
import 'package:cake_wallet/view_model/node_list/node_create_or_edit_view_model.dart';
33
import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_edit_or_create_view_model.dart';
34
import 'package:cake_wallet/view_model/auth_view_model.dart';
34
-import 'package:cake_wallet/view_model/dashboard_view_model.dart';
35
+import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
36
+import 'package:cake_wallet/view_model/dashboard/balance_view_model.dart';
37
import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_view_model.dart';
38
import 'package:cake_wallet/view_model/monero_account_list/monero_account_edit_or_create_view_model.dart';
39
import 'package:cake_wallet/view_model/monero_account_list/monero_account_list_view_model.dart';
@@ -52,6 +54,9 @@ import 'package:cake_wallet/store/app_store.dart';
54
import 'package:cake_wallet/src/domain/common/wallet_type.dart';
55
import 'package:cake_wallet/view_model/wallet_new_vm.dart';
56
import 'package:cake_wallet/store/authentication_store.dart';
57
+import 'package:cake_wallet/store/dashboard/trades_store.dart';
58
+import 'package:cake_wallet/store/dashboard/trade_filter_store.dart';
59
+import 'package:cake_wallet/store/dashboard/transaction_filter_store.dart';
60
61
final getIt = GetIt.instance;
62
@@ -77,7 +82,9 @@ NodeListStore setupNodeListStore(Box<Node> nodeSource) {
82
Future setup(
83
{Box<WalletInfo> walletInfoSource,
84
Box<Node> nodeSource,
80
- Box<Contact> contactSource}) async {
85
+ Box<Contact> contactSource,
86
+ Box<Trade> tradesSource,
87
+ PriceStore priceStore}) async {
88
getIt.registerSingletonAsync<SharedPreferences>(
89
() => SharedPreferences.getInstance());
90
@@ -97,6 +104,13 @@ Future setup(
104
nodeListStore: getIt.get<NodeListStore>()));
105
getIt.registerSingleton<ContactService>(
106
ContactService(contactSource, getIt.get<AppStore>().contactListStore));
107
+ getIt.registerSingleton<TradesStore>(TradesStore(
108
+ tradesSource: tradesSource,
109
+ settingsStore: getIt.get<SettingsStore>()));
110
+ getIt.registerSingleton<TradeFilterStore>(
111
+ TradeFilterStore(wallet: getIt.get<AppStore>().wallet));
112
+ getIt.registerSingleton<TransactionFilterStore>(TransactionFilterStore());
113
+
114
getIt.registerFactory<KeyService>(
115
() => KeyService(getIt.get<FlutterSecureStorage>()));
116
@@ -128,7 +142,19 @@ Future setup(
142
() => WalletAddressListViewModel(wallet: getIt.get<AppStore>().wallet));
143
144
getIt.registerFactory(
131
- () => DashboardViewModel(appStore: getIt.get<AppStore>()));
145
+ () => BalanceViewModel(
146
+ wallet: getIt.get<AppStore>().wallet,
147
+ settingsStore: getIt.get<SettingsStore>(),
148
+ priceStore: priceStore));
149
+
150
+ getIt.registerFactory(
151
+ () => DashboardViewModel(
152
+ balanceViewModel: getIt.get<BalanceViewModel>(),
153
+ appStore: getIt.get<AppStore>(),
154
+ tradesStore: getIt.get<TradesStore>(),
155
+ tradeFilterStore: getIt.get<TradeFilterStore>(),
156
+ transactionFilterStore: getIt.get<TransactionFilterStore>()
157
+ ));
158
159
getIt.registerFactory<AuthService>(() => AuthService(
160
secureStorage: getIt.get<FlutterSecureStorage>(),
lib/main.dart
+14
-8
@@ -85,13 +85,6 @@ void main() async {
85
final exchangeTemplates =
86
await Hive.openBox<ExchangeTemplate>(ExchangeTemplate.boxName);
87
88
- await initialSetup(
89
- sharedPreferences: await SharedPreferences.getInstance(),
90
- nodes: nodes,
91
- walletInfoSource: walletInfoSource,
92
- contactSource: contacts,
93
- initialMigrationVersion: 3);
94
-
88
final sharedPreferences = await SharedPreferences.getInstance();
89
final walletService = WalletService();
90
final walletListService = WalletListService(
@@ -125,6 +118,15 @@ void main() async {
118
final walletCreationService = WalletCreationService();
119
final authService = AuthService();
120
121
+ await initialSetup(
122
+ sharedPreferences: await SharedPreferences.getInstance(),
123
+ nodes: nodes,
124
+ walletInfoSource: walletInfoSource,
125
+ contactSource: contacts,
126
+ tradesSource: trades,
127
+ priceStore: priceStore,
128
+ initialMigrationVersion: 3);
129
+
130
setReactions(
131
settingsStore: settingsStore,
132
priceStore: priceStore,
@@ -163,6 +165,8 @@ Future<void> initialSetup(
165
@required Box<Node> nodes,
166
@required Box<WalletInfo> walletInfoSource,
167
@required Box<Contact> contactSource,
168
+ @required Box<Trade> tradesSource,
169
+ @required PriceStore priceStore,
170
int initialMigrationVersion = 3}) async {
171
await defaultSettingsMigration(
172
version: initialMigrationVersion,
@@ -171,7 +175,9 @@ Future<void> initialSetup(
175
await setup(
176
walletInfoSource: walletInfoSource,
177
nodeSource: nodes,
174
- contactSource: contactSource);
178
+ contactSource: contactSource,
179
+ tradesSource: tradesSource,
180
+ priceStore: priceStore);
181
await bootstrap();
182
monero_wallet.onStartup();
183
}
lib/src/domain/common/transaction_info.dart
+1
@@ -8,4 +8,5 @@ abstract class TransactionInfo extends Object {
8
int height;
9
String amountFormatted();
10
String fiatAmount();
11
+ void changeFiatAmount(String amount);
12
}
\ No newline at end of file
lib/src/screens/dashboard/dashboard_page.dart
+9
-12
@@ -2,13 +2,14 @@ import 'package:cake_wallet/generated/i18n.dart';
2
import 'package:cake_wallet/routes.dart';
3
import 'package:flutter/material.dart';
4
import 'package:flutter/cupertino.dart';
5
-import 'package:cake_wallet/view_model/dashboard_view_model.dart';
5
+import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
6
import 'package:cake_wallet/src/screens/base_page.dart';
7
import 'package:cake_wallet/src/screens/dashboard/widgets/menu_widget.dart';
8
import 'package:cake_wallet/palette.dart';
9
import 'package:dots_indicator/dots_indicator.dart';
10
import 'package:cake_wallet/src/screens/dashboard/widgets/action_button.dart';
11
import 'package:cake_wallet/src/screens/dashboard/widgets/balance_page.dart';
12
+import 'package:cake_wallet/src/screens/dashboard/widgets/transactions_page.dart';
13
import 'package:flutter_mobx/flutter_mobx.dart';
14
import 'package:mobx/mobx.dart';
15
import 'package:cake_wallet/src/screens/dashboard/widgets/sync_indicator.dart';
@@ -35,8 +36,11 @@ class DashboardPage extends BasePage {
36
return Container(
37
alignment: Alignment.centerRight,
38
width: 40,
38
- child: InkWell(
39
- onTap: () async {
39
+ child: FlatButton(
40
+ highlightColor: Colors.transparent,
41
+ splashColor: Colors.transparent,
42
+ padding: EdgeInsets.all(0),
43
+ onPressed: () async {
44
await showDialog<void>(
45
builder: (_) => MenuWidget(
46
name: walletViewModel.name,
@@ -45,7 +49,7 @@ class DashboardPage extends BasePage {
49
context: context);
50
},
51
child: menuButton
48
- ),
52
+ )
53
);
54
}
55
@@ -141,14 +145,7 @@ class DashboardPage extends BasePage {
145
}
146
147
pages.add(BalancePage(dashboardViewModel: walletViewModel));
144
- pages.add(Center(
145
- child: Text(
146
- 'SECOND PAGE',
147
- style: TextStyle(
148
- color: Colors.white
149
- ),
150
- ),
151
- ));
148
+ pages.add(TransactionsPage(dashboardViewModel: walletViewModel));
149
150
controller.addListener(() {
151
walletViewModel.currentPage = controller.page;
lib/src/screens/dashboard/widgets/balance_page.dart
+3
-3
@@ -1,5 +1,5 @@
1
import 'package:flutter/material.dart';
2
-import 'package:cake_wallet/view_model/dashboard_view_model.dart';
2
+import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
3
import 'package:cake_wallet/palette.dart';
4
import 'package:flutter_mobx/flutter_mobx.dart';
5
@@ -35,7 +35,7 @@ class BalancePage extends StatelessWidget {
35
Observer(
36
builder: (_) {
37
return Text(
38
- dashboardViewModel.balance.totalBalance,
38
+ dashboardViewModel.balanceViewModel.cryptoBalance,
39
style: TextStyle(
40
fontSize: 54,
41
fontWeight: FontWeight.bold,
@@ -48,7 +48,7 @@ class BalancePage extends StatelessWidget {
48
Observer(
49
builder: (_) {
50
return Text(
51
- '\$ 0.00',
51
+ dashboardViewModel.balanceViewModel.fiatBalance,
52
style: TextStyle(
53
fontSize: 18,
54
fontWeight: FontWeight.w500,
lib/src/screens/dashboard/widgets/button_header.dart
deleted
-255
@@ -1,255 +0,0 @@
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/generated/i18n.dart';
6
-import 'package:flutter_mobx/flutter_mobx.dart';
7
-import 'package:provider/provider.dart';
8
-import 'package:cake_wallet/routes.dart';
9
-import 'package:date_range_picker/date_range_picker.dart' as date_rage_picker;
10
-import 'package:cake_wallet/themes.dart';
11
-import 'package:cake_wallet/theme_changer.dart';
12
-
13
-class ButtonHeader extends SliverPersistentHeaderDelegate {
14
- final sendImage = Image.asset('assets/images/send.png');
15
- final exchangeImage = Image.asset('assets/images/exchange.png');
16
- final buyImage = Image.asset('assets/images/coins.png');
17
-
18
- @override
19
- Widget build(
20
- BuildContext context, double shrinkOffset, bool overlapsContent) {
21
- final _themeChanger = Provider.of<ThemeChanger>(context);
22
- Image filterButton;
23
-
24
- if (_themeChanger.getTheme() == Themes.darkTheme) {
25
- filterButton = Image.asset('assets/images/filter_button.png');
26
- } else {
27
- filterButton = Image.asset('assets/images/filter_light_button.png');
28
- }
29
-
30
- return ClipRRect(
31
- borderRadius: BorderRadius.only(
32
- topLeft: Radius.circular(24), topRight: Radius.circular(24)),
33
- child: Container(
34
- color: Colors.red,
35
-// height: 75,
36
- padding: EdgeInsets.only(top: 26, left: 20, right: 20, bottom: 10),
37
-// color: Theme.of(context).backgroundColor,
38
- child: Stack(
39
- children: <Widget>[
40
- Center(
41
- child: Text(
42
- S.of(context).transactions,
43
- style: TextStyle(
44
- fontSize: 20,
45
- fontWeight: FontWeight.w600,
46
- color: Theme.of(context).primaryTextTheme.title.color),
47
- )),
48
- Positioned(
49
- right: 0,
50
- height: 36,
51
- child: PopupMenuButton<int>(
52
- itemBuilder: (context) => [
53
- PopupMenuItem(
54
- enabled: false,
55
- value: -1,
56
- child: Text(S.of(context).transactions,
57
- style: TextStyle(
58
- fontWeight: FontWeight.bold,
59
- color: Theme.of(context)
60
- .primaryTextTheme
61
- .caption
62
- .color))),
63
-// PopupMenuItem(
64
-// value: 0,
65
-// child: Observer(
66
-// builder: (_) => Row(
67
-// mainAxisAlignment:
68
-// MainAxisAlignment
69
-// .spaceBetween,
70
-// children: [
71
-// Text(S.of(context).incoming),
72
-// Checkbox(
73
-// value: actionListStore
74
-// .transactionFilterStore
75
-// .displayIncoming,
76
-// onChanged: (value) =>
77
-// actionListStore
78
-// .transactionFilterStore
79
-// .toggleIncoming(),
80
-// )
81
-// ]))),
82
-// PopupMenuItem(
83
-// value: 1,
84
-// child: Observer(
85
-// builder: (_) => Row(
86
-// mainAxisAlignment:
87
-// MainAxisAlignment
88
-// .spaceBetween,
89
-// children: [
90
-// Text(S.of(context).outgoing),
91
-// Checkbox(
92
-// value: actionListStore
93
-// .transactionFilterStore
94
-// .displayOutgoing,
95
-// onChanged: (value) =>
96
-// actionListStore
97
-// .transactionFilterStore
98
-// .toggleOutgoing(),
99
-// )
100
-// ]))),
101
- PopupMenuItem(
102
- value: 2,
103
- child: Text(S.of(context).transactions_by_date)),
104
- PopupMenuDivider(),
105
- PopupMenuItem(
106
- enabled: false,
107
- value: -1,
108
- child: Text(S.of(context).trades,
109
- style: TextStyle(
110
- fontWeight: FontWeight.bold,
111
- color: Theme.of(context)
112
- .primaryTextTheme
113
- .caption
114
- .color))),
115
- PopupMenuItem(
116
- value: 3,
117
- child: Observer(
118
- builder: (_) => Row(
119
- mainAxisAlignment:
120
- MainAxisAlignment.spaceBetween,
121
- children: [
122
- Text('XMR.TO'),
123
-// Checkbox(
124
-// value: actionListStore
125
-// .tradeFilterStore
126
-// .displayXMRTO,
127
-// onChanged: (value) =>
128
-// actionListStore
129
-// .tradeFilterStore
130
-// .toggleDisplayExchange(
131
-// ExchangeProviderDescription
132
-// .xmrto),
133
-// )
134
- ]))),
135
- PopupMenuItem(
136
- value: 4,
137
- child: Observer(
138
- builder: (_) => Row(
139
- mainAxisAlignment:
140
- MainAxisAlignment.spaceBetween,
141
- children: [
142
- Text('Change.NOW'),
143
-// Checkbox(
144
-// value: actionListStore
145
-// .tradeFilterStore
146
-// .displayChangeNow,
147
-// onChanged: (value) =>
148
-// actionListStore
149
-// .tradeFilterStore
150
-// .toggleDisplayExchange(
151
-// ExchangeProviderDescription
152
-// .changeNow),
153
-// )
154
- ]))),
155
- PopupMenuItem(
156
- value: 5,
157
- child: Observer(
158
- builder: (_) => Row(
159
- mainAxisAlignment:
160
- MainAxisAlignment.spaceBetween,
161
- children: [
162
- Text('MorphToken'),
163
-// Checkbox(
164
-// value: actionListStore
165
-// .tradeFilterStore
166
-// .displayMorphToken,
167
-// onChanged: (value) =>
168
-// actionListStore
169
-// .tradeFilterStore
170
-// .toggleDisplayExchange(
171
-// ExchangeProviderDescription
172
-// .morphToken),
173
-// )
174
- ])))
175
- ],
176
- child: filterButton,
177
- onSelected: (item) async {
178
- if (item == 2) {
179
- final List<DateTime> picked =
180
- await date_rage_picker.showDatePicker(
181
- context: context,
182
- initialFirstDate:
183
- DateTime.now().subtract(Duration(days: 1)),
184
- initialLastDate: (DateTime.now()),
185
- firstDate: DateTime(2015),
186
- lastDate: DateTime.now().add(Duration(days: 1)));
187
-
188
- if (picked != null && picked.length == 2) {
189
-// actionListStore.transactionFilterStore
190
-// .changeStartDate(picked.first);
191
-// actionListStore.transactionFilterStore
192
-// .changeEndDate(picked.last);
193
- }
194
- }
195
- },
196
- )),
197
- ],
198
- ),
199
- ),
200
- );
201
- }
202
-
203
- @override
204
- double get maxExtent => 164;
205
-
206
- @override
207
- double get minExtent => 66;
208
-
209
- @override
210
- bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) => true;
211
-
212
- Widget actionButton(
213
- {BuildContext context,
214
- @required Image image,
215
- @required String title,
216
- @required String route}) {
217
- return Container(
218
- width: MediaQuery.of(context).size.width,
219
- child: Column(
220
- mainAxisAlignment: MainAxisAlignment.start,
221
- crossAxisAlignment: CrossAxisAlignment.center,
222
- children: <Widget>[
223
- GestureDetector(
224
- onTap: () {
225
- if (route.isNotEmpty) {
226
- Navigator.of(context, rootNavigator: true).pushNamed(route);
227
- }
228
- },
229
- child: Container(
230
- height: 48,
231
- width: 48,
232
- alignment: Alignment.center,
233
- decoration: BoxDecoration(
234
- color: Theme.of(context).primaryTextTheme.subhead.color,
235
- shape: BoxShape.circle),
236
- child: image,
237
- ),
238
- ),
239
- Padding(
240
- padding: EdgeInsets.only(top: 12),
241
- child: Text(
242
- title,
243
- style: TextStyle(
244
- fontSize: 16,
245
- fontWeight: FontWeight.w600,
246
- color: Color.fromRGBO(140, 153, 201,
247
- 0.8) // Theme.of(context).primaryTextTheme.caption.color
248
- ),
249
- ),
250
- )
251
- ],
252
- ),
253
- );
254
- }
255
-}
lib/src/screens/dashboard/widgets/header_row.dart
new
+187
@@ -0,0 +1,187 @@
1
+import 'package:flutter/material.dart';
2
+import 'package:cake_wallet/palette.dart';
3
+import 'package:cake_wallet/generated/i18n.dart';
4
+import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
5
+import 'package:cake_wallet/src/domain/exchange/exchange_provider_description.dart';
6
+import 'package:date_range_picker/date_range_picker.dart' as date_rage_picker;
7
+import 'package:flutter_mobx/flutter_mobx.dart';
8
+
9
+class HeaderRow extends StatelessWidget {
10
+ HeaderRow({this.dashboardViewModel});
11
+
12
+ final DashboardViewModel dashboardViewModel;
13
+
14
+ final filterIcon = Image.asset('assets/images/filter_icon.png',
15
+ color: PaletteDark.wildBlue);
16
+
17
+ @override
18
+ Widget build(BuildContext context) {
19
+ return Container(
20
+ height: 52,
21
+ color: Colors.transparent,
22
+ padding: EdgeInsets.only(left: 24, right: 24),
23
+ child: Row(
24
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
25
+ crossAxisAlignment: CrossAxisAlignment.center,
26
+ children: <Widget>[
27
+ Text(
28
+ S.of(context).transactions,
29
+ style: TextStyle(
30
+ fontSize: 20,
31
+ fontWeight: FontWeight.w500,
32
+ color: Colors.white
33
+ ),
34
+ ),
35
+ PopupMenuButton<int>(
36
+ itemBuilder: (context) => [
37
+ PopupMenuItem(
38
+ enabled: false,
39
+ value: -1,
40
+ child: Text(S.of(context).transactions,
41
+ style: TextStyle(
42
+ fontWeight: FontWeight.bold,
43
+ color: Theme.of(context).primaryTextTheme.caption.color))),
44
+ PopupMenuItem(
45
+ value: 0,
46
+ child: Observer(
47
+ builder: (_) => Row(
48
+ mainAxisAlignment:
49
+ MainAxisAlignment
50
+ .spaceBetween,
51
+ children: [
52
+ Text(S.of(context).incoming),
53
+ Checkbox(
54
+ value: dashboardViewModel
55
+ .transactionFilterStore
56
+ .displayIncoming,
57
+ onChanged: (value) => dashboardViewModel
58
+ .transactionFilterStore
59
+ .toggleIncoming()
60
+ )
61
+ ]))),
62
+ PopupMenuItem(
63
+ value: 1,
64
+ child: Observer(
65
+ builder: (_) => Row(
66
+ mainAxisAlignment:
67
+ MainAxisAlignment
68
+ .spaceBetween,
69
+ children: [
70
+ Text(S.of(context).outgoing),
71
+ Checkbox(
72
+ value: dashboardViewModel
73
+ .transactionFilterStore
74
+ .displayOutgoing,
75
+ onChanged: (value) => dashboardViewModel
76
+ .transactionFilterStore
77
+ .toggleOutgoing(),
78
+ )
79
+ ]))),
80
+ PopupMenuItem(
81
+ value: 2,
82
+ child:
83
+ Text(S.of(context).transactions_by_date)),
84
+ PopupMenuDivider(),
85
+ PopupMenuItem(
86
+ enabled: false,
87
+ value: -1,
88
+ child: Text(S.of(context).trades,
89
+ style: TextStyle(
90
+ fontWeight: FontWeight.bold,
91
+ color: Theme.of(context).primaryTextTheme.caption.color))),
92
+ PopupMenuItem(
93
+ value: 3,
94
+ child: Observer(
95
+ builder: (_) => Row(
96
+ mainAxisAlignment:
97
+ MainAxisAlignment
98
+ .spaceBetween,
99
+ children: [
100
+ Text('XMR.TO'),
101
+ Checkbox(
102
+ value: dashboardViewModel
103
+ .tradeFilterStore
104
+ .displayXMRTO,
105
+ onChanged: (value) => dashboardViewModel
106
+ .tradeFilterStore
107
+ .toggleDisplayExchange(
108
+ ExchangeProviderDescription
109
+ .xmrto),
110
+ )
111
+ ]))),
112
+ PopupMenuItem(
113
+ value: 4,
114
+ child: Observer(
115
+ builder: (_) => Row(
116
+ mainAxisAlignment:
117
+ MainAxisAlignment
118
+ .spaceBetween,
119
+ children: [
120
+ Text('Change.NOW'),
121
+ Checkbox(
122
+ value: dashboardViewModel
123
+ .tradeFilterStore
124
+ .displayChangeNow,
125
+ onChanged: (value) => dashboardViewModel
126
+ .tradeFilterStore
127
+ .toggleDisplayExchange(
128
+ ExchangeProviderDescription
129
+ .changeNow),
130
+ )
131
+ ]))),
132
+ PopupMenuItem(
133
+ value: 5,
134
+ child: Observer(
135
+ builder: (_) => Row(
136
+ mainAxisAlignment:
137
+ MainAxisAlignment
138
+ .spaceBetween,
139
+ children: [
140
+ Text('MorphToken'),
141
+ Checkbox(
142
+ value: dashboardViewModel
143
+ .tradeFilterStore
144
+ .displayMorphToken,
145
+ onChanged: (value) => dashboardViewModel
146
+ .tradeFilterStore
147
+ .toggleDisplayExchange(
148
+ ExchangeProviderDescription
149
+ .morphToken),
150
+ )
151
+ ])))
152
+ ],
153
+ child: Container(
154
+ height: 36,
155
+ width: 36,
156
+ decoration: BoxDecoration(
157
+ shape: BoxShape.circle,
158
+ color: PaletteDark.oceanBlue
159
+ ),
160
+ child: filterIcon,
161
+ ),
162
+ onSelected: (item) async {
163
+ if (item == 2) {
164
+ final picked =
165
+ await date_rage_picker.showDatePicker(
166
+ context: context,
167
+ initialFirstDate: DateTime.now()
168
+ .subtract(Duration(days: 1)),
169
+ initialLastDate: (DateTime.now()),
170
+ firstDate: DateTime(2015),
171
+ lastDate: DateTime.now()
172
+ .add(Duration(days: 1)));
173
+
174
+ if (picked != null && picked.length == 2) {
175
+ dashboardViewModel.transactionFilterStore
176
+ .changeStartDate(picked.first);
177
+ dashboardViewModel.transactionFilterStore
178
+ .changeEndDate(picked.last);
179
+ }
180
+ }
181
+ },
182
+ ),
183
+ ],
184
+ ),
185
+ );
186
+ }
187
+}
\ No newline at end of file
lib/src/screens/dashboard/widgets/sync_indicator.dart
+1
-1
@@ -1,5 +1,5 @@
1
import 'package:flutter/material.dart';
2
-import 'package:cake_wallet/view_model/dashboard_view_model.dart';
2
+import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
3
import 'package:cake_wallet/palette.dart';
4
import 'package:flutter_mobx/flutter_mobx.dart';
5
import 'package:cake_wallet/src/domain/common/sync_status.dart';
lib/src/screens/dashboard/widgets/trade_history_panel.dart
deleted
-322
@@ -1,322 +0,0 @@
1
-import 'package:cake_wallet/generated/i18n.dart';
2
-import 'package:cake_wallet/theme_changer.dart';
3
-import 'package:cake_wallet/themes.dart';
4
-import 'package:flutter/cupertino.dart';
5
-import 'package:flutter/material.dart';
6
-import 'package:flutter_mobx/flutter_mobx.dart';
7
-import 'package:intl/intl.dart';
8
-import 'package:provider/provider.dart';
9
-import 'package:cake_wallet/routes.dart';
10
-import 'package:cake_wallet/view_model/dashboard_view_model.dart';
11
-import 'package:cake_wallet/src/domain/common/balance_display_mode.dart';
12
-import 'package:cake_wallet/src/stores/action_list/action_list_store.dart';
13
-import 'package:cake_wallet/src/stores/action_list/date_section_item.dart';
14
-import 'package:cake_wallet/src/stores/action_list/trade_list_item.dart';
15
-import 'package:cake_wallet/src/stores/action_list/transaction_list_item.dart';
16
-import 'package:cake_wallet/src/stores/settings/settings_store.dart';
17
-import 'date_section_raw.dart';
18
-import 'trade_row.dart';
19
-import 'transaction_raw.dart';
20
-import 'button_header.dart';
21
-import 'package:date_range_picker/date_range_picker.dart' as date_rage_picker;
22
-
23
-class TradeHistoryPanel extends StatefulWidget {
24
- TradeHistoryPanel({this.dashboardViewModel});
25
-
26
- final DashboardViewModel dashboardViewModel;
27
-
28
- @override
29
- TradeHistoryPanelState createState() => TradeHistoryPanelState();
30
-}
31
-
32
-class TradeHistoryPanelState extends State<TradeHistoryPanel> {
33
- final _listObserverKey = GlobalKey();
34
- final _listKey = GlobalKey();
35
-
36
- double panelHeight;
37
- double screenHeight;
38
-
39
- @override
40
- void initState() {
41
- panelHeight = 0;
42
- screenHeight = 0;
43
- super.initState();
44
- WidgetsBinding.instance.addPostFrameCallback(afterLayout);
45
- }
46
-
47
- void afterLayout(dynamic _) {
48
- screenHeight = MediaQuery.of(context).size.height;
49
- setState(() {
50
- panelHeight = screenHeight;
51
- });
52
- }
53
-
54
- @override
55
- Widget build(BuildContext context) {
56
- // AnimatedContainer(
57
-// width: MediaQuery.of(context).size.width,
58
-// height: panelHeight,
59
-// duration: Duration(milliseconds: 1000),
60
-// curve: Curves.fastOutSlowIn,
61
-// child: )
62
-
63
- final transactionDateFormat = DateFormat('HH:mm');
64
- final _themeChanger = Provider.of<ThemeChanger>(context);
65
- final filterButton = Image.asset(
66
- _themeChanger.getTheme() == Themes.darkTheme
67
- ? 'assets/images/filter_button.png'
68
- : 'assets/images/filter_light_button.png',
69
- height: 36);
70
-
71
- return ClipRRect(
72
- borderRadius: BorderRadius.only(
73
- topLeft: Radius.circular(20), topRight: Radius.circular(20)),
74
- child: Container(
75
- color: Colors.white,
76
- child: Column(children: [
77
- Container(
78
- padding:
79
- EdgeInsets.only(top: 32, left: 20, right: 20, bottom: 20),
80
- color: Theme.of(context).backgroundColor,
81
- child: Stack(
82
- children: <Widget>[
83
- SizedBox(height: 37), // Force stack height
84
- Center(
85
- child: Text(S.of(context).transactions,
86
- style: TextStyle(
87
- fontSize: 20,
88
- fontWeight: FontWeight.w600,
89
- color: Theme.of(context)
90
- .primaryTextTheme
91
- .title
92
- .color))),
93
- Positioned(
94
- right: 0,
95
- child: PopupMenuButton<int>(
96
- itemBuilder: (context) => [
97
- PopupMenuItem(
98
- enabled: false,
99
- value: -1,
100
- child: Text(S.of(context).transactions,
101
- style: TextStyle(
102
- fontWeight: FontWeight.bold,
103
- color: Theme.of(context)
104
- .primaryTextTheme
105
- .caption
106
- .color))),
107
-// PopupMenuItem(
108
-// value: 0,
109
-// child: Observer(
110
-// builder: (_) => Row(
111
-// mainAxisAlignment:
112
-// MainAxisAlignment
113
-// .spaceBetween,
114
-// children: [
115
-// Text(S.of(context).incoming),
116
-// Checkbox(
117
-// value: actionListStore
118
-// .transactionFilterStore
119
-// .displayIncoming,
120
-// onChanged: (value) =>
121
-// actionListStore
122
-// .transactionFilterStore
123
-// .toggleIncoming(),
124
-// )
125
-// ]))),
126
-// PopupMenuItem(
127
-// value: 1,
128
-// child: Observer(
129
-// builder: (_) => Row(
130
-// mainAxisAlignment:
131
-// MainAxisAlignment
132
-// .spaceBetween,
133
-// children: [
134
-// Text(S.of(context).outgoing),
135
-// Checkbox(
136
-// value: actionListStore
137
-// .transactionFilterStore
138
-// .displayOutgoing,
139
-// onChanged: (value) =>
140
-// actionListStore
141
-// .transactionFilterStore
142
-// .toggleOutgoing(),
143
-// )
144
-// ]))),
145
- PopupMenuItem(
146
- value: 2,
147
- child:
148
- Text(S.of(context).transactions_by_date)),
149
- PopupMenuDivider(),
150
- PopupMenuItem(
151
- enabled: false,
152
- value: -1,
153
- child: Text(S.of(context).trades,
154
- style: TextStyle(
155
- fontWeight: FontWeight.bold,
156
- color: Theme.of(context)
157
- .primaryTextTheme
158
- .caption
159
- .color))),
160
- PopupMenuItem(
161
- value: 3,
162
- child: Observer(
163
- builder: (_) => Row(
164
- mainAxisAlignment:
165
- MainAxisAlignment.spaceBetween,
166
- children: [
167
- Text('XMR.TO'),
168
-// Checkbox(
169
-// value: actionListStore
170
-// .tradeFilterStore
171
-// .displayXMRTO,
172
-// onChanged: (value) =>
173
-// actionListStore
174
-// .tradeFilterStore
175
-// .toggleDisplayExchange(
176
-// ExchangeProviderDescription
177
-// .xmrto),
178
-// )
179
- ]))),
180
- PopupMenuItem(
181
- value: 4,
182
- child: Observer(
183
- builder: (_) => Row(
184
- mainAxisAlignment:
185
- MainAxisAlignment.spaceBetween,
186
- children: [
187
- Text('Change.NOW'),
188
-// Checkbox(
189
-// value: actionListStore
190
-// .tradeFilterStore
191
-// .displayChangeNow,
192
-// onChanged: (value) =>
193
-// actionListStore
194
-// .tradeFilterStore
195
-// .toggleDisplayExchange(
196
-// ExchangeProviderDescription
197
-// .changeNow),
198
-// )
199
- ]))),
200
- PopupMenuItem(
201
- value: 5,
202
- child: Observer(
203
- builder: (_) => Row(
204
- mainAxisAlignment:
205
- MainAxisAlignment.spaceBetween,
206
- children: [
207
- Text('MorphToken'),
208
-// Checkbox(
209
-// value: actionListStore
210
-// .tradeFilterStore
211
-// .displayMorphToken,
212
-// onChanged: (value) =>
213
-// actionListStore
214
-// .tradeFilterStore
215
-// .toggleDisplayExchange(
216
-// ExchangeProviderDescription
217
-// .morphToken),
218
-// )
219
- ])))
220
- ],
221
- child: filterButton,
222
- onSelected: (item) async {
223
- if (item == 2) {
224
- final picked =
225
- await date_rage_picker.showDatePicker(
226
- context: context,
227
- initialFirstDate: DateTime.now()
228
- .subtract(Duration(days: 1)),
229
- initialLastDate: (DateTime.now()),
230
- firstDate: DateTime(2015),
231
- lastDate: DateTime.now()
232
- .add(Duration(days: 1)));
233
-
234
- if (picked != null && picked.length == 2) {
235
-// actionListStore.transactionFilterStore
236
-// .changeStartDate(picked.first);
237
-// actionListStore.transactionFilterStore
238
-// .changeEndDate(picked.last);
239
- }
240
- }
241
- },
242
- )),
243
- ],
244
- ),
245
- ),
246
- widget.dashboardViewModel.transactions?.isNotEmpty ?? false
247
- ? ListView.separated(
248
- physics: NeverScrollableScrollPhysics(),
249
- shrinkWrap: true,
250
- itemCount: widget.dashboardViewModel.transactions.length,
251
- itemBuilder: (_, index) {
252
- final item =
253
- widget.dashboardViewModel.transactions[index];
254
-
255
- if (item is DateSectionItem) {
256
- return DateSectionRaw(date: item.date);
257
- }
258
-
259
- if (item is TransactionListItem) {
260
- final transaction = item.transaction;
261
- final savedDisplayMode = BalanceDisplayMode.all;
262
- //settingsStore
263
-// .balanceDisplayMode;
264
- final formattedAmount = savedDisplayMode ==
265
- BalanceDisplayMode.hiddenBalance
266
- ? '---'
267
- : transaction.amountFormatted();
268
- final formattedFiatAmount = savedDisplayMode ==
269
- BalanceDisplayMode.hiddenBalance
270
- ? '---'
271
- : transaction.fiatAmount(); // symbol ???
272
-
273
- return TransactionRow(
274
- onTap: () => Navigator.of(context).pushNamed(
275
- Routes.transactionDetails,
276
- arguments: transaction),
277
- direction: transaction.direction,
278
- formattedDate: transactionDateFormat
279
- .format(transaction.date),
280
- formattedAmount: formattedAmount,
281
- formattedFiatAmount: formattedFiatAmount,
282
- isPending: transaction.isPending);
283
- }
284
-
285
- if (item is TradeListItem) {
286
- final trade = item.trade;
287
- final savedDisplayMode = BalanceDisplayMode.all;
288
- //settingsStore
289
- // .balanceDisplayMode;
290
- final formattedAmount = trade.amount != null
291
- ? savedDisplayMode ==
292
- BalanceDisplayMode.hiddenBalance
293
- ? '---'
294
- : trade.amountFormatted()
295
- : trade.amount;
296
-
297
- return TradeRow(
298
- onTap: () => Navigator.of(context).pushNamed(
299
- Routes.tradeDetails,
300
- arguments: trade),
301
- provider: trade.provider,
302
- from: trade.from,
303
- to: trade.to,
304
- createdAtFormattedDate:
305
- transactionDateFormat.format(trade.createdAt),
306
- formattedAmount: formattedAmount);
307
- }
308
-
309
- return Container(
310
- color: Theme.of(context).backgroundColor,
311
- height: 1);
312
- },
313
- separatorBuilder: (_, __) =>
314
- Container(height: 14, color: Colors.white),
315
- )
316
- : Padding(
317
- padding: EdgeInsets.all(20),
318
- child: Text('Your transactions will be displayed here!',
319
- style: TextStyle(color: Colors.grey)))
320
- ]))); //,
321
- }
322
-}
lib/src/screens/dashboard/widgets/trade_row.dart
+1
-1
@@ -37,7 +37,7 @@ class TradeRow extends StatelessWidget {
37
child: Padding(
38
padding: const EdgeInsets.only(left: 12),
39
child: Container(
40
- height: 42,
40
+ height: 46,
41
child: Column(
42
mainAxisAlignment: MainAxisAlignment.spaceBetween,
43
mainAxisSize: MainAxisSize.max,
lib/src/screens/dashboard/widgets/transaction_raw.dart
+1
-1
@@ -46,7 +46,7 @@ class TransactionRow extends StatelessWidget {
46
child: Padding(
47
padding: const EdgeInsets.only(left: 12),
48
child: Container(
49
- height: 42,
49
+ height: 46,
50
child: Column(
51
mainAxisAlignment: MainAxisAlignment.spaceBetween,
52
mainAxisSize: MainAxisSize.max,
lib/src/screens/dashboard/widgets/transactions_page.dart
new
+98
@@ -0,0 +1,98 @@
1
+import 'package:flutter/material.dart';
2
+import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
3
+import 'package:flutter_mobx/flutter_mobx.dart';
4
+import 'package:cake_wallet/src/screens/dashboard/widgets/header_row.dart';
5
+import 'package:cake_wallet/src/screens/dashboard/widgets/date_section_raw.dart';
6
+import 'package:cake_wallet/src/screens/dashboard/widgets/trade_row.dart';
7
+import 'package:cake_wallet/src/screens/dashboard/widgets/transaction_raw.dart';
8
+import 'package:cake_wallet/view_model/dashboard/trade_list_item.dart';
9
+import 'package:cake_wallet/view_model/dashboard/transaction_list_item.dart';
10
+import 'package:cake_wallet/view_model/dashboard/date_section_item.dart';
11
+import 'package:intl/intl.dart';
12
+import 'package:cake_wallet/routes.dart';
13
+import 'package:cake_wallet/generated/i18n.dart';
14
+
15
+class TransactionsPage extends StatelessWidget {
16
+ TransactionsPage({@required this.dashboardViewModel});
17
+
18
+ final DashboardViewModel dashboardViewModel;
19
+
20
+ @override
21
+ Widget build(BuildContext context) {
22
+ return Container(
23
+ padding: EdgeInsets.only(
24
+ top: 24,
25
+ bottom: 24
26
+ ),
27
+ child: Column(
28
+ children: <Widget>[
29
+ HeaderRow(dashboardViewModel: dashboardViewModel),
30
+ Expanded(
31
+ child: Observer(
32
+ builder: (_) {
33
+ final items = dashboardViewModel.items;
34
+
35
+ return items?.isNotEmpty ?? false
36
+ ? ListView.builder(
37
+ itemCount: items.length,
38
+ itemBuilder: (context, index) {
39
+
40
+ final item = items[index];
41
+
42
+ if (item is DateSectionItem) {
43
+ return DateSectionRaw(date: item.date);
44
+ }
45
+
46
+ if (item is TransactionListItem) {
47
+ final transaction = item.transaction;
48
+
49
+ return TransactionRow(
50
+ onTap: () => Navigator.of(context).pushNamed(
51
+ Routes.transactionDetails,
52
+ arguments: transaction),
53
+ direction: transaction.direction,
54
+ formattedDate: DateFormat('HH:mm')
55
+ .format(transaction.date),
56
+ formattedAmount: item.formattedCryptoAmount,
57
+ formattedFiatAmount: item.formattedFiatAmount,
58
+ isPending: transaction.isPending);
59
+ }
60
+
61
+ if (item is TradeListItem) {
62
+ final trade = item.trade;
63
+
64
+ return TradeRow(
65
+ onTap: () => Navigator.of(context).pushNamed(
66
+ Routes.tradeDetails,
67
+ arguments: trade),
68
+ provider: trade.provider,
69
+ from: trade.from,
70
+ to: trade.to,
71
+ createdAtFormattedDate:
72
+ DateFormat('HH:mm').format(trade.createdAt),
73
+ formattedAmount: item.tradeFormattedAmount
74
+ );
75
+ }
76
+
77
+ return Container(
78
+ color: Theme.of(context).backgroundColor,
79
+ height: 1);
80
+ }
81
+ )
82
+ : Center(
83
+ child: Text(
84
+ S.of(context).placeholder_transactions,
85
+ style: TextStyle(
86
+ fontSize: 14,
87
+ color: Colors.grey
88
+ ),
89
+ ),
90
+ );
91
+ }
92
+ )
93
+ )
94
+ ],
95
+ ),
96
+ );
97
+ }
98
+}
\ No newline at end of file
lib/src/screens/dashboard/widgets/wallet_card.dart
deleted
-508
@@ -1,508 +0,0 @@
1
-import 'dart:async';
2
-import 'package:cake_wallet/palette.dart';
3
-import 'package:flutter/services.dart';
4
-import 'package:provider/provider.dart';
5
-import 'package:flutter/cupertino.dart';
6
-import 'package:flutter/material.dart';
7
-import 'package:flutter_mobx/flutter_mobx.dart';
8
-import 'package:cake_wallet/src/domain/common/balance_display_mode.dart';
9
-import 'package:cake_wallet/src/stores/settings/settings_store.dart';
10
-import 'package:cake_wallet/generated/i18n.dart';
11
-import 'package:cake_wallet/src/domain/common/sync_status.dart';
12
-import 'package:cake_wallet/src/screens/receive/widgets/qr_image.dart';
13
-import 'package:cake_wallet/routes.dart';
14
-import 'package:cake_wallet/view_model/dashboard_view_model.dart';
15
-
16
-class WalletCard extends StatefulWidget {
17
- WalletCard({this.walletVM});
18
-
19
- final DashboardViewModel walletVM;
20
-
21
- @override
22
- WalletCardState createState() => WalletCardState();
23
-}
24
-
25
-class WalletCardState extends State<WalletCard> {
26
- final _syncingObserverKey = GlobalKey();
27
- final _balanceObserverKey = GlobalKey();
28
- final _addressObserverKey = GlobalKey();
29
-
30
- double cardWidth;
31
- double cardHeight;
32
- double screenWidth;
33
- double opacity;
34
- bool isDraw;
35
- bool isFrontSide;
36
-
37
- @override
38
- void initState() {
39
- cardWidth = 0;
40
- cardHeight = 220;
41
- screenWidth = 0;
42
- opacity = 0;
43
- isDraw = false;
44
- isFrontSide = true;
45
- super.initState();
46
- WidgetsBinding.instance.addPostFrameCallback(afterLayout);
47
- }
48
-
49
- void afterLayout(dynamic _) {
50
- screenWidth = MediaQuery.of(context).size.width - 20;
51
- setState(() {
52
- cardWidth = screenWidth;
53
- opacity = 1;
54
- });
55
- Timer(Duration(milliseconds: 500), () => setState(() => isDraw = true));
56
- }
57
-
58
- @override
59
- Widget build(BuildContext context) {
60
- final colorsSync = [
61
- Theme.of(context).cardTheme.color,
62
- Theme.of(context).hoverColor
63
- ];
64
-
65
- return Container(
66
- width: double.infinity,
67
- height: cardHeight,
68
- alignment: Alignment.centerRight,
69
- decoration: BoxDecoration(
70
- borderRadius: BorderRadius.only(
71
- topLeft: Radius.circular(14), bottomLeft: Radius.circular(14))),
72
- child: AnimatedContainer(
73
- alignment: Alignment.centerLeft,
74
- width: cardWidth,
75
- height: cardHeight,
76
- duration: Duration(milliseconds: 500),
77
- curve: Curves.fastOutSlowIn,
78
- decoration: BoxDecoration(
79
- borderRadius: BorderRadius.only(
80
- topLeft: Radius.circular(14),
81
- bottomLeft: Radius.circular(14)),
82
- color: Theme.of(context).focusColor),
83
- child: ClipRRect(
84
- borderRadius: BorderRadius.only(
85
- topLeft: Radius.circular(10), bottomLeft: Radius.circular(10)),
86
- child: Container(
87
- width: cardWidth,
88
- height: cardHeight,
89
- color: Theme.of(context).cardColor,
90
- child: isFrontSide
91
- ? frontSide(colorsSync)
92
- : InkWell(
93
- onTap: () => setState(() => isFrontSide = true),
94
- child: backSide(colorsSync)),
95
- ),
96
- )),
97
- );
98
- }
99
-
100
- Widget frontSide(List<Color> colorsSync) {
101
- final settingsStore = Provider.of<SettingsStore>(context);
102
- final triangleButton = Image.asset(
103
- 'assets/images/triangle.png',
104
- color: Theme.of(context).primaryTextTheme.title.color,
105
- );
106
-
107
- return Observer(
108
- key: _syncingObserverKey,
109
- builder: (_) {
110
- final status = widget.walletVM.status;
111
- final statusText = status.title();
112
- final progress = status.progress();
113
- final indicatorOffset = progress * cardWidth;
114
- final indicatorWidth =
115
- progress <= 1 ? cardWidth - indicatorOffset : 0.0;
116
- var descriptionText = '';
117
-
118
- if (status is SyncingSyncStatus) {
119
- descriptionText = S.of(context).Blocks_remaining(status.toString());
120
- }
121
-
122
- if (status is FailedSyncStatus) {
123
- descriptionText = S.of(context).please_try_to_connect_to_another_node;
124
- }
125
-
126
- return Container(
127
- width: cardWidth,
128
- height: cardHeight,
129
- color: Colors.white,
130
- child: Stack(
131
- children: <Widget>[
132
- progress <= 1
133
- ? Positioned(
134
- left: indicatorOffset,
135
- top: 0,
136
- bottom: 0,
137
- child: Container(
138
- width: indicatorWidth,
139
- height: cardHeight,
140
- color: Color.fromRGBO(227, 238, 249, 1),
141
- ))
142
- : Offstage(),
143
- isDraw
144
- ? Positioned(
145
- left: 24,
146
- right: 24,
147
- top: 32,
148
- bottom: 24,
149
- child: Container(
150
- child: Column(
151
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
152
- children: <Widget>[
153
- Row(
154
- crossAxisAlignment: CrossAxisAlignment.start,
155
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
156
- children: <Widget>[
157
- Column(
158
- crossAxisAlignment: CrossAxisAlignment.start,
159
- children: <Widget>[
160
- InkWell(
161
- onTap: () => Navigator.of(context)
162
- .pushNamed(Routes.walletList),
163
- child: Row(
164
- children: <Widget>[
165
- Text(
166
- widget.walletVM.name,
167
- style: TextStyle(
168
- fontSize: 20,
169
- fontWeight: FontWeight.bold,
170
- color: Theme.of(context)
171
- .primaryTextTheme
172
- .title
173
- .color),
174
- ),
175
- SizedBox(width: 10),
176
- triangleButton
177
- ],
178
- ),
179
- ),
180
- SizedBox(height: 5),
181
- if (widget.walletVM.subname?.isNotEmpty ??
182
- false)
183
- Text(
184
- widget.walletVM.subname,
185
- style: TextStyle(
186
- fontSize: 12,
187
- fontWeight: FontWeight.w600,
188
- color: Theme.of(context)
189
- .primaryTextTheme
190
- .caption
191
- .color),
192
- )
193
- ],
194
- ),
195
- InkWell(
196
- onTap: () =>
197
- setState(() => isFrontSide = false),
198
- child: Container(
199
- width: 98,
200
- height: 32,
201
- alignment: Alignment.center,
202
- decoration: BoxDecoration(
203
- color: Theme.of(context)
204
- .accentTextTheme
205
- .subtitle
206
- .backgroundColor,
207
- border: Border.all(
208
- color: Color.fromRGBO(
209
- 219, 231, 237, 1)),
210
- // FIXME
211
- borderRadius: BorderRadius.all(
212
- Radius.circular(16))),
213
- child: Text(
214
- 'Receive',
215
- style: TextStyle(
216
- fontSize: 12,
217
- fontWeight: FontWeight.w600,
218
- color: Theme.of(context)
219
- .primaryTextTheme
220
- .title
221
- .color),
222
- )),
223
- )
224
- ],
225
- ),
226
- status is SyncedSyncStatus
227
- ? Observer(
228
- key: _balanceObserverKey,
229
- builder: (_) {
230
- final balanceDisplayMode =
231
- BalanceDisplayMode.availableBalance;
232
-// settingsStore.balanceDisplayMode;
233
- final symbol =
234
- settingsStore.fiatCurrency.toString();
235
- var balance = '---';
236
- var fiatBalance = '---';
237
-
238
- if (balanceDisplayMode ==
239
- BalanceDisplayMode.availableBalance) {
240
- balance = widget.walletVM.balance
241
- .unlockedBalance ??
242
- '0.0';
243
- fiatBalance = '\$ 0.00';
244
-// '$symbol ${balanceStore.fiatUnlockedBalance}';
245
- }
246
-
247
- if (balanceDisplayMode ==
248
- BalanceDisplayMode.fullBalance) {
249
- balance = widget.walletVM.balance
250
- .totalBalance ??
251
- '0.0';
252
- fiatBalance = '\$ 0.00';
253
-// '$symbol ${balanceStore.fiatFullBalance}';
254
- }
255
-
256
- return Row(
257
- crossAxisAlignment:
258
- CrossAxisAlignment.end,
259
- mainAxisAlignment:
260
- MainAxisAlignment.spaceBetween,
261
- children: <Widget>[
262
- Column(
263
- mainAxisAlignment:
264
- MainAxisAlignment.spaceBetween,
265
- crossAxisAlignment:
266
- CrossAxisAlignment.start,
267
- children: <Widget>[
268
- Text(
269
- balanceDisplayMode.toString(),
270
- style: TextStyle(
271
- fontSize: 12,
272
- color: Theme.of(context)
273
- .primaryTextTheme
274
- .caption
275
- .color),
276
- ),
277
- SizedBox(height: 5),
278
- Container(
279
- height: 36,
280
- child: Text(
281
- balance,
282
- style: TextStyle(
283
- fontSize: 32,
284
- color: Theme.of(context)
285
- .primaryTextTheme
286
- .title
287
- .color,
288
- fontWeight:
289
- FontWeight.bold),
290
- ))
291
- ],
292
- ),
293
- Text(
294
- fiatBalance,
295
- style: TextStyle(
296
- fontSize: 14,
297
- fontWeight: FontWeight.w600,
298
-// FIXME
299
-// color: Theme.of(context)
300
-// .primaryTextTheme
301
-// .title
302
-// .color,
303
- color: Color.fromRGBO(
304
- 72, 89, 109, 1)),
305
- )
306
- ],
307
- );
308
- })
309
- : Row(
310
- crossAxisAlignment: CrossAxisAlignment.end,
311
- mainAxisAlignment:
312
- MainAxisAlignment.spaceBetween,
313
- children: <Widget>[
314
- Column(
315
- crossAxisAlignment:
316
- CrossAxisAlignment.start,
317
- children: <Widget>[
318
- Text(
319
- statusText,
320
- style: TextStyle(
321
- fontSize: 12,
322
- fontWeight: FontWeight.w600,
323
- color: Theme.of(context)
324
- .primaryTextTheme
325
- .caption
326
- .color),
327
- ),
328
- SizedBox(height: 5),
329
- Text(
330
- descriptionText,
331
- style: TextStyle(
332
- fontSize: 14,
333
- fontWeight: FontWeight.w600,
334
- color: Theme.of(context)
335
- .primaryTextTheme
336
- .title
337
- .color),
338
- )
339
- ],
340
- )
341
- ],
342
- )
343
- ],
344
- ),
345
- ))
346
- : Offstage()
347
- ],
348
- ),
349
- );
350
- },
351
- );
352
- }
353
-
354
- Widget backSide(List<Color> colorsSync) {
355
- final rightArrow = Image.asset('assets/images/right_arrow.png',
356
- color: Theme.of(context).primaryTextTheme.title.color);
357
- var messageBoxHeight = 0.0;
358
- var messageBoxWidth = cardWidth - 10;
359
-
360
- return Observer(
361
- key: _addressObserverKey,
362
- builder: (_) {
363
- return Container(
364
- width: cardWidth,
365
- height: cardHeight,
366
- alignment: Alignment.topCenter,
367
- child: Stack(
368
- alignment: Alignment.topRight,
369
- children: <Widget>[
370
- Container(
371
- width: cardWidth,
372
- height: cardHeight,
373
- padding:
374
- EdgeInsets.only(left: 24, right: 24, top: 32, bottom: 32),
375
- decoration: BoxDecoration(
376
- borderRadius: BorderRadius.only(
377
- topLeft: Radius.circular(10),
378
- bottomLeft: Radius.circular(10)),
379
- gradient: LinearGradient(
380
- colors: colorsSync,
381
- begin: Alignment.topCenter,
382
- end: Alignment.bottomCenter)),
383
- child: Column(
384
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
385
- children: <Widget>[
386
- Row(
387
- crossAxisAlignment: CrossAxisAlignment.start,
388
- children: <Widget>[
389
- Expanded(
390
- child: Container(
391
- child: Column(
392
- crossAxisAlignment: CrossAxisAlignment.start,
393
- children: <Widget>[
394
- Text(
395
- S.current.card_address,
396
- style: TextStyle(
397
- fontSize: 12,
398
- color: Theme.of(context)
399
- .primaryTextTheme
400
- .caption
401
- .color),
402
- ),
403
- SizedBox(height: 10),
404
- GestureDetector(
405
- onTap: () {
406
- Clipboard.setData(ClipboardData(
407
- text: widget.walletVM.address));
408
- _addressObserverKey.currentState
409
- .setState(() {
410
- messageBoxHeight = 20;
411
- messageBoxWidth = cardWidth;
412
- });
413
- Timer(Duration(milliseconds: 1000), () {
414
- try {
415
- _addressObserverKey.currentState
416
- .setState(() {
417
- messageBoxHeight = 0;
418
- messageBoxWidth = cardWidth - 10;
419
- });
420
- } catch (e) {
421
- print('${e.toString()}');
422
- }
423
- });
424
- },
425
- child: Text(
426
- widget.walletVM.address,
427
- style: TextStyle(
428
- fontSize: 12,
429
- fontWeight: FontWeight.w600,
430
- color: Theme.of(context)
431
- .primaryTextTheme
432
- .title
433
- .color),
434
- ),
435
- )
436
- ],
437
- ),
438
- )),
439
- SizedBox(width: 10),
440
- Container(
441
- width: 90,
442
- height: 90,
443
- child: QrImage(
444
- data: widget.walletVM.address,
445
- backgroundColor: Colors.transparent,
446
- foregroundColor: Theme.of(context)
447
- .primaryTextTheme
448
- .caption
449
- .color),
450
- )
451
- ],
452
- ),
453
- Container(
454
- height: 44,
455
- padding: EdgeInsets.only(left: 20, right: 20),
456
- alignment: Alignment.center,
457
- decoration: BoxDecoration(
458
- borderRadius: BorderRadius.all(Radius.circular(22)),
459
- color: Theme.of(context)
460
- .primaryTextTheme
461
- .overline
462
- .color),
463
- child: InkWell(
464
- onTap: () =>
465
- Navigator.of(context, rootNavigator: true)
466
- .pushNamed(Routes.receive),
467
- child: Row(
468
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
469
- children: <Widget>[
470
- Text(
471
- S.of(context).addresses,
472
- style: TextStyle(
473
- fontSize: 14,
474
- fontWeight: FontWeight.w600,
475
- color: Theme.of(context)
476
- .primaryTextTheme
477
- .title
478
- .color),
479
- ),
480
- rightArrow
481
- ],
482
- ),
483
- ),
484
- )
485
- ],
486
- ),
487
- ),
488
- AnimatedContainer(
489
- width: messageBoxWidth,
490
- height: messageBoxHeight,
491
- alignment: Alignment.center,
492
- duration: Duration(milliseconds: 500),
493
- curve: Curves.fastOutSlowIn,
494
- decoration: BoxDecoration(
495
- borderRadius:
496
- BorderRadius.only(topLeft: Radius.circular(10)),
497
- color: Colors.green),
498
- child: Text(
499
- S.of(context).copied_to_clipboard,
500
- style: TextStyle(fontSize: 10, color: Colors.white),
501
- ),
502
- )
503
- ],
504
- ),
505
- );
506
- });
507
- }
508
-}
lib/store/dashboard/trade_filter_store.dart
new
+62
@@ -0,0 +1,62 @@
1
+import 'package:cake_wallet/core/wallet_base.dart';
2
+import 'package:mobx/mobx.dart';
3
+import 'package:cake_wallet/src/domain/exchange/exchange_provider_description.dart';
4
+import 'package:cake_wallet/view_model/dashboard/trade_list_item.dart';
5
+
6
+part 'trade_filter_store.g.dart';
7
+
8
+class TradeFilterStore = TradeFilterStoreBase with _$TradeFilterStore;
9
+
10
+abstract class TradeFilterStoreBase with Store {
11
+ TradeFilterStoreBase(
12
+ {this.displayXMRTO = true,
13
+ this.displayChangeNow = true,
14
+ this.displayMorphToken = true,
15
+ this.wallet});
16
+
17
+ @observable
18
+ bool displayXMRTO;
19
+
20
+ @observable
21
+ bool displayChangeNow;
22
+
23
+ @observable
24
+ bool displayMorphToken;
25
+
26
+ WalletBase wallet;
27
+
28
+ @action
29
+ void toggleDisplayExchange(ExchangeProviderDescription provider) {
30
+ switch (provider) {
31
+ case ExchangeProviderDescription.changeNow:
32
+ displayChangeNow = !displayChangeNow;
33
+ break;
34
+ case ExchangeProviderDescription.xmrto:
35
+ displayXMRTO = !displayXMRTO;
36
+ break;
37
+ case ExchangeProviderDescription.morphToken:
38
+ displayMorphToken = !displayMorphToken;
39
+ break;
40
+ }
41
+ }
42
+
43
+ List<TradeListItem> filtered({List<TradeListItem> trades}) {
44
+ final _trades =
45
+ trades.where((item) => item.trade.walletId == wallet.id).toList();
46
+ final needToFilter = !displayChangeNow || !displayXMRTO || !displayMorphToken;
47
+
48
+ return needToFilter
49
+ ? trades
50
+ .where((item) =>
51
+ (displayXMRTO &&
52
+ item.trade.provider == ExchangeProviderDescription.xmrto) ||
53
+ (displayChangeNow &&
54
+ item.trade.provider ==
55
+ ExchangeProviderDescription.changeNow) ||
56
+ (displayMorphToken &&
57
+ item.trade.provider ==
58
+ ExchangeProviderDescription.morphToken))
59
+ .toList()
60
+ : _trades;
61
+ }
62
+}
\ No newline at end of file
lib/store/dashboard/trades_store.dart
new
+35
@@ -0,0 +1,35 @@
1
+import 'dart:async';
2
+import 'package:cake_wallet/src/domain/exchange/trade.dart';
3
+import 'package:cake_wallet/view_model/dashboard/trade_list_item.dart';
4
+import 'package:flutter/cupertino.dart';
5
+import 'package:hive/hive.dart';
6
+import 'package:mobx/mobx.dart';
7
+import 'package:cake_wallet/store/settings_store.dart';
8
+
9
+part 'trades_store.g.dart';
10
+
11
+class TradesStore = TradesStoreBase with _$TradesStore;
12
+
13
+abstract class TradesStoreBase with Store {
14
+ TradesStoreBase({this.tradesSource, this.settingsStore}) {
15
+ trades = <TradeListItem>[];
16
+
17
+ _onTradesChanged =
18
+ tradesSource.watch().listen((_) async => await updateTradeList());
19
+
20
+ updateTradeList();
21
+ }
22
+
23
+ Box<Trade> tradesSource;
24
+ StreamSubscription<BoxEvent> _onTradesChanged;
25
+ SettingsStore settingsStore;
26
+
27
+ @observable
28
+ List<TradeListItem> trades;
29
+
30
+ @action
31
+ Future updateTradeList() async => trades =
32
+ tradesSource.values.map((trade) => TradeListItem(
33
+ trade: trade,
34
+ displayMode: settingsStore.balanceDisplayMode)).toList();
35
+}
\ No newline at end of file
lib/store/dashboard/transaction_filter_store.dart
new
+69
@@ -0,0 +1,69 @@
1
+import 'package:mobx/mobx.dart';
2
+import 'package:cake_wallet/src/domain/common/transaction_direction.dart';
3
+import 'package:cake_wallet/view_model/dashboard/transaction_list_item.dart';
4
+
5
+part 'transaction_filter_store.g.dart';
6
+
7
+class TransactionFilterStore = TransactionFilterStoreBase
8
+ with _$TransactionFilterStore;
9
+
10
+abstract class TransactionFilterStoreBase with Store {
11
+ TransactionFilterStoreBase(
12
+ {this.displayIncoming = true, this.displayOutgoing = true});
13
+
14
+ @observable
15
+ bool displayIncoming;
16
+
17
+ @observable
18
+ bool displayOutgoing;
19
+
20
+ @observable
21
+ DateTime startDate;
22
+
23
+ @observable
24
+ DateTime endDate;
25
+
26
+ @action
27
+ void toggleIncoming() => displayIncoming = !displayIncoming;
28
+
29
+ @action
30
+ void toggleOutgoing() => displayOutgoing = !displayOutgoing;
31
+
32
+ @action
33
+ void changeStartDate(DateTime date) => startDate = date;
34
+
35
+ @action
36
+ void changeEndDate(DateTime date) => endDate = date;
37
+
38
+ List<TransactionListItem> filtered({List<TransactionListItem> transactions}) {
39
+ var _transactions = <TransactionListItem>[];
40
+ final needToFilter = !displayOutgoing ||
41
+ !displayIncoming ||
42
+ (startDate != null && endDate != null);
43
+
44
+ if (needToFilter) {
45
+ _transactions = transactions.where((item) {
46
+ var allowed = true;
47
+
48
+ if (allowed && startDate != null && endDate != null) {
49
+ allowed = startDate.isBefore(item.transaction.date) &&
50
+ endDate.isAfter(item.transaction.date);
51
+ }
52
+
53
+ if (allowed && (!displayOutgoing || !displayIncoming)) {
54
+ allowed = (displayOutgoing &&
55
+ item.transaction.direction ==
56
+ TransactionDirection.outgoing) ||
57
+ (displayIncoming &&
58
+ item.transaction.direction == TransactionDirection.incoming);
59
+ }
60
+
61
+ return allowed;
62
+ }).toList();
63
+ } else {
64
+ _transactions = transactions;
65
+ }
66
+
67
+ return _transactions;
68
+ }
69
+}
\ No newline at end of file
lib/view_model/dashboard/action_list_display_mode.dart
new
+32
@@ -0,0 +1,32 @@
1
+enum ActionListDisplayMode { transactions, trades }
2
+
3
+int serializeActionlistDisplayModes(List<ActionListDisplayMode> modes) {
4
+ var i = 0;
5
+
6
+ for (final mode in modes) {
7
+ switch (mode) {
8
+ case ActionListDisplayMode.trades:
9
+ i += 1;
10
+ break;
11
+ case ActionListDisplayMode.transactions:
12
+ i += 10;
13
+ break;
14
+ }
15
+ }
16
+
17
+ return i;
18
+}
19
+
20
+List<ActionListDisplayMode> deserializeActionlistDisplayModes(int raw) {
21
+ final modes = List<ActionListDisplayMode>();
22
+
23
+ if (raw == 1 || raw - 10 == 1) {
24
+ modes.add(ActionListDisplayMode.trades);
25
+ }
26
+
27
+ if (raw >= 10) {
28
+ modes.add(ActionListDisplayMode.transactions);
29
+ }
30
+
31
+ return modes;
32
+}
lib/view_model/dashboard/action_list_item.dart
new
+3
@@ -0,0 +1,3 @@
1
+abstract class ActionListItem {
2
+ DateTime get date;
3
+}
\ No newline at end of file
lib/view_model/dashboard/balance_view_model.dart
new
+115
@@ -0,0 +1,115 @@
1
+import 'package:cake_wallet/bitcoin/bitcoin_wallet.dart';
2
+import 'package:cake_wallet/core/wallet_base.dart';
3
+import 'package:cake_wallet/monero/monero_wallet.dart';
4
+import 'package:cake_wallet/src/domain/common/balance_display_mode.dart';
5
+import 'package:cake_wallet/src/domain/common/calculate_fiat_amount.dart';
6
+import 'package:cake_wallet/src/domain/common/crypto_currency.dart';
7
+import 'package:cake_wallet/view_model/dashboard/wallet_balance.dart';
8
+import 'package:cake_wallet/store/settings_store.dart';
9
+import 'package:cake_wallet/src/stores/price/price_store.dart';
10
+import 'package:flutter/cupertino.dart';
11
+import 'package:mobx/mobx.dart';
12
+
13
+part 'balance_view_model.g.dart';
14
+
15
+class BalanceViewModel = BalanceViewModelBase with _$BalanceViewModel;
16
+
17
+abstract class BalanceViewModelBase with Store {
18
+ BalanceViewModelBase({
19
+ @required this.wallet,
20
+ @required this.settingsStore,
21
+ @required this.priceStore
22
+ });
23
+
24
+ final WalletBase wallet;
25
+ final SettingsStore settingsStore;
26
+ final PriceStore priceStore;
27
+
28
+ WalletBalance _getWalletBalance() {
29
+ final _wallet = wallet;
30
+
31
+ if (_wallet is MoneroWallet) {
32
+ return WalletBalance(
33
+ unlockedBalance: _wallet.balance.formattedUnlockedBalance,
34
+ totalBalance: _wallet.balance.formattedFullBalance);
35
+ }
36
+
37
+ if (_wallet is BitcoinWallet) {
38
+ return WalletBalance(
39
+ unlockedBalance: _wallet.balance.confirmedFormatted,
40
+ totalBalance: _wallet.balance.unconfirmedFormatted);
41
+ }
42
+ }
43
+
44
+ String _getFiatBalance({double price, String cryptoAmount}) {
45
+ if (cryptoAmount == null) {
46
+ return '0.00';
47
+ }
48
+
49
+ return calculateFiatAmount(price: price, cryptoAmount: cryptoAmount);
50
+ }
51
+
52
+ @computed
53
+ double get price {
54
+ String symbol;
55
+ final _wallet = wallet;
56
+
57
+ if (_wallet is MoneroWallet) {
58
+ symbol = PriceStoreBase.generateSymbolForPair(
59
+ fiat: settingsStore.fiatCurrency, crypto: CryptoCurrency.xmr);
60
+ }
61
+
62
+ if (_wallet is BitcoinWallet) {
63
+ symbol = PriceStoreBase.generateSymbolForPair(
64
+ fiat: settingsStore.fiatCurrency, crypto: CryptoCurrency.btc);
65
+ }
66
+
67
+ return priceStore.prices[symbol];
68
+ }
69
+
70
+ @computed
71
+ String get cryptoBalance {
72
+ final walletBalance = _getWalletBalance();
73
+ final displayMode = settingsStore.balanceDisplayMode;
74
+ var balance = '---';
75
+
76
+ if (displayMode == BalanceDisplayMode.availableBalance) {
77
+ balance = walletBalance.unlockedBalance ?? '0.0';
78
+ }
79
+
80
+ if (displayMode == BalanceDisplayMode.fullBalance) {
81
+ balance = walletBalance.totalBalance ?? '0.0';
82
+ }
83
+
84
+ return balance;
85
+ }
86
+
87
+ @computed
88
+ String get fiatBalance {
89
+ final walletBalance = _getWalletBalance();
90
+ final displayMode = settingsStore.balanceDisplayMode;
91
+ final fiatCurrency = settingsStore.fiatCurrency;
92
+ var balance = '---';
93
+
94
+ final totalBalance = _getFiatBalance(
95
+ price: price,
96
+ cryptoAmount: walletBalance.totalBalance
97
+ );
98
+
99
+ final unlockedBalance = _getFiatBalance(
100
+ price: price,
101
+ cryptoAmount: walletBalance.unlockedBalance
102
+ );
103
+
104
+ if (displayMode == BalanceDisplayMode.availableBalance) {
105
+ balance = fiatCurrency.toString() + ' ' + unlockedBalance ?? '0.00';
106
+ }
107
+
108
+ if (displayMode == BalanceDisplayMode.fullBalance) {
109
+ balance = fiatCurrency.toString() + ' ' + totalBalance ?? '0.00';
110
+ }
111
+
112
+ return balance;
113
+ }
114
+
115
+}
\ No newline at end of file
lib/view_model/dashboard/dashboard_view_model.dart
new
+145
@@ -0,0 +1,145 @@
1
+import 'package:cake_wallet/bitcoin/bitcoin_transaction_info.dart';
2
+import 'package:cake_wallet/bitcoin/bitcoin_wallet.dart';
3
+import 'package:cake_wallet/monero/monero_wallet.dart';
4
+import 'package:cake_wallet/src/domain/common/balance_display_mode.dart';
5
+import 'package:cake_wallet/src/domain/common/crypto_currency.dart';
6
+import 'package:cake_wallet/src/domain/common/transaction_direction.dart';
7
+import 'package:cake_wallet/src/domain/common/transaction_info.dart';
8
+import 'package:cake_wallet/src/domain/exchange/exchange_provider_description.dart';
9
+import 'package:cake_wallet/src/domain/exchange/trade.dart';
10
+import 'package:cake_wallet/view_model/dashboard/balance_view_model.dart';
11
+import 'package:cake_wallet/view_model/dashboard/trade_list_item.dart';
12
+import 'package:cake_wallet/view_model/dashboard/transaction_list_item.dart';
13
+import 'package:cake_wallet/view_model/dashboard/action_list_item.dart';
14
+import 'package:cake_wallet/view_model/dashboard/action_list_display_mode.dart';
15
+import 'package:mobx/mobx.dart';
16
+import 'package:cake_wallet/core/wallet_base.dart';
17
+import 'package:cake_wallet/src/domain/common/sync_status.dart';
18
+import 'package:cake_wallet/src/domain/common/wallet_type.dart';
19
+import 'package:cake_wallet/store/app_store.dart';
20
+import 'package:cake_wallet/generated/i18n.dart';
21
+import 'package:cake_wallet/store/dashboard/trades_store.dart';
22
+import 'package:cake_wallet/store/dashboard/trade_filter_store.dart';
23
+import 'package:cake_wallet/store/dashboard/transaction_filter_store.dart';
24
+import 'package:cake_wallet/view_model/dashboard/formatted_item_list.dart';
25
+
26
+part 'dashboard_view_model.g.dart';
27
+
28
+class DashboardViewModel = DashboardViewModelBase with _$DashboardViewModel;
29
+
30
+abstract class DashboardViewModelBase with Store {
31
+ DashboardViewModelBase({
32
+ this.balanceViewModel,
33
+ this.appStore,
34
+ this.tradesStore,
35
+ this.tradeFilterStore,
36
+ this.transactionFilterStore}) {
37
+
38
+ name = appStore.wallet?.name;
39
+ wallet ??= appStore.wallet;
40
+ type = wallet.type;
41
+
42
+ transactions = ObservableList.of(wallet.transactionHistory.transactions
43
+ .map((transaction) => TransactionListItem(
44
+ transaction: transaction,
45
+ price: price,
46
+ fiatCurrency: appStore.settingsStore.fiatCurrency,
47
+ displayMode: balanceDisplayMode)));
48
+
49
+ _reaction = reaction((_) => appStore.wallet, _onWalletChange);
50
+
51
+ final _wallet = wallet;
52
+
53
+ if (_wallet is MoneroWallet) {
54
+ subname = _wallet.account?.label;
55
+ }
56
+
57
+ currentPage = 0;
58
+ }
59
+
60
+ @observable
61
+ WalletType type;
62
+
63
+ @observable
64
+ String name;
65
+
66
+ @observable
67
+ double currentPage;
68
+
69
+ @observable
70
+ ObservableList<TransactionListItem> transactions;
71
+
72
+ @observable
73
+ String subname;
74
+
75
+ @computed
76
+ String get address => wallet.address;
77
+
78
+ @computed
79
+ SyncStatus get status => wallet.syncStatus;
80
+
81
+ @computed
82
+ String get syncStatusText {
83
+ var statusText = '';
84
+
85
+ if (status is SyncingSyncStatus) {
86
+ statusText = S.current
87
+ .Blocks_remaining(
88
+ status.toString());
89
+ }
90
+
91
+ if (status is FailedSyncStatus) {
92
+ statusText = S
93
+ .current
94
+ .please_try_to_connect_to_another_node;
95
+ }
96
+
97
+ return statusText;
98
+ }
99
+
100
+ @computed
101
+ BalanceDisplayMode get balanceDisplayMode =>
102
+ appStore.settingsStore.balanceDisplayMode;
103
+
104
+ @computed
105
+ List<TradeListItem> get trades => tradesStore.trades;
106
+
107
+ @computed
108
+ double get price => balanceViewModel.price;
109
+
110
+ @computed
111
+ List<ActionListItem> get items {
112
+ final _items = <ActionListItem>[];
113
+
114
+ _items
115
+ .addAll(transactionFilterStore.filtered(transactions: transactions));
116
+ _items.addAll(tradeFilterStore.filtered(trades: trades));
117
+
118
+ return formattedItemsList(_items);
119
+ }
120
+
121
+ WalletBase wallet;
122
+
123
+ BalanceViewModel balanceViewModel;
124
+
125
+ AppStore appStore;
126
+
127
+ TradesStore tradesStore;
128
+
129
+ TradeFilterStore tradeFilterStore;
130
+
131
+ TransactionFilterStore transactionFilterStore;
132
+
133
+ ReactionDisposer _reaction;
134
+
135
+ void _onWalletChange(WalletBase wallet) {
136
+ name = wallet.name;
137
+ transactions.clear();
138
+ transactions.addAll(wallet.transactionHistory.transactions
139
+ .map((transaction) => TransactionListItem(
140
+ transaction: transaction,
141
+ price: price,
142
+ fiatCurrency: appStore.settingsStore.fiatCurrency,
143
+ displayMode: balanceDisplayMode)));
144
+ }
145
+}
lib/view_model/dashboard/date_section_item.dart
new
+8
@@ -0,0 +1,8 @@
1
+import 'package:cake_wallet/view_model/dashboard/action_list_item.dart';
2
+
3
+class DateSectionItem extends ActionListItem {
4
+ DateSectionItem(this.date);
5
+
6
+ @override
7
+ final DateTime date;
8
+}
\ No newline at end of file
lib/view_model/dashboard/formatted_item_list.dart
new
+34
@@ -0,0 +1,34 @@
1
+import 'package:cake_wallet/view_model/dashboard/action_list_item.dart';
2
+import 'package:cake_wallet/view_model/dashboard/date_section_item.dart';
3
+
4
+List<ActionListItem> formattedItemsList(List<ActionListItem> items) {
5
+ final formattedList = <ActionListItem>[];
6
+ DateTime lastDate;
7
+ items.sort((a, b) => b.date.compareTo(a.date));
8
+
9
+ for (var i = 0; i < items.length; i++) {
10
+ final transaction = items[i];
11
+
12
+ if (lastDate == null) {
13
+ lastDate = transaction.date;
14
+ formattedList.add(DateSectionItem(transaction.date));
15
+ formattedList.add(transaction);
16
+ continue;
17
+ }
18
+
19
+ final isCurrentDay = lastDate.year == transaction.date.year &&
20
+ lastDate.month == transaction.date.month &&
21
+ lastDate.day == transaction.date.day;
22
+
23
+ if (isCurrentDay) {
24
+ formattedList.add(transaction);
25
+ continue;
26
+ }
27
+
28
+ lastDate = transaction.date;
29
+ formattedList.add(DateSectionItem(transaction.date));
30
+ formattedList.add(transaction);
31
+ }
32
+
33
+ return formattedList;
34
+}
\ No newline at end of file
lib/view_model/dashboard/trade_list_item.dart
new
+21
@@ -0,0 +1,21 @@
1
+import 'package:cake_wallet/src/domain/exchange/trade.dart';
2
+import 'package:cake_wallet/view_model/dashboard/action_list_item.dart';
3
+import 'package:cake_wallet/src/domain/common/balance_display_mode.dart';
4
+
5
+class TradeListItem extends ActionListItem {
6
+ TradeListItem({this.trade, this.displayMode});
7
+
8
+ final Trade trade;
9
+ final BalanceDisplayMode displayMode;
10
+
11
+ String get tradeFormattedAmount {
12
+ return trade.amount != null
13
+ ? displayMode == BalanceDisplayMode.hiddenBalance
14
+ ? '---'
15
+ : trade.amountFormatted()
16
+ : trade.amount;
17
+ }
18
+
19
+ @override
20
+ DateTime get date => trade.createdAt;
21
+}
lib/view_model/dashboard/transaction_list_item.dart
new
+54
@@ -0,0 +1,54 @@
1
+import 'package:cake_wallet/src/domain/common/balance_display_mode.dart';
2
+import 'package:cake_wallet/src/domain/common/fiat_currency.dart';
3
+import 'package:cake_wallet/src/domain/common/transaction_info.dart';
4
+import 'package:cake_wallet/view_model/dashboard/action_list_item.dart';
5
+import 'package:cake_wallet/bitcoin/bitcoin_transaction_info.dart';
6
+import 'package:cake_wallet/src/domain/monero/monero_transaction_info.dart';
7
+import 'package:cake_wallet/src/domain/monero/monero_amount_format.dart';
8
+import 'package:cake_wallet/bitcoin/bitcoin_amount_format.dart';
9
+import 'package:cake_wallet/src/domain/common/calculate_fiat_amount_raw.dart';
10
+
11
+class TransactionListItem extends ActionListItem {
12
+ TransactionListItem({
13
+ this.transaction,
14
+ this.price,
15
+ this.fiatCurrency,
16
+ this.displayMode
17
+ });
18
+
19
+ final TransactionInfo transaction;
20
+ final double price;
21
+ final FiatCurrency fiatCurrency;
22
+ final BalanceDisplayMode displayMode;
23
+
24
+ String get formattedCryptoAmount {
25
+
26
+ return displayMode == BalanceDisplayMode.hiddenBalance
27
+ ? '---'
28
+ : transaction.amountFormatted();
29
+ }
30
+
31
+ String get formattedFiatAmount {
32
+
33
+ if (transaction is MoneroTransactionInfo) {
34
+ final amount = calculateFiatAmountRaw(
35
+ cryptoAmount: moneroAmountToDouble(amount: transaction.amount),
36
+ price: price);
37
+ transaction.changeFiatAmount(amount);
38
+ }
39
+
40
+ if (transaction is BitcoinTransactionInfo) {
41
+ final amount = calculateFiatAmountRaw(
42
+ cryptoAmount: bitcoinAmountToDouble(amount: transaction.amount),
43
+ price: price);
44
+ transaction.changeFiatAmount(amount);
45
+ }
46
+
47
+ return displayMode == BalanceDisplayMode.hiddenBalance
48
+ ? '---'
49
+ : fiatCurrency.title + ' ' + transaction.fiatAmount();
50
+ }
51
+
52
+ @override
53
+ DateTime get date => transaction.date;
54
+}
\ No newline at end of file
lib/view_model/dashboard/wallet_balance.dart
new
+6
@@ -0,0 +1,6 @@
1
+class WalletBalance {
2
+ WalletBalance({this.unlockedBalance, this.totalBalance});
3
+
4
+ String unlockedBalance;
5
+ String totalBalance;
6
+}
\ No newline at end of file
lib/view_model/dashboard_view_model.dart
deleted
-194
@@ -1,194 +0,0 @@
1
-import 'package:cake_wallet/bitcoin/bitcoin_transaction_info.dart';
2
-import 'package:cake_wallet/bitcoin/bitcoin_wallet.dart';
3
-import 'package:cake_wallet/monero/monero_wallet.dart';
4
-import 'package:cake_wallet/src/domain/common/transaction_direction.dart';
5
-import 'package:cake_wallet/src/domain/common/transaction_info.dart';
6
-import 'package:cake_wallet/src/stores/action_list/transaction_list_item.dart';
7
-import 'package:mobx/mobx.dart';
8
-import 'package:cake_wallet/core/wallet_base.dart';
9
-import 'package:cake_wallet/src/domain/common/sync_status.dart';
10
-import 'package:cake_wallet/src/domain/common/wallet_type.dart';
11
-import 'package:cake_wallet/store/app_store.dart';
12
-import 'package:cake_wallet/generated/i18n.dart';
13
-
14
-part 'dashboard_view_model.g.dart';
15
-
16
-class DashboardViewModel = DashboardViewModelBase with _$DashboardViewModel;
17
-
18
-class WalletBalace {
19
- WalletBalace({this.unlockedBalance, this.totalBalance});
20
-
21
- final String unlockedBalance;
22
- final String totalBalance;
23
-}
24
-
25
-abstract class DashboardViewModelBase with Store {
26
- DashboardViewModelBase({this.appStore}) {
27
- name = appStore.wallet?.name;
28
- wallet ??= appStore.wallet;
29
- type = wallet.type;
30
- transactions = ObservableList.of(wallet.transactionHistory.transactions
31
- .map((transaction) => TransactionListItem(transaction: transaction)));
32
- _reaction = reaction((_) => appStore.wallet, _onWalletChange);
33
-
34
- final _wallet = wallet;
35
-
36
- if (_wallet is MoneroWallet) {
37
- subname = _wallet.account?.label;
38
- }
39
-
40
- currentPage = 0;
41
- }
42
-
43
- @observable
44
- WalletType type;
45
-
46
- @observable
47
- String name;
48
-
49
- @observable
50
- double currentPage;
51
-
52
- @computed
53
- String get address => wallet.address;
54
-
55
- @computed
56
- SyncStatus get status => wallet.syncStatus;
57
-
58
- @computed
59
- String get syncStatusText {
60
- var statusText = '';
61
-
62
- if (status is SyncingSyncStatus) {
63
- statusText = S.current
64
- .Blocks_remaining(
65
- status.toString());
66
- }
67
-
68
- if (status is FailedSyncStatus) {
69
- statusText = S
70
- .current
71
- .please_try_to_connect_to_another_node;
72
- }
73
-
74
- return statusText;
75
- }
76
-
77
- @computed
78
- WalletBalace get balance {
79
- final wallet = this.wallet;
80
-
81
- if (wallet is MoneroWallet) {
82
- return WalletBalace(
83
- unlockedBalance: wallet.balance.formattedUnlockedBalance,
84
- totalBalance: wallet.balance.formattedFullBalance);
85
- }
86
-
87
- if (wallet is BitcoinWallet) {
88
- return WalletBalace(
89
- unlockedBalance: wallet.balance.confirmedFormatted,
90
- totalBalance: wallet.balance.unconfirmedFormatted);
91
- }
92
- }
93
-
94
- @observable
95
- ObservableList<Object> transactions;
96
-// ObservableList.of([
97
-// TransactionListItem(transaction: BitcoinTransactionInfo(
98
-// id: '',
99
-// height: 0,
100
-// amount: 0,
101
-// direction: TransactionDirection.incoming,
102
-// date: DateTime.now(),
103
-// isPending: false
104
-// )),
105
-// TransactionListItem(transaction: BitcoinTransactionInfo(
106
-// id: '',
107
-// height: 0,
108
-// amount: 0,
109
-// direction: TransactionDirection.incoming,
110
-// date: DateTime.now(),
111
-// isPending: false
112
-// )),
113
-// TransactionListItem(transaction: BitcoinTransactionInfo(
114
-// id: '',
115
-// height: 0,
116
-// amount: 0,
117
-// direction: TransactionDirection.incoming,
118
-// date: DateTime.now(),
119
-// isPending: false
120
-// )),
121
-// TransactionListItem(transaction: BitcoinTransactionInfo(
122
-// id: '',
123
-// height: 0,
124
-// amount: 0,
125
-// direction: TransactionDirection.incoming,
126
-// date: DateTime.now(),
127
-// isPending: false
128
-// )),
129
-// TransactionListItem(transaction: BitcoinTransactionInfo(
130
-// id: '',
131
-// height: 0,
132
-// amount: 0,
133
-// direction: TransactionDirection.incoming,
134
-// date: DateTime.now(),
135
-// isPending: false
136
-// )),
137
-// TransactionListItem(transaction: BitcoinTransactionInfo(
138
-// id: '',
139
-// height: 0,
140
-// amount: 0,
141
-// direction: TransactionDirection.incoming,
142
-// date: DateTime.now(),
143
-// isPending: false
144
-// )),
145
-// TransactionListItem(transaction: BitcoinTransactionInfo(
146
-// id: '',
147
-// height: 0,
148
-// amount: 0,
149
-// direction: TransactionDirection.incoming,
150
-// date: DateTime.now(),
151
-// isPending: false
152
-// )),
153
-// TransactionListItem(transaction: BitcoinTransactionInfo(
154
-// id: '',
155
-// height: 0,
156
-// amount: 0,
157
-// direction: TransactionDirection.incoming,
158
-// date: DateTime.now(),
159
-// isPending: false
160
-// )),
161
-// TransactionListItem(transaction: BitcoinTransactionInfo(
162
-// id: '',
163
-// height: 0,
164
-// amount: 0,
165
-// direction: TransactionDirection.incoming,
166
-// date: DateTime.now(),
167
-// isPending: false
168
-// )),
169
-// TransactionListItem(transaction: BitcoinTransactionInfo(
170
-// id: '',
171
-// height: 0,
172
-// amount: 0,
173
-// direction: TransactionDirection.incoming,
174
-// date: DateTime.now(),
175
-// isPending: false
176
-// )),
177
-// ]);
178
-
179
- @observable
180
- String subname;
181
-
182
- WalletBase wallet;
183
-
184
- AppStore appStore;
185
-
186
- ReactionDisposer _reaction;
187
-
188
- void _onWalletChange(WalletBase wallet) {
189
- name = wallet.name;
190
- transactions.clear();
191
- transactions.addAll(wallet.transactionHistory.transactions
192
- .map((transaction) => TransactionListItem(transaction: transaction)));
193
- }
194
-}