CAKE-158 | made account tile slidable; added onEdit function to account tile; added ability to edit wallet account name; added isFirstAddress parameter to wallet_address_list_view_model.dart and made first address in the address list not editable (receive page); wrapped wallet account name in the wallet menu title by observer; added _moneroTransactionsChangeReaction to dashboard_view_model.dart
OleksandrSobol committed
Nov 17, 2020 at 20:16 UTC
23abacd2526c9d898422de3abc055f89fd9070bb
11 files changed
+97
-11
lib/core/monero_account_label_validator.dart
+1
-1
@@ -7,7 +7,7 @@ class MoneroLabelValidator extends TextValidator {
7
MoneroLabelValidator({@required CryptoCurrency type})
8
: super(
9
errorMessage: S.current.error_text_account_name,
10
- pattern: '^[a-zA-Z0-9_]{1,15}\$',
10
+ pattern: '^[a-zA-Z0-9_ ]{1,15}\$',
11
minLength: 1,
12
maxLength: 15);
13
}
lib/di.dart
+16
-2
@@ -48,6 +48,7 @@ import 'package:cake_wallet/store/wallet_list_store.dart';
48
import 'package:cake_wallet/view_model/contact_list/contact_list_view_model.dart';
49
import 'package:cake_wallet/view_model/contact_list/contact_view_model.dart';
50
import 'package:cake_wallet/view_model/exchange/exchange_trade_view_model.dart';
51
+import 'package:cake_wallet/view_model/monero_account_list/account_list_item.dart';
52
import 'package:cake_wallet/view_model/node_list/node_list_view_model.dart';
53
import 'package:cake_wallet/view_model/node_list/node_create_or_edit_view_model.dart';
54
import 'package:cake_wallet/view_model/rescan_view_model.dart';
@@ -272,7 +273,7 @@ Future setup(
273
getIt.registerFactory(() => MoneroAccountListPage(
274
accountListViewModel: getIt.get<MoneroAccountListViewModel>()));
275
275
- getIt.registerFactory(() {
276
+ /*getIt.registerFactory(() {
277
final wallet = getIt.get<AppStore>().wallet;
278
279
if (wallet is MoneroWallet) {
@@ -285,7 +286,20 @@ Future setup(
286
287
getIt.registerFactory(() => MoneroAccountEditOrCreatePage(
288
moneroAccountCreationViewModel:
288
- getIt.get<MoneroAccountEditOrCreateViewModel>()));
289
+ getIt.get<MoneroAccountEditOrCreateViewModel>()));*/
290
+
291
+ getIt.registerFactoryParam<MoneroAccountEditOrCreateViewModel,
292
+ AccountListItem, void>(
293
+ (AccountListItem account, _) =>
294
+ MoneroAccountEditOrCreateViewModel((
295
+ getIt.get<AppStore>().wallet as MoneroWallet).accountList,
296
+ accountListItem: account));
297
+
298
+ getIt.registerFactoryParam<MoneroAccountEditOrCreatePage,
299
+ AccountListItem, void>((AccountListItem account, _) =>
300
+ MoneroAccountEditOrCreatePage(
301
+ moneroAccountCreationViewModel:
302
+ getIt.get<MoneroAccountEditOrCreateViewModel>(param1: account)));
303
304
getIt.registerFactory(() {
305
final appStore = getIt.get<AppStore>();
lib/router.dart
+3
-1
@@ -3,6 +3,7 @@ import 'package:cake_wallet/entities/transaction_description.dart';
3
import 'package:cake_wallet/src/screens/pin_code/pin_code_widget.dart';
4
import 'package:cake_wallet/src/screens/restore/wallet_restore_page.dart';
5
import 'package:cake_wallet/store/settings_store.dart';
6
+import 'package:cake_wallet/view_model/monero_account_list/account_list_item.dart';
7
import 'package:flutter/cupertino.dart';
8
import 'package:flutter/material.dart';
9
import 'package:cake_wallet/routes.dart';
@@ -261,7 +262,8 @@ Route<dynamic> createRoute(RouteSettings settings) {
262
263
case Routes.accountCreation:
264
return CupertinoPageRoute<String>(
264
- builder: (_) => getIt.get<MoneroAccountEditOrCreatePage>());
265
+ builder: (_) => getIt.get<MoneroAccountEditOrCreatePage>(
266
+ param1: settings.arguments as AccountListItem));
267
268
case Routes.addressBook:
269
return MaterialPageRoute<void>(
lib/src/screens/dashboard/widgets/menu_widget.dart
+3
-2
@@ -5,6 +5,7 @@ import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
5
import 'package:cake_wallet/entities/wallet_type.dart';
6
import 'package:cake_wallet/src/screens/dashboard/wallet_menu.dart';
7
import 'package:flutter/rendering.dart';
8
+import 'package:flutter_mobx/flutter_mobx.dart';
9
10
// FIXME: terrible design.
11
@@ -147,7 +148,7 @@ class MenuWidgetState extends State<MenuWidget> {
148
),
149
if (widget.dashboardViewModel.subname !=
150
null)
150
- Text(
151
+ Observer(builder: (_) => Text(
152
widget.dashboardViewModel.subname,
153
style: TextStyle(
154
color: Theme.of(context)
@@ -156,7 +157,7 @@ class MenuWidgetState extends State<MenuWidget> {
157
.decorationColor,
158
fontWeight: FontWeight.w500,
159
fontSize: 12),
159
- )
160
+ ))
161
],
162
),
163
))
lib/src/screens/monero_accounts/monero_account_list_page.dart
+6
-1
@@ -103,7 +103,12 @@ class MoneroAccountListPage extends StatelessWidget {
103
accountListViewModel
104
.select(account);
105
Navigator.of(context).pop();
106
- });
106
+ },
107
+ onEdit: () async =>
108
+ await Navigator.of(context)
109
+ .pushNamed(
110
+ Routes.accountCreation,
111
+ arguments: account));
112
},
113
),
114
isAlwaysShowScrollThumb
lib/src/screens/monero_accounts/widgets/account_tile.dart
+19
-3
@@ -1,15 +1,19 @@
1
import 'package:flutter/material.dart';
2
+import 'package:flutter_slidable/flutter_slidable.dart';
3
+import 'package:cake_wallet/generated/i18n.dart';
4
5
class AccountTile extends StatelessWidget {
6
AccountTile({
7
@required this.isCurrent,
8
@required this.accountName,
7
- @required this.onTap
9
+ @required this.onTap,
10
+ @required this.onEdit
11
});
12
13
final bool isCurrent;
14
final String accountName;
12
- final VoidCallback onTap;
15
+ final Function() onTap;
16
+ final Function() onEdit;
17
18
@override
19
Widget build(BuildContext context) {
@@ -20,7 +24,7 @@ class AccountTile extends StatelessWidget {
24
? Theme.of(context).textTheme.subtitle.color
25
: Theme.of(context).textTheme.display4.color;
26
23
- return GestureDetector(
27
+ final Widget cell = GestureDetector(
28
onTap: onTap,
29
child: Container(
30
height: 77,
@@ -39,5 +43,17 @@ class AccountTile extends StatelessWidget {
43
),
44
),
45
);
46
+
47
+ return isCurrent ? cell : Slidable(
48
+ key: Key(accountName),
49
+ child: cell,
50
+ actionPane: SlidableDrawerActionPane(),
51
+ secondaryActions: <Widget>[
52
+ IconSlideAction(
53
+ caption: S.of(context).edit,
54
+ color: Colors.blue,
55
+ icon: Icons.edit,
56
+ onTap: () => onEdit?.call())
57
+ ]);
58
}
59
}
\ No newline at end of file
lib/src/screens/receive/receive_page.dart
+3
@@ -116,6 +116,8 @@ class ReceivePage extends BasePage {
116
}
117
118
if (item is WalletAddressListItem) {
119
+ final isFirst = addressListViewModel.isFirstAddress;
120
+ addressListViewModel.isFirstAddress = false;
121
cell = Observer(builder: (_) {
122
final isCurrent = item.address ==
123
addressListViewModel.address.address;
@@ -134,6 +136,7 @@ class ReceivePage extends BasePage {
136
137
return AddressCell.fromItem(item,
138
isCurrent: isCurrent,
139
+ isFirstAddress: isFirst,
140
backgroundColor: backgroundColor,
141
textColor: textColor,
142
onTap: (_) => addressListViewModel.setAddress(item),
lib/src/screens/receive/widgets/address_cell.dart
+5
-1
@@ -6,6 +6,7 @@ import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_i
6
class AddressCell extends StatelessWidget {
7
factory AddressCell.fromItem(WalletAddressListItem item,
8
{@required bool isCurrent,
9
+ @required bool isFirstAddress,
10
@required Color backgroundColor,
11
@required Color textColor,
12
Function(String) onTap,
@@ -14,6 +15,7 @@ class AddressCell extends StatelessWidget {
15
address: item.address,
16
name: item.name,
17
isCurrent: isCurrent,
18
+ isFirstAddress: isFirstAddress,
19
backgroundColor: backgroundColor,
20
textColor: textColor,
21
onTap: onTap,
@@ -23,6 +25,7 @@ class AddressCell extends StatelessWidget {
25
{@required this.address,
26
@required this.name,
27
@required this.isCurrent,
28
+ @required this.isFirstAddress,
29
@required this.backgroundColor,
30
@required this.textColor,
31
this.onTap,
@@ -31,6 +34,7 @@ class AddressCell extends StatelessWidget {
34
final String address;
35
final String name;
36
final bool isCurrent;
37
+ final bool isFirstAddress;
38
final Color backgroundColor;
39
final Color textColor;
40
final Function(String) onTap;
@@ -56,7 +60,7 @@ class AddressCell extends StatelessWidget {
60
),
61
));
62
59
- return isCurrent
63
+ return (isCurrent || isFirstAddress)
64
? cell
65
: Slidable(
66
key: Key(address),
lib/view_model/dashboard/dashboard_view_model.dart
+36
@@ -1,6 +1,8 @@
1
import 'package:cake_wallet/bitcoin/bitcoin_transaction_info.dart';
2
import 'package:cake_wallet/bitcoin/bitcoin_wallet.dart';
3
+import 'package:cake_wallet/entities/transaction_history.dart';
4
import 'package:cake_wallet/monero/account.dart';
5
+import 'package:cake_wallet/monero/monero_transaction_history.dart';
6
import 'package:cake_wallet/monero/monero_wallet.dart';
7
import 'package:cake_wallet/entities/balance_display_mode.dart';
8
import 'package:cake_wallet/entities/crypto_currency.dart';
@@ -85,6 +87,10 @@ abstract class DashboardViewModelBase with Store {
87
_onMoneroAccountChangeReaction = reaction((_) => _wallet.account,
88
(Account account) => _onMoneroAccountChange(_wallet));
89
90
+ _onMoneroTransactionsChangeReaction = reaction((_) => _wallet.transactionHistory,
91
+ (MoneroTransactionHistory transactionHistory) =>
92
+ _onMoneroTransactionsChange(_wallet));
93
+
94
final _accountTransactions = _wallet
95
.transactionHistory.transactions.values
96
.where((tx) => tx.accountIndex == _wallet.account.id).toList();
@@ -187,6 +193,8 @@ abstract class DashboardViewModelBase with Store {
193
194
ReactionDisposer _onMoneroAccountChangeReaction;
195
196
+ ReactionDisposer _onMoneroTransactionsChangeReaction;
197
+
198
Future<void> reconnect() async {
199
final node = appStore.settingsStore.getCurrentNode(wallet.type);
200
await wallet.connectToNode(node: node);
@@ -199,6 +207,18 @@ abstract class DashboardViewModelBase with Store {
207
transactions.clear();
208
209
if (wallet is MoneroWallet) {
210
+ subname = wallet.account?.label;
211
+
212
+ _onMoneroAccountChangeReaction?.reaction?.dispose();
213
+ _onMoneroTransactionsChangeReaction?.reaction?.dispose();
214
+
215
+ _onMoneroAccountChangeReaction = reaction((_) => wallet.account,
216
+ (Account account) => _onMoneroAccountChange(wallet));
217
+
218
+ _onMoneroTransactionsChangeReaction = reaction((_) => wallet.transactionHistory,
219
+ (MoneroTransactionHistory transactionHistory) =>
220
+ _onMoneroTransactionsChange(wallet));
221
+
222
final _accountTransactions = wallet
223
.transactionHistory.transactions.values
224
.where((tx) => tx.accountIndex == wallet.account.id).toList();
@@ -219,6 +239,22 @@ abstract class DashboardViewModelBase with Store {
239
240
@action
241
void _onMoneroAccountChange(MoneroWallet wallet) {
242
+ subname = wallet.account?.label;
243
+ transactions.clear();
244
+
245
+ final _accountTransactions = wallet
246
+ .transactionHistory.transactions.values
247
+ .where((tx) => tx.accountIndex == wallet.account.id).toList();
248
+
249
+ transactions.addAll(_accountTransactions
250
+ .map((transaction) => TransactionListItem(
251
+ transaction: transaction,
252
+ balanceViewModel: balanceViewModel,
253
+ settingsStore: appStore.settingsStore)));
254
+ }
255
+
256
+ @action
257
+ void _onMoneroTransactionsChange(MoneroWallet wallet) {
258
transactions.clear();
259
260
final _accountTransactions = wallet
lib/view_model/monero_account_list/monero_account_edit_or_create_view_model.dart
+1
@@ -13,6 +13,7 @@ abstract class MoneroAccountEditOrCreateViewModelBase with Store {
13
{AccountListItem accountListItem})
14
: state = InitialExecutionState(),
15
isEdit = accountListItem != null,
16
+ label = accountListItem?.label??'',
17
_accountListItem = accountListItem;
18
19
final bool isEdit;
lib/view_model/wallet_address_list/wallet_address_list_view_model.dart
+4
@@ -67,6 +67,9 @@ abstract class WalletAddressListViewModelBase with Store {
67
@observable
68
String amount;
69
70
+ @observable
71
+ bool isFirstAddress;
72
+
73
@computed
74
WalletType get type => _wallet.type;
75
@@ -97,6 +100,7 @@ abstract class WalletAddressListViewModelBase with Store {
100
final addressList = ObservableList<ListItem>();
101
102
if (wallet is MoneroWallet) {
103
+ isFirstAddress = true;
104
addressList.addAll(wallet.subaddressList.subaddresses.map((subaddress) =>
105
WalletAddressListItem(
106
id: subaddress.id,