diff --git a/lib/di.dart b/lib/di.dart index aac1bfa24..f038a5d02 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -222,10 +222,10 @@ Future setup( addressEditOrCreateViewModel: getIt.get(param1: item))); - // getIt.get() getIt.registerFactory(() => SendViewModel( getIt.get().wallet, getIt.get().settingsStore, + getIt.get(), getIt.get())); getIt.registerFactory( @@ -318,10 +318,10 @@ Future setup( () => NodeCreateOrEditPage(getIt.get())); getIt.registerFactory(() => ExchangeViewModel( - wallet: getIt.get().wallet, - exchangeTemplateStore: getIt.get(), - trades: tradesSource, - tradesStore: getIt.get())); + getIt.get().wallet, + tradesSource, + getIt.get(), + getIt.get())); getIt.registerFactory(() => ExchangeTradeViewModel( wallet: getIt.get().wallet, diff --git a/lib/main.dart b/lib/main.dart index 6c73a5bc8..c2db950ad 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -120,7 +120,7 @@ class App extends StatelessWidget { settingsStore.isDarkTheme ? Brightness.light : Brightness.dark; final authenticationStore = getIt.get(); final initialRoute = authenticationStore.state == AuthenticationState.denied - ? Routes.welcome + ? Routes.disclaimer : Routes.login; SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle( diff --git a/lib/src/screens/disclaimer/disclaimer_page.dart b/lib/src/screens/disclaimer/disclaimer_page.dart index b80a7a1fe..935de9612 100644 --- a/lib/src/screens/disclaimer/disclaimer_page.dart +++ b/lib/src/screens/disclaimer/disclaimer_page.dart @@ -1,5 +1,6 @@ import 'dart:ui'; import 'package:cake_wallet/palette.dart'; +import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:flutter/material.dart'; import 'package:flutter/cupertino.dart'; @@ -19,26 +20,28 @@ class DisclaimerPage extends BasePage { String get title => 'Terms of Use'; @override - Widget body(BuildContext context) => DisclaimerPageBody(isReadOnly: true); + Widget leading(BuildContext context) => + isReadOnly ? super.leading(context) : null; + + @override + Widget body(BuildContext context) => DisclaimerPageBody(isReadOnly: isReadOnly); } class DisclaimerPageBody extends StatefulWidget { - DisclaimerPageBody({this.isReadOnly = true}); + DisclaimerPageBody({this.isReadOnly}); final bool isReadOnly; @override - DisclaimerBodyState createState() => DisclaimerBodyState(false); + DisclaimerBodyState createState() => DisclaimerBodyState(); } class DisclaimerBodyState extends State { - DisclaimerBodyState(this._isAccepted); static const xmrtoUrl = 'https://xmr.to/terms-of-service'; static const changenowUrl = 'https://changenow.io/terms-of-use'; static const morphUrl = 'http://morphtoken.com/terms'; - final bool _isAccepted; bool _checked = false; String _fileText = ''; @@ -51,26 +54,10 @@ class DisclaimerBodyState extends State { setState(() {}); } - Future _showAlertDialog(BuildContext context) async { - await showPopUp( - context: context, - builder: (BuildContext context) { - return AlertWithOneAction( - alertTitle: 'Terms and conditions', - alertContent: 'By using this app, you agree to the Terms of Agreement set forth to below', - buttonText: S.of(context).ok, - buttonAction: () => Navigator.of(context).pop() - ); - }); - } - - void _afterLayout(Duration _) => _showAlertDialog(context); - @override void initState() { super.initState(); getFileLines(); - if (_isAccepted) WidgetsBinding.instance.addPostFrameCallback(_afterLayout); } @override @@ -87,8 +74,7 @@ class DisclaimerBodyState extends State { padding: EdgeInsets.only(left: 24.0, right: 24.0), child: Column( children: [ - !_isAccepted - ? Row( + Row( children: [ Expanded( child: Text( @@ -102,13 +88,10 @@ class DisclaimerBodyState extends State { ), ) ], - ) - : Offstage(), - !_isAccepted - ? SizedBox( + ), + SizedBox( height: 20.0, - ) - : Offstage(), + ), Row( children: [ Expanded( @@ -254,8 +237,7 @@ class DisclaimerBodyState extends State { ], )), if (!widget.isReadOnly) ...[ - !_isAccepted - ? Row( + Row( children: [ Expanded( child: Container( @@ -303,25 +285,19 @@ class DisclaimerBodyState extends State { )), ), ], - ) - : Offstage(), - !_isAccepted - ? Container( + ), + Container( padding: EdgeInsets.only(left: 24.0, right: 24.0, bottom: 24.0), child: PrimaryButton( - onPressed: _checked ? () {} : null, + onPressed: _checked ? () => + Navigator.of(context).popAndPushNamed(Routes.welcome) + : null, text: 'Accept', color: Colors.green, textColor: Colors.white, ), - ) - : Offstage(), - _isAccepted - ? SizedBox( - height: 24.0, - ) - : Offstage() + ), ], ], ), diff --git a/lib/src/screens/exchange/exchange_page.dart b/lib/src/screens/exchange/exchange_page.dart index ab154a98d..bf587776f 100644 --- a/lib/src/screens/exchange/exchange_page.dart +++ b/lib/src/screens/exchange/exchange_page.dart @@ -307,8 +307,7 @@ class ExchangePage extends BasePage { ), Observer(builder: (_) { final templates = exchangeViewModel.templates; - final itemCount = - exchangeViewModel.templates.length; + final itemCount = templates.length; return ListView.builder( scrollDirection: Axis.horizontal, @@ -338,24 +337,22 @@ class ExchangePage extends BasePage { alertContent: S .of(context) .confirm_delete_template, - leftButtonText: - S.of(context).delete, rightButtonText: + S.of(context).delete, + leftButtonText: S.of(context).cancel, - actionLeftButton: () { + actionRightButton: () { Navigator.of( dialogContext) .pop(); exchangeViewModel - .exchangeTemplateStore - .remove( + .removeTemplate( template: template); exchangeViewModel - .exchangeTemplateStore - .update(); + .updateTemplate(); }, - actionRightButton: () => + actionLeftButton: () => Navigator.of( dialogContext) .pop()); diff --git a/lib/src/screens/exchange/exchange_template_page.dart b/lib/src/screens/exchange/exchange_template_page.dart index 85ea1f280..c68efc473 100644 --- a/lib/src/screens/exchange/exchange_template_page.dart +++ b/lib/src/screens/exchange/exchange_template_page.dart @@ -134,6 +134,7 @@ class ExchangeTemplatePage extends BasePage { initialIsAddressEditable: exchangeViewModel .isDepositAddressEnabled, isAmountEstimated: false, + hasRefundAddress: true, currencies: CryptoCurrency.all, onCurrencySelected: (currency) => exchangeViewModel.changeDepositCurrency( @@ -220,7 +221,7 @@ class ExchangeTemplatePage extends BasePage { PrimaryButton( onPressed: () { if (_formKey.currentState.validate()) { - exchangeViewModel.exchangeTemplateStore.addTemplate( + exchangeViewModel.addTemplate( amount: exchangeViewModel.depositAmount, depositCurrency: exchangeViewModel.depositCurrency.toString(), @@ -229,7 +230,7 @@ class ExchangeTemplatePage extends BasePage { provider: exchangeViewModel.provider.toString(), depositAddress: exchangeViewModel.depositAddress, receiveAddress: exchangeViewModel.receiveAddress); - exchangeViewModel.exchangeTemplateStore.update(); + exchangeViewModel.updateTemplate(); Navigator.of(context).pop(); } }, diff --git a/lib/src/screens/send/send_page.dart b/lib/src/screens/send/send_page.dart index dd2340d33..811d940dd 100644 --- a/lib/src/screens/send/send_page.dart +++ b/lib/src/screens/send/send_page.dart @@ -1,7 +1,9 @@ import 'dart:ui'; import 'package:cake_wallet/entities/transaction_priority.dart'; +import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; import 'package:cake_wallet/src/widgets/keyboard_done_button.dart'; import 'package:cake_wallet/src/widgets/picker.dart'; +import 'package:cake_wallet/src/widgets/template_tile.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -161,73 +163,70 @@ class SendPage extends BasePage { .decorationColor), validator: sendViewModel.addressValidator, ), - Observer( - builder: (_) => Padding( - padding: const EdgeInsets.only(top: 20), - child: BaseTextFormField( - focusNode: _cryptoAmountFocus, - controller: _cryptoAmountController, - keyboardType: + Padding( + padding: const EdgeInsets.only(top: 20), + child: BaseTextFormField( + focusNode: _cryptoAmountFocus, + controller: _cryptoAmountController, + keyboardType: TextInputType.numberWithOptions( signed: false, decimal: true), - prefixIcon: Padding( - padding: EdgeInsets.only(top: 9), - child: Text( - sendViewModel.currency.title + ':', + prefixIcon: Padding( + padding: EdgeInsets.only(top: 9), + child: Text( + sendViewModel.currency.title + ':', + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + color: Colors.white, + )), + ), + suffixIcon: Container( + height: 32, + width: 32, + margin: EdgeInsets.only( + left: 14, top: 4, bottom: 10), + decoration: BoxDecoration( + color: Theme.of(context) + .primaryTextTheme + .display1 + .color, + borderRadius: BorderRadius.all( + Radius.circular(6))), + child: InkWell( + onTap: () => + sendViewModel.setSendAll(), + child: Center( + child: Text(S.of(context).all, + textAlign: TextAlign.center, style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: Colors.white, - )), + fontSize: 12, + fontWeight: FontWeight.bold, + color: Theme.of(context) + .primaryTextTheme + .display1 + .decorationColor)), ), - suffixIcon: Container( - height: 32, - width: 32, - margin: EdgeInsets.only( - left: 14, top: 4, bottom: 10), - decoration: BoxDecoration( - color: Theme.of(context) - .primaryTextTheme - .display1 - .color, - borderRadius: BorderRadius.all( - Radius.circular(6))), - child: InkWell( - onTap: () => - sendViewModel.setSendAll(), - child: Center( - child: Text(S.of(context).all, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.bold, - color: Theme.of(context) - .primaryTextTheme - .display1 - .decorationColor)), - ), - ), - ), - hintText: '0.0000', - borderColor: Theme.of(context) + ), + ), + hintText: '0.0000', + borderColor: Theme.of(context) + .primaryTextTheme + .headline + .color, + textStyle: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w500, + color: Colors.white), + placeholderTextStyle: TextStyle( + color: Theme.of(context) .primaryTextTheme .headline - .color, - textStyle: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: Colors.white), - placeholderTextStyle: TextStyle( - color: Theme.of(context) - .primaryTextTheme - .headline - .decorationColor, - fontWeight: FontWeight.w500, - fontSize: 14), - validator: - sendViewModel.sendAll - ? sendViewModel.allAmountValidator - : sendViewModel.amountValidator))), + .decorationColor, + fontWeight: FontWeight.w500, + fontSize: 14), + validator: + sendViewModel.amountValidator)), Observer( builder: (_) => Padding( padding: EdgeInsets.only(top: 10), @@ -419,53 +418,53 @@ class SendPage extends BasePage { )), ), ), - // Observer( - // builder: (_) { - // final templates = sendViewModel.templates; - // final itemCount = templates.length; + Observer( + builder: (_) { + final templates = sendViewModel.templates; + final itemCount = templates.length; - // return ListView.builder( - // scrollDirection: Axis.horizontal, - // shrinkWrap: true, - // physics: NeverScrollableScrollPhysics(), - // itemCount: itemCount, - // itemBuilder: (context, index) { - // final template = templates[index]; + return ListView.builder( + scrollDirection: Axis.horizontal, + shrinkWrap: true, + physics: NeverScrollableScrollPhysics(), + itemCount: itemCount, + itemBuilder: (context, index) { + final template = templates[index]; - // return TemplateTile( - // key: UniqueKey(), - // to: template.name, - // amount: template.amount, - // from: template.cryptoCurrency, - // onTap: () { - // _addressController.text = template.address; - // _cryptoAmountController.text = template.amount; - // getOpenaliasRecord(context); - // }, - // onRemove: () { - // showPopUp( - // context: context, - // builder: (dialogContext) { - // return AlertWithTwoActions( - // alertTitle: S.of(context).template, - // alertContent: S.of(context).confirm_delete_template, - // leftButtonText: S.of(context).delete, - // rightButtonText: S.of(context).cancel, - // actionLeftButton: () { - // Navigator.of(dialogContext).pop(); - // sendViewModel.sendTemplateStore.remove(template: template); - // sendViewModel.sendTemplateStore.update(); - // }, - // actionRightButton: () => Navigator.of(dialogContext).pop() - // ); - // } - // ); - // }, - // ); - // } - // ); - // } - // ) + return TemplateTile( + key: UniqueKey(), + to: template.name, + amount: template.amount, + from: template.cryptoCurrency, + onTap: () { + _addressController.text = template.address; + _cryptoAmountController.text = template.amount; + getOpenaliasRecord(context); + }, + onRemove: () { + showPopUp( + context: context, + builder: (dialogContext) { + return AlertWithTwoActions( + alertTitle: S.of(context).template, + alertContent: S.of(context).confirm_delete_template, + rightButtonText: S.of(context).delete, + leftButtonText: S.of(context).cancel, + actionRightButton: () { + Navigator.of(dialogContext).pop(); + sendViewModel.removeTemplate(template: template); + sendViewModel.updateTemplate(); + }, + actionLeftButton: () => Navigator.of(dialogContext).pop() + ); + } + ); + }, + ); + } + ); + } + ) ], ), ), @@ -514,7 +513,6 @@ class SendPage extends BasePage { final amount = _fiatAmountController.text; if (amount != sendViewModel.fiatAmount) { - sendViewModel.sendAll = false; sendViewModel.setFiatAmount(amount); } }); diff --git a/lib/src/screens/send/send_template_page.dart b/lib/src/screens/send/send_template_page.dart index fcda9b7af..37708fcb2 100644 --- a/lib/src/screens/send/send_template_page.dart +++ b/lib/src/screens/send/send_template_page.dart @@ -134,7 +134,7 @@ class SendTemplatePage extends BasePage { signed: false, decimal: true), inputFormatters: [ BlacklistingTextInputFormatter( - RegExp('[\\-|\\ |\\,]')) + RegExp('[\\-|\\ ]')) ], prefixIcon: Padding( padding: EdgeInsets.only(top: 9), @@ -172,7 +172,7 @@ class SendTemplatePage extends BasePage { signed: false, decimal: true), inputFormatters: [ BlacklistingTextInputFormatter( - RegExp('[\\-|\\ |\\,]')) + RegExp('[\\-|\\ ]')) ], prefixIcon: Padding( padding: EdgeInsets.only(top: 9), @@ -210,12 +210,12 @@ class SendTemplatePage extends BasePage { bottomSection: PrimaryButton( onPressed: () { if (_formKey.currentState.validate()) { - // sendViewModel.sendTemplateStore.addTemplate( - // name: _nameController.text, - // address: _addressController.text, - // cryptoCurrency: sendViewModel.currency.title, - // amount: _cryptoAmountController.text); - // sendViewModel.sendTemplateStore.update(); + sendViewModel.addTemplate( + name: _nameController.text, + address: _addressController.text, + cryptoCurrency: sendViewModel.currency.title, + amount: _cryptoAmountController.text); + sendViewModel.updateTemplate(); Navigator.of(context).pop(); } }, @@ -249,6 +249,22 @@ class SendTemplatePage extends BasePage { } }); + _cryptoAmountController.addListener(() { + final amount = _cryptoAmountController.text; + + if (amount != sendViewModel.cryptoAmount) { + sendViewModel.setCryptoAmount(amount); + } + }); + + _fiatAmountController.addListener(() { + final amount = _fiatAmountController.text; + + if (amount != sendViewModel.fiatAmount) { + sendViewModel.setFiatAmount(amount); + } + }); + _addressController.addListener(() { final address = _addressController.text; diff --git a/lib/view_model/exchange/exchange_view_model.dart b/lib/view_model/exchange/exchange_view_model.dart index caca84b83..b6efa310f 100644 --- a/lib/view_model/exchange/exchange_view_model.dart +++ b/lib/view_model/exchange/exchange_view_model.dart @@ -27,10 +27,10 @@ class ExchangeViewModel = ExchangeViewModelBase with _$ExchangeViewModel; abstract class ExchangeViewModelBase with Store { ExchangeViewModelBase( - {this.wallet, + this.wallet, this.trades, - this.exchangeTemplateStore, - this.tradesStore}) { + this._exchangeTemplateStore, + this.tradesStore) { providerList = [ XMRTOExchangeProvider(), ChangeNowExchangeProvider(), @@ -54,7 +54,7 @@ abstract class ExchangeViewModelBase with Store { final WalletBase wallet; final Box trades; - final ExchangeTemplateStore exchangeTemplateStore; + final ExchangeTemplateStore _exchangeTemplateStore; final TradesStore tradesStore; @observable @@ -101,7 +101,7 @@ abstract class ExchangeViewModelBase with Store { @computed ObservableList get templates => - exchangeTemplateStore.templates; + _exchangeTemplateStore.templates; @action void changeProvider({ExchangeProvider provider}) { @@ -267,6 +267,22 @@ abstract class ExchangeViewModelBase with Store { _onPairChange(); } + void updateTemplate() => _exchangeTemplateStore.update(); + + void addTemplate({String amount, String depositCurrency, String receiveCurrency, + String provider, String depositAddress, String receiveAddress}) => + _exchangeTemplateStore.addTemplate( + amount: amount, + depositCurrency: depositCurrency, + receiveCurrency: receiveCurrency, + provider: provider, + depositAddress: depositAddress, + receiveAddress: receiveAddress + ); + + void removeTemplate({ExchangeTemplate template}) => + _exchangeTemplateStore.remove(template: template); + List providersForCurrentPair() { return _providersForPair(from: depositCurrency, to: receiveCurrency); } diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart index 40ebdd43f..d49be63f7 100644 --- a/lib/view_model/send/send_view_model.dart +++ b/lib/view_model/send/send_view_model.dart @@ -1,4 +1,6 @@ import 'package:cake_wallet/entities/openalias_record.dart'; +import 'package:cake_wallet/entities/template.dart'; +import 'package:cake_wallet/store/templates/send_template_store.dart'; import 'package:intl/intl.dart'; import 'package:mobx/mobx.dart'; import 'package:cake_wallet/core/template_validator.dart'; @@ -29,7 +31,8 @@ class SendViewModel = SendViewModelBase with _$SendViewModel; abstract class SendViewModelBase with Store { SendViewModelBase( - this._wallet, this._settingsStore, this._fiatConversationStore) + this._wallet, this._settingsStore, this._sendTemplateStore, + this._fiatConversationStore) : state = InitialExecutionState(), _cryptoNumberFormat = NumberFormat(), sendAll = false { @@ -90,8 +93,12 @@ abstract class SendViewModelBase with Store { @computed bool get isReadyForSend => _wallet.syncStatus is SyncedSyncStatus; + @computed + ObservableList