From 04e7c1884176b5e6f607d3bd0074914492e16f78 Mon Sep 17 00:00:00 2001 From: M Date: Fri, 2 Oct 2020 20:28:29 +0300 Subject: [PATCH] Fixes and improvments. --- ios/Runner.xcodeproj/project.pbxproj | 6 +- lib/monero/monero_wallet.dart | 2 - .../on_authentication_state_change.dart | 2 - .../screens/contact/contact_list_page.dart | 162 ++++++++-------- .../dashboard/widgets/transaction_raw.dart | 37 ++-- lib/src/screens/nodes/nodes_list_page.dart | 179 +++++++++--------- lib/src/screens/pin_code/pin_code_widget.dart | 4 +- lib/src/screens/send/send_page.dart | 60 +++--- .../screens/wallet_list/wallet_list_page.dart | 2 +- lib/utils/mobx.dart | 15 +- lib/utils/show_pop_up.dart | 4 +- .../node_list/node_list_view_model.dart | 5 +- lib/view_model/send/send_view_model.dart | 8 + 13 files changed, 246 insertions(+), 240 deletions(-) diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index c0d7cb8e8..a3b83428b 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -354,7 +354,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 4; DEVELOPMENT_TEAM = 32J6BB6VUS; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( @@ -493,7 +493,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 4; DEVELOPMENT_TEAM = 32J6BB6VUS; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( @@ -526,7 +526,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 4; DEVELOPMENT_TEAM = 32J6BB6VUS; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( diff --git a/lib/monero/monero_wallet.dart b/lib/monero/monero_wallet.dart index 9e59a1264..59ac8702a 100644 --- a/lib/monero/monero_wallet.dart +++ b/lib/monero/monero_wallet.dart @@ -180,9 +180,7 @@ abstract class MoneroWalletBase extends WalletBase with Store { @override Future save() async { - print('SAVE CALLED'); await monero_wallet.store(); - print('SAVE FINISHED'); } Future getNodeHeight() async => monero_wallet.getNodeHeight(); diff --git a/lib/reactions/on_authentication_state_change.dart b/lib/reactions/on_authentication_state_change.dart index 237ef00a8..80f3b2823 100644 --- a/lib/reactions/on_authentication_state_change.dart +++ b/lib/reactions/on_authentication_state_change.dart @@ -14,8 +14,6 @@ void startAuthenticationStateChange(AuthenticationStore authenticationStore, if (state == AuthenticationState.installed) { await loadCurrentWallet(); - // await navigatorKey.currentState - // .pushNamedAndRemoveUntil(Routes.login, (_) => false); } if (state == AuthenticationState.allowed) { diff --git a/lib/src/screens/contact/contact_list_page.dart b/lib/src/screens/contact/contact_list_page.dart index c66f5f2c4..548544679 100644 --- a/lib/src/screens/contact/contact_list_page.dart +++ b/lib/src/screens/contact/contact_list_page.dart @@ -63,14 +63,14 @@ class ContactListPage extends BasePage { builder: (_) { return contactListViewModel.contacts.isNotEmpty ? SectionStandardList( - sectionCount: 1, - context: context, - itemCounter: (int sectionIndex) => contactListViewModel.contacts.length, - itemBuilder: (_, sectionIndex, index) { - final contact = contactListViewModel.contacts[index]; - final image = _getCurrencyImage(contact.type); - final content = Builder( - builder: (context) => GestureDetector( + sectionCount: 1, + context: context, + itemCounter: (int sectionIndex) => + contactListViewModel.contacts.length, + itemBuilder: (_, sectionIndex, index) { + final contact = contactListViewModel.contacts[index]; + final image = _getCurrencyImage(contact.type); + final content = GestureDetector( onTap: () async { if (!isEditable) { Navigator.of(context).pop(contact); @@ -83,94 +83,79 @@ class ContactListPage extends BasePage { if (isCopied != null && isCopied) { await Clipboard.setData( ClipboardData(text: contact.address)); - await showBar(context, - S.of(context).copied_to_clipboard); + await showBar( + context, S.of(context).copied_to_clipboard); } }, - child: Column( - children: [ - Container( - width: double.infinity, - child: Padding( - padding: const EdgeInsets.only( - left: 24, top: 16, bottom: 16, right: 24), - child: Row( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: - CrossAxisAlignment.center, - children: [ - image ?? Offstage(), - Padding( - padding: image != null - ? EdgeInsets.only(left: 12) - : EdgeInsets.only(left: 0), - child: Text( - contact.name, - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.normal, - color: Theme.of(context) - .primaryTextTheme - .title - .color), - ), - ) - ], - )), - ), - ], + child: Container( + color: Colors.transparent, + padding: const EdgeInsets.only( + left: 24, top: 16, bottom: 16, right: 24), + child: Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + image ?? Offstage(), + Padding( + padding: image != null + ? EdgeInsets.only(left: 12) + : EdgeInsets.only(left: 0), + child: Text( + contact.name, + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.normal, + color: Theme.of(context) + .primaryTextTheme + .title + .color), + ), + ) + ], + ), ), - ) - ); + ); - return !isEditable - ? content - : Slidable( - key: Key('${contact.key}'), - actionPane: SlidableDrawerActionPane(), - child: content, - secondaryActions: [ - IconSlideAction( - caption: S.of(context).edit, - color: Colors.blue, - icon: Icons.edit, - onTap: () async => await Navigator.of(context) - .pushNamed(Routes.addressBookAddContact, - arguments: contact), - ), - IconSlideAction( - caption: S.of(context).delete, - color: Colors.red, - icon: CupertinoIcons.delete, - onTap: () async { - final isDelete = - await showAlertDialog(context) ?? false; + return !isEditable + ? content + : Slidable( + key: Key('${contact.key}'), + actionPane: SlidableDrawerActionPane(), + child: content, + secondaryActions: [ + IconSlideAction( + caption: S.of(context).edit, + color: Colors.blue, + icon: Icons.edit, + onTap: () async => + await Navigator.of(context).pushNamed( + Routes.addressBookAddContact, + arguments: contact), + ), + IconSlideAction( + caption: S.of(context).delete, + color: Colors.red, + icon: CupertinoIcons.delete, + onTap: () async { + final isDelete = + await showAlertDialog(context) ?? + false; - if (isDelete) { - await contactListViewModel - .delete(contact); - } - }, - ), - ], - dismissal: SlidableDismissal( - child: SlidableDrawerDismissal(), - onDismissed: (actionType) async => null, - // await contactListViewModel.delete(contact), - onWillDismiss: (actionType) async => - showAlertDialog(context), - ), - ); - }, - ) + if (isDelete) { + await contactListViewModel + .delete(contact); + } + }, + ), + ]); + }, + ) : Center( child: Text( S.of(context).placeholder_contacts, textAlign: TextAlign.center, - style: TextStyle( - color: Colors.grey, - fontSize: 14), + style: TextStyle(color: Colors.grey, fontSize: 14), ), ); }, @@ -181,7 +166,8 @@ class ContactListPage extends BasePage { Image image; switch (currency) { case CryptoCurrency.xmr: - image = Image.asset('assets/images/monero_logo.png', height: 24, width: 24); + image = + Image.asset('assets/images/monero_logo.png', height: 24, width: 24); break; case CryptoCurrency.ada: image = Image.asset('assets/images/ada.png', height: 24, width: 24); diff --git a/lib/src/screens/dashboard/widgets/transaction_raw.dart b/lib/src/screens/dashboard/widgets/transaction_raw.dart index 14d07a9fc..67e13ce43 100644 --- a/lib/src/screens/dashboard/widgets/transaction_raw.dart +++ b/lib/src/screens/dashboard/widgets/transaction_raw.dart @@ -29,8 +29,21 @@ class TransactionRow extends StatelessWidget { child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ + Container( + height: 36, + width: 36, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Theme.of(context).textTheme.overline.decorationColor + ), + child: Image.asset( + direction == TransactionDirection.incoming + ? 'assets/images/down_arrow.png' + : 'assets/images/up_arrow.png'), + ), Expanded( child: Container( + padding: const EdgeInsets.only(left: 12), height: 56, child: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -48,25 +61,11 @@ class TransactionRow extends StatelessWidget { fontSize: 16, fontWeight: FontWeight.w500, color: Colors.white)), - Container( - decoration: BoxDecoration( - borderRadius: - BorderRadius.all(Radius.circular(10)), - color: (direction == - TransactionDirection.incoming - ? Colors.green.withOpacity(0.8) - : Theme.of(context) - .accentTextTheme - .body2 - .decorationColor - .withOpacity(0.8))), - padding: EdgeInsets.only( - top: 3, bottom: 3, left: 10, right: 10), - child: Text(formattedAmount, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - color: Colors.white))) + Text(formattedAmount, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: Colors.white)) ]), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, diff --git a/lib/src/screens/nodes/nodes_list_page.dart b/lib/src/screens/nodes/nodes_list_page.dart index b0bc8c15f..20abdae32 100644 --- a/lib/src/screens/nodes/nodes_list_page.dart +++ b/lib/src/screens/nodes/nodes_list_page.dart @@ -10,6 +10,7 @@ import 'package:cake_wallet/src/screens/nodes/widgets/node_list_row.dart'; import 'package:cake_wallet/src/widgets/standard_list.dart'; import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; import 'package:cake_wallet/view_model/node_list/node_list_view_model.dart'; +import 'package:flutter_slidable/flutter_slidable.dart'; class NodeListPage extends BasePage { NodeListPage(this.nodeListViewModel); @@ -59,102 +60,104 @@ class NodeListPage extends BasePage { } @override - Widget body(context) { + Widget body(BuildContext context) { return Container( padding: EdgeInsets.only(top: 10), child: Observer( - builder: (_) => SectionStandardList( - sectionCount: 2, - context: context, - itemBuilder: (_, sectionIndex, index) { - return Observer(builder: (_) { - if (sectionIndex == 0) { - return NodeHeaderListRow( - title: S.of(context).add_new_node, - onTap: (_) async => await Navigator.of(context) - .pushNamed(Routes.newNode)); - } + builder: (BuildContext context) { + return nodeListViewModel.nodes.isNotEmpty + ? SectionStandardList( + sectionCount: 2, + context: context, + itemCounter: (int sectionIndex) { + if (sectionIndex == 0) { + return 1; + } - final node = nodeListViewModel.nodes[index]; - final isSelected = node.keyIndex == - nodeListViewModel.settingsStore.currentNode.keyIndex; - final nodeListRow = NodeListRow( - title: node.uri, - isSelected: isSelected, - isAlive: node.requestNode(), - onTap: (_) async { - if (isSelected) { - return; - } + return nodeListViewModel.nodes.length; + }, + itemBuilder: (_, sectionIndex, index) { + if (sectionIndex == 0) { + return NodeHeaderListRow( + title: S.of(context).add_new_node, + onTap: (_) async => await Navigator.of(context) + .pushNamed(Routes.newNode)); + } - await showPopUp( - context: context, - builder: (BuildContext context) { - // FIXME: Add translation. - return AlertWithTwoActions( - alertTitle: 'Change current node', - alertContent: - S.of(context).change_current_node(node.uri), - leftButtonText: S.of(context).cancel, - rightButtonText: S.of(context).change, - actionLeftButton: () => - Navigator.of(context).pop(), - actionRightButton: () async { - await nodeListViewModel.setAsCurrent(node); - Navigator.of(context).pop(); - }); - }); - }); + final node = nodeListViewModel.nodes[index]; + final isSelected = node.keyIndex == + nodeListViewModel.settingsStore.currentNode.keyIndex; + final nodeListRow = NodeListRow( + title: node.uri, + isSelected: isSelected, + isAlive: node.requestNode(), + onTap: (_) async { + if (isSelected) { + return; + } - final dismissibleRow = Dismissible( - key: Key('${node.keyIndex}'), - confirmDismiss: (direction) async { - return await showPopUp( - context: context, - builder: (BuildContext context) { - return AlertWithTwoActions( - alertTitle: S.of(context).remove_node, - alertContent: S.of(context).remove_node_message, - rightButtonText: S.of(context).remove, - leftButtonText: S.of(context).cancel, - actionRightButton: () => - Navigator.pop(context, true), - actionLeftButton: () => - Navigator.pop(context, false)); - }); - }, - onDismissed: (direction) async => - nodeListViewModel.delete(node), - direction: DismissDirection.endToStart, - background: Container( - padding: EdgeInsets.only(right: 10.0), - alignment: AlignmentDirectional.centerEnd, - color: Palette.red, - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - const Icon( - CupertinoIcons.delete, - color: Colors.white, - ), - Text( - S.of(context).delete, - style: TextStyle(color: Colors.white), - ) - ], - )), - child: nodeListRow); + await showPopUp( + context: context, + builder: (BuildContext context) { + // FIXME: Add translation. + return AlertWithTwoActions( + alertTitle: 'Change current node', + alertContent: S + .of(context) + .change_current_node(node.uri), + leftButtonText: S.of(context).cancel, + rightButtonText: S.of(context).change, + actionLeftButton: () => + Navigator.of(context).pop(), + actionRightButton: () async { + await nodeListViewModel + .setAsCurrent(node); + Navigator.of(context).pop(); + }); + }); + }); - return isSelected ? nodeListRow : dismissibleRow; - }); - }, - itemCounter: (int sectionIndex) { - if (sectionIndex == 0) { - return 1; - } + final dismissibleRow = Slidable( + key: Key('${node.keyIndex}'), + actionPane: SlidableDrawerActionPane(), + child: nodeListRow, + secondaryActions: [ + IconSlideAction( + caption: S.of(context).delete, + color: Colors.red, + icon: CupertinoIcons.delete, + onTap: () async { + final confirmed = await showPopUp( + context: context, + builder: (BuildContext context) { + return AlertWithTwoActions( + alertTitle: + S.of(context).remove_node, + alertContent: S + .of(context) + .remove_node_message, + rightButtonText: + S.of(context).remove, + leftButtonText: + S.of(context).cancel, + actionRightButton: () => + Navigator.pop(context, true), + actionLeftButton: () => + Navigator.pop(context, false)); + }) ?? + false; - return nodeListViewModel.nodes.length; - }), + if (confirmed) { + await nodeListViewModel.delete(node); + } + }, + ), + ]); + + return isSelected ? nodeListRow : dismissibleRow; + }) + : Container(); + }, ), ); } diff --git a/lib/src/screens/pin_code/pin_code_widget.dart b/lib/src/screens/pin_code/pin_code_widget.dart index 6cb0a9714..2911a3936 100644 --- a/lib/src/screens/pin_code/pin_code_widget.dart +++ b/lib/src/screens/pin_code/pin_code_widget.dart @@ -81,8 +81,8 @@ class PinCodeState extends State { } @override - Widget build(BuildContext context) => - Scaffold(key: _key, body: body(context)); + Widget build(BuildContext context) => Scaffold( + key: _key, body: body(context), resizeToAvoidBottomPadding: false); Widget body(BuildContext context) { final deleteIconImage = Image.asset( diff --git a/lib/src/screens/send/send_page.dart b/lib/src/screens/send/send_page.dart index 7a856cb43..0490463f9 100644 --- a/lib/src/screens/send/send_page.dart +++ b/lib/src/screens/send/send_page.dart @@ -25,15 +25,29 @@ import 'package:cake_wallet/src/screens/send/widgets/confirm_sending_alert.dart' import 'package:cake_wallet/src/widgets/base_text_form_field.dart'; class SendPage extends BasePage { - SendPage({@required this.sendViewModel}); + SendPage({@required this.sendViewModel}) + : _addressController = TextEditingController(), + _cryptoAmountController = TextEditingController(), + _fiatAmountController = TextEditingController(), + _formKey = GlobalKey(), + _cryptoAmountFocus = FocusNode(), + _fiatAmountFocus = FocusNode(), + _addressFocusNode = FocusNode() { + _addressFocusNode.addListener(() { + if (!_addressFocusNode.hasFocus && _addressController.text.isNotEmpty) { + getOpenaliasRecord(_addressFocusNode.context); + } + }); + } final SendViewModel sendViewModel; - final _addressController = TextEditingController(); - final _cryptoAmountController = TextEditingController(); - final _fiatAmountController = TextEditingController(); - final _formKey = GlobalKey(); - final _cryptoAmountFocus = FocusNode(); - final _fiatAmountFocus = FocusNode(); + final TextEditingController _addressController; + final TextEditingController _cryptoAmountController; + final TextEditingController _fiatAmountController; + final GlobalKey _formKey; + final FocusNode _cryptoAmountFocus; + final FocusNode _fiatAmountFocus; + final FocusNode _addressFocusNode; bool _effectsInstalled = false; @@ -105,6 +119,7 @@ class SendPage extends BasePage { child: Column( children: [ AddressTextField( + focusNode: _addressFocusNode, controller: _addressController, onURIScanned: (uri) { var address = ''; @@ -672,24 +687,23 @@ class SendPage extends BasePage { } Future getOpenaliasRecord(BuildContext context) async { - // final isOpenalias = - // await sendViewModel.isOpenaliasRecord(_addressController.text); + final record = + await sendViewModel.decodeOpenaliasRecord(_addressController.text); - // if (isOpenalias) { - // _addressController.text = sendViewModel.recordAddress; + if (record != null) { + _addressController.text = record.address; - // await showPopUp( - // context: context, - // builder: (BuildContext context) { - // return AlertWithOneAction( - // alertTitle: S.of(context).openalias_alert_title, - // alertContent: S - // .of(context) - // .openalias_alert_content(sendViewModel.recordName), - // buttonText: S.of(context).ok, - // buttonAction: () => Navigator.of(context).pop()); - // }); - // } + await showPopUp( + context: context, + builder: (BuildContext context) { + return AlertWithOneAction( + alertTitle: S.of(context).openalias_alert_title, + alertContent: + S.of(context).openalias_alert_content(record.name), + buttonText: S.of(context).ok, + buttonAction: () => Navigator.of(context).pop()); + }); + } } Future _setTransactionPriority(BuildContext context) async { diff --git a/lib/src/screens/wallet_list/wallet_list_page.dart b/lib/src/screens/wallet_list/wallet_list_page.dart index 8b55347c4..f6116b653 100644 --- a/lib/src/screens/wallet_list/wallet_list_page.dart +++ b/lib/src/screens/wallet_list/wallet_list_page.dart @@ -131,7 +131,7 @@ class WalletListBodyState extends State { wallet.name, style: TextStyle( fontSize: 22, - fontWeight: FontWeight.w600, + fontWeight: FontWeight.w500, color: Theme.of(context) .primaryTextTheme .title diff --git a/lib/utils/mobx.dart b/lib/utils/mobx.dart index 9e2316af7..7ae97d56f 100644 --- a/lib/utils/mobx.dart +++ b/lib/utils/mobx.dart @@ -61,7 +61,7 @@ extension MobxBindable on Box { } return watch().listen((event) { - if (filter != null && !filter(event.value as T)) { + if (filter != null && event.value != null && !filter(event.value as T)) { return; } @@ -80,7 +80,7 @@ extension MobxBindable on Box { } return watch().listen((event) { - if (filter != null && !filter(event.value as T)) { + if (filter != null && event.value != null && !filter(event.value as T)) { return; } @@ -124,15 +124,13 @@ extension HiveBindable on ObservableList { listen().listen((event) => dest.acceptEntityChange(event)); void acceptBoxChange(BoxEvent event, {T transformed}) { - print('---------------------'); - print('event.key: ${event.key}; event.deleted: ${event.deleted};'); if (event.deleted) { removeWhere((el) { - print('el.keyIndex ${el.keyIndex}'); - return el.keyIndex == event.key; }); - } + return el.keyIndex == event.key; + }); - print('---------------------'); + return; + } final dynamic value = transformed ?? event.value; @@ -150,6 +148,7 @@ extension HiveBindable on ObservableList { void acceptEntityChange(EntityChange event) { if (event.type == ChangeType.delete) { removeWhere((el) => el.keyIndex == event.key); + return; } final dynamic value = event.value; diff --git a/lib/utils/show_pop_up.dart b/lib/utils/show_pop_up.dart index 280bcff3c..a97fb3762 100644 --- a/lib/utils/show_pop_up.dart +++ b/lib/utils/show_pop_up.dart @@ -14,8 +14,8 @@ Future showPopUp({ context: context, builder: builder, barrierDismissible: barrierDismissible, - //barrierColor: barrierColor, - //useSafeArea: useSafeArea, + barrierColor: barrierColor, + useSafeArea: useSafeArea, useRootNavigator: useRootNavigator, routeSettings: routeSettings, child: child); diff --git a/lib/view_model/node_list/node_list_view_model.dart b/lib/view_model/node_list/node_list_view_model.dart index 2231ff7c9..3bb1d09ba 100644 --- a/lib/view_model/node_list/node_list_view_model.dart +++ b/lib/view_model/node_list/node_list_view_model.dart @@ -16,7 +16,7 @@ abstract class NodeListViewModelBase with Store { NodeListViewModelBase(this._nodeSource, this._wallet, this.settingsStore) : nodes = ObservableList() { _nodeSource.bindToList(nodes, - filter: (Node val) => val.type == _wallet.type, initialFire: true); + filter: (Node val) => val?.type == _wallet.type, initialFire: true); } final ObservableList nodes; @@ -46,7 +46,8 @@ abstract class NodeListViewModelBase with Store { await setAsCurrent(node); } - Future delete(Node node) async => _nodeSource.delete(node.key); + @action + Future delete(Node node) async => node.delete(); Future setAsCurrent(Node node) async => settingsStore.currentNode = node; diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart index a37f39341..eb4ec2f4a 100644 --- a/lib/view_model/send/send_view_model.dart +++ b/lib/view_model/send/send_view_model.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/entities/openalias_record.dart'; import 'package:intl/intl.dart'; import 'package:mobx/mobx.dart'; import 'package:cake_wallet/core/template_validator.dart'; @@ -144,6 +145,13 @@ abstract class SendViewModelBase with Store { void setTransactionPriority(TransactionPriority priority) => _settingsStore.transactionPriority = priority; + Future decodeOpenaliasRecord(String name) async { + final record = await OpenaliasRecord + .fetchAddressAndName(OpenaliasRecord.formatDomainName(name)); + + return record.name != name ? record : null; + } + @action void _updateFiatAmount() { try {