diff --git a/lib/core/monero_account_label_validator.dart b/lib/core/monero_account_label_validator.dart index dcbac668..2bc0fccc 100644 --- a/lib/core/monero_account_label_validator.dart +++ b/lib/core/monero_account_label_validator.dart @@ -7,7 +7,7 @@ class MoneroLabelValidator extends TextValidator { MoneroLabelValidator({@required CryptoCurrency type}) : super( errorMessage: S.current.error_text_account_name, - pattern: '^[a-zA-Z0-9_]{1,15}\$', + pattern: '^[a-zA-Z0-9_ ]{1,15}\$', minLength: 1, maxLength: 15); } diff --git a/lib/di.dart b/lib/di.dart index 1dba56bc..f7e6fe3b 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -48,6 +48,7 @@ import 'package:cake_wallet/store/wallet_list_store.dart'; import 'package:cake_wallet/view_model/contact_list/contact_list_view_model.dart'; import 'package:cake_wallet/view_model/contact_list/contact_view_model.dart'; import 'package:cake_wallet/view_model/exchange/exchange_trade_view_model.dart'; +import 'package:cake_wallet/view_model/monero_account_list/account_list_item.dart'; import 'package:cake_wallet/view_model/node_list/node_list_view_model.dart'; import 'package:cake_wallet/view_model/node_list/node_create_or_edit_view_model.dart'; import 'package:cake_wallet/view_model/rescan_view_model.dart'; @@ -272,7 +273,7 @@ Future setup( getIt.registerFactory(() => MoneroAccountListPage( accountListViewModel: getIt.get())); - getIt.registerFactory(() { + /*getIt.registerFactory(() { final wallet = getIt.get().wallet; if (wallet is MoneroWallet) { @@ -285,7 +286,20 @@ Future setup( getIt.registerFactory(() => MoneroAccountEditOrCreatePage( moneroAccountCreationViewModel: - getIt.get())); + getIt.get()));*/ + + getIt.registerFactoryParam( + (AccountListItem account, _) => + MoneroAccountEditOrCreateViewModel(( + getIt.get().wallet as MoneroWallet).accountList, + accountListItem: account)); + + getIt.registerFactoryParam((AccountListItem account, _) => + MoneroAccountEditOrCreatePage( + moneroAccountCreationViewModel: + getIt.get(param1: account))); getIt.registerFactory(() { final appStore = getIt.get(); diff --git a/lib/router.dart b/lib/router.dart index acad61d0..2d7877d0 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -3,6 +3,7 @@ import 'package:cake_wallet/entities/transaction_description.dart'; import 'package:cake_wallet/src/screens/pin_code/pin_code_widget.dart'; import 'package:cake_wallet/src/screens/restore/wallet_restore_page.dart'; import 'package:cake_wallet/store/settings_store.dart'; +import 'package:cake_wallet/view_model/monero_account_list/account_list_item.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/routes.dart'; @@ -261,7 +262,8 @@ Route createRoute(RouteSettings settings) { case Routes.accountCreation: return CupertinoPageRoute( - builder: (_) => getIt.get()); + builder: (_) => getIt.get( + param1: settings.arguments as AccountListItem)); case Routes.addressBook: return MaterialPageRoute( diff --git a/lib/src/screens/dashboard/widgets/menu_widget.dart b/lib/src/screens/dashboard/widgets/menu_widget.dart index 7701d0ad..f8de5ba8 100644 --- a/lib/src/screens/dashboard/widgets/menu_widget.dart +++ b/lib/src/screens/dashboard/widgets/menu_widget.dart @@ -5,6 +5,7 @@ import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; import 'package:cake_wallet/entities/wallet_type.dart'; import 'package:cake_wallet/src/screens/dashboard/wallet_menu.dart'; import 'package:flutter/rendering.dart'; +import 'package:flutter_mobx/flutter_mobx.dart'; // FIXME: terrible design. @@ -147,7 +148,7 @@ class MenuWidgetState extends State { ), if (widget.dashboardViewModel.subname != null) - Text( + Observer(builder: (_) => Text( widget.dashboardViewModel.subname, style: TextStyle( color: Theme.of(context) @@ -156,7 +157,7 @@ class MenuWidgetState extends State { .decorationColor, fontWeight: FontWeight.w500, fontSize: 12), - ) + )) ], ), )) diff --git a/lib/src/screens/monero_accounts/monero_account_list_page.dart b/lib/src/screens/monero_accounts/monero_account_list_page.dart index 623f3cb9..47404e44 100644 --- a/lib/src/screens/monero_accounts/monero_account_list_page.dart +++ b/lib/src/screens/monero_accounts/monero_account_list_page.dart @@ -103,7 +103,12 @@ class MoneroAccountListPage extends StatelessWidget { accountListViewModel .select(account); Navigator.of(context).pop(); - }); + }, + onEdit: () async => + await Navigator.of(context) + .pushNamed( + Routes.accountCreation, + arguments: account)); }, ), isAlwaysShowScrollThumb diff --git a/lib/src/screens/monero_accounts/widgets/account_tile.dart b/lib/src/screens/monero_accounts/widgets/account_tile.dart index eb9c7f25..f0753933 100644 --- a/lib/src/screens/monero_accounts/widgets/account_tile.dart +++ b/lib/src/screens/monero_accounts/widgets/account_tile.dart @@ -1,15 +1,19 @@ import 'package:flutter/material.dart'; +import 'package:flutter_slidable/flutter_slidable.dart'; +import 'package:cake_wallet/generated/i18n.dart'; class AccountTile extends StatelessWidget { AccountTile({ @required this.isCurrent, @required this.accountName, - @required this.onTap + @required this.onTap, + @required this.onEdit }); final bool isCurrent; final String accountName; - final VoidCallback onTap; + final Function() onTap; + final Function() onEdit; @override Widget build(BuildContext context) { @@ -20,7 +24,7 @@ class AccountTile extends StatelessWidget { ? Theme.of(context).textTheme.subtitle.color : Theme.of(context).textTheme.display4.color; - return GestureDetector( + final Widget cell = GestureDetector( onTap: onTap, child: Container( height: 77, @@ -39,5 +43,17 @@ class AccountTile extends StatelessWidget { ), ), ); + + return isCurrent ? cell : Slidable( + key: Key(accountName), + child: cell, + actionPane: SlidableDrawerActionPane(), + secondaryActions: [ + IconSlideAction( + caption: S.of(context).edit, + color: Colors.blue, + icon: Icons.edit, + onTap: () => onEdit?.call()) + ]); } } \ No newline at end of file diff --git a/lib/src/screens/receive/receive_page.dart b/lib/src/screens/receive/receive_page.dart index 1ac4a073..202784ee 100644 --- a/lib/src/screens/receive/receive_page.dart +++ b/lib/src/screens/receive/receive_page.dart @@ -116,6 +116,8 @@ class ReceivePage extends BasePage { } if (item is WalletAddressListItem) { + final isFirst = addressListViewModel.isFirstAddress; + addressListViewModel.isFirstAddress = false; cell = Observer(builder: (_) { final isCurrent = item.address == addressListViewModel.address.address; @@ -134,6 +136,7 @@ class ReceivePage extends BasePage { return AddressCell.fromItem(item, isCurrent: isCurrent, + isFirstAddress: isFirst, backgroundColor: backgroundColor, textColor: textColor, onTap: (_) => addressListViewModel.setAddress(item), diff --git a/lib/src/screens/receive/widgets/address_cell.dart b/lib/src/screens/receive/widgets/address_cell.dart index 6306ae20..cfc63a24 100644 --- a/lib/src/screens/receive/widgets/address_cell.dart +++ b/lib/src/screens/receive/widgets/address_cell.dart @@ -6,6 +6,7 @@ import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_i class AddressCell extends StatelessWidget { factory AddressCell.fromItem(WalletAddressListItem item, {@required bool isCurrent, + @required bool isFirstAddress, @required Color backgroundColor, @required Color textColor, Function(String) onTap, @@ -14,6 +15,7 @@ class AddressCell extends StatelessWidget { address: item.address, name: item.name, isCurrent: isCurrent, + isFirstAddress: isFirstAddress, backgroundColor: backgroundColor, textColor: textColor, onTap: onTap, @@ -23,6 +25,7 @@ class AddressCell extends StatelessWidget { {@required this.address, @required this.name, @required this.isCurrent, + @required this.isFirstAddress, @required this.backgroundColor, @required this.textColor, this.onTap, @@ -31,6 +34,7 @@ class AddressCell extends StatelessWidget { final String address; final String name; final bool isCurrent; + final bool isFirstAddress; final Color backgroundColor; final Color textColor; final Function(String) onTap; @@ -56,7 +60,7 @@ class AddressCell extends StatelessWidget { ), )); - return isCurrent + return (isCurrent || isFirstAddress) ? cell : Slidable( key: Key(address), diff --git a/lib/view_model/dashboard/dashboard_view_model.dart b/lib/view_model/dashboard/dashboard_view_model.dart index 62742d84..189c3ea3 100644 --- a/lib/view_model/dashboard/dashboard_view_model.dart +++ b/lib/view_model/dashboard/dashboard_view_model.dart @@ -1,6 +1,8 @@ import 'package:cake_wallet/bitcoin/bitcoin_transaction_info.dart'; import 'package:cake_wallet/bitcoin/bitcoin_wallet.dart'; +import 'package:cake_wallet/entities/transaction_history.dart'; import 'package:cake_wallet/monero/account.dart'; +import 'package:cake_wallet/monero/monero_transaction_history.dart'; import 'package:cake_wallet/monero/monero_wallet.dart'; import 'package:cake_wallet/entities/balance_display_mode.dart'; import 'package:cake_wallet/entities/crypto_currency.dart'; @@ -85,6 +87,10 @@ abstract class DashboardViewModelBase with Store { _onMoneroAccountChangeReaction = reaction((_) => _wallet.account, (Account account) => _onMoneroAccountChange(_wallet)); + _onMoneroTransactionsChangeReaction = reaction((_) => _wallet.transactionHistory, + (MoneroTransactionHistory transactionHistory) => + _onMoneroTransactionsChange(_wallet)); + final _accountTransactions = _wallet .transactionHistory.transactions.values .where((tx) => tx.accountIndex == _wallet.account.id).toList(); @@ -187,6 +193,8 @@ abstract class DashboardViewModelBase with Store { ReactionDisposer _onMoneroAccountChangeReaction; + ReactionDisposer _onMoneroTransactionsChangeReaction; + Future reconnect() async { final node = appStore.settingsStore.getCurrentNode(wallet.type); await wallet.connectToNode(node: node); @@ -199,6 +207,18 @@ abstract class DashboardViewModelBase with Store { transactions.clear(); if (wallet is MoneroWallet) { + subname = wallet.account?.label; + + _onMoneroAccountChangeReaction?.reaction?.dispose(); + _onMoneroTransactionsChangeReaction?.reaction?.dispose(); + + _onMoneroAccountChangeReaction = reaction((_) => wallet.account, + (Account account) => _onMoneroAccountChange(wallet)); + + _onMoneroTransactionsChangeReaction = reaction((_) => wallet.transactionHistory, + (MoneroTransactionHistory transactionHistory) => + _onMoneroTransactionsChange(wallet)); + final _accountTransactions = wallet .transactionHistory.transactions.values .where((tx) => tx.accountIndex == wallet.account.id).toList(); @@ -219,6 +239,22 @@ abstract class DashboardViewModelBase with Store { @action void _onMoneroAccountChange(MoneroWallet wallet) { + subname = wallet.account?.label; + transactions.clear(); + + final _accountTransactions = wallet + .transactionHistory.transactions.values + .where((tx) => tx.accountIndex == wallet.account.id).toList(); + + transactions.addAll(_accountTransactions + .map((transaction) => TransactionListItem( + transaction: transaction, + balanceViewModel: balanceViewModel, + settingsStore: appStore.settingsStore))); + } + + @action + void _onMoneroTransactionsChange(MoneroWallet wallet) { transactions.clear(); final _accountTransactions = wallet diff --git a/lib/view_model/monero_account_list/monero_account_edit_or_create_view_model.dart b/lib/view_model/monero_account_list/monero_account_edit_or_create_view_model.dart index 33e9dd1e..d32f8ead 100644 --- a/lib/view_model/monero_account_list/monero_account_edit_or_create_view_model.dart +++ b/lib/view_model/monero_account_list/monero_account_edit_or_create_view_model.dart @@ -13,6 +13,7 @@ abstract class MoneroAccountEditOrCreateViewModelBase with Store { {AccountListItem accountListItem}) : state = InitialExecutionState(), isEdit = accountListItem != null, + label = accountListItem?.label??'', _accountListItem = accountListItem; final bool isEdit; diff --git a/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart b/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart index e8c897bf..de8ba1e9 100644 --- a/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart +++ b/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart @@ -67,6 +67,9 @@ abstract class WalletAddressListViewModelBase with Store { @observable String amount; + @observable + bool isFirstAddress; + @computed WalletType get type => _wallet.type; @@ -97,6 +100,7 @@ abstract class WalletAddressListViewModelBase with Store { final addressList = ObservableList(); if (wallet is MoneroWallet) { + isFirstAddress = true; addressList.addAll(wallet.subaddressList.subaddresses.map((subaddress) => WalletAddressListItem( id: subaddress.id,