From 585f90b2fb263e7ea3c7839d6c21b020b0c47a42 Mon Sep 17 00:00:00 2001 From: OleksandrSobol Date: Tue, 22 Sep 2020 21:32:43 +0300 Subject: [PATCH] CAKE-49 | deleted base send widget, base exchange widget and top panel; added extendBodyBehindAppBar property and transparent AppBar style to base page; refactored send page, send template page, exchange page and exchange template page --- lib/src/screens/base_page.dart | 25 +- lib/src/screens/exchange/exchange_page.dart | 567 +++++++++++++- .../exchange/exchange_template_page.dart | 393 +++++++++- .../widgets/base_exchange_widget.dart | 618 --------------- lib/src/screens/send/send_page.dart | 708 +++++++++-------- lib/src/screens/send/send_template_page.dart | 254 ++++++- .../send/widgets/base_send_widget.dart | 709 ------------------ lib/src/widgets/top_panel.dart | 44 -- 8 files changed, 1528 insertions(+), 1790 deletions(-) delete mode 100644 lib/src/screens/exchange/widgets/base_exchange_widget.dart delete mode 100644 lib/src/screens/send/widgets/base_send_widget.dart delete mode 100644 lib/src/widgets/top_panel.dart diff --git a/lib/src/screens/base_page.dart b/lib/src/screens/base_page.dart index 33945e5d2..67e542683 100644 --- a/lib/src/screens/base_page.dart +++ b/lib/src/screens/base_page.dart @@ -6,7 +6,7 @@ import 'package:cake_wallet/themes.dart'; import 'package:cake_wallet/theme_changer.dart'; import 'package:cake_wallet/palette.dart'; -enum AppBarStyle { regular, withShadow } +enum AppBarStyle { regular, withShadow, transparent } abstract class BasePage extends StatelessWidget { String get title => null; @@ -21,6 +21,8 @@ abstract class BasePage extends StatelessWidget { bool get resizeToAvoidBottomPadding => true; + bool get extendBodyBehindAppBar => false; + Widget get endDrawer => null; AppBarStyle get appBarStyle => AppBarStyle.regular; @@ -85,6 +87,8 @@ abstract class BasePage extends StatelessWidget { ObstructingPreferredSizeWidget appBar(BuildContext context) { final _themeChanger = Provider.of(context); final _isDarkTheme = _themeChanger.getTheme() == Themes.darkTheme; + final appBarColor = _isDarkTheme + ? backgroundDarkColor : backgroundLightColor; switch (appBarStyle) { case AppBarStyle.regular: @@ -93,8 +97,7 @@ abstract class BasePage extends StatelessWidget { leading: leading(context), middle: middle(context), trailing: trailing(context), - backgroundColor: - _isDarkTheme ? backgroundDarkColor : backgroundLightColor); + backgroundColor: appBarColor); case AppBarStyle.withShadow: return NavBar.withShadow( @@ -102,8 +105,16 @@ abstract class BasePage extends StatelessWidget { leading: leading(context), middle: middle(context), trailing: trailing(context), - backgroundColor: - _isDarkTheme ? backgroundDarkColor : backgroundLightColor); + backgroundColor: appBarColor); + + case AppBarStyle.transparent: + return CupertinoNavigationBar( + leading: leading(context), + middle: middle(context), + trailing: trailing(context), + backgroundColor: Colors.transparent, + border: null, + ); default: return NavBar( @@ -111,8 +122,7 @@ abstract class BasePage extends StatelessWidget { leading: leading(context), middle: middle(context), trailing: trailing(context), - backgroundColor: - _isDarkTheme ? backgroundDarkColor : backgroundLightColor); + backgroundColor: appBarColor); } } @@ -128,6 +138,7 @@ abstract class BasePage extends StatelessWidget { backgroundColor: _isDarkTheme ? backgroundDarkColor : backgroundLightColor, resizeToAvoidBottomPadding: resizeToAvoidBottomPadding, + extendBodyBehindAppBar: extendBodyBehindAppBar, endDrawer: endDrawer, appBar: appBar(context), body: body(context), //SafeArea(child: ), diff --git a/lib/src/screens/exchange/exchange_page.dart b/lib/src/screens/exchange/exchange_page.dart index 51765380e..9a2ec17c8 100644 --- a/lib/src/screens/exchange/exchange_page.dart +++ b/lib/src/screens/exchange/exchange_page.dart @@ -1,18 +1,38 @@ import 'dart:ui'; +import 'package:cake_wallet/core/address_validator.dart'; +import 'package:cake_wallet/core/amount_validator.dart'; +import 'package:cake_wallet/routes.dart'; +import 'package:cake_wallet/src/domain/common/crypto_currency.dart'; +import 'package:cake_wallet/src/domain/exchange/exchange_template.dart'; +import 'package:cake_wallet/src/domain/exchange/xmrto/xmrto_exchange_provider.dart'; +import 'package:cake_wallet/src/screens/exchange/widgets/exchange_card.dart'; +import 'package:cake_wallet/src/stores/exchange/exchange_trade_state.dart'; +import 'package:cake_wallet/src/stores/exchange/limits_state.dart'; +import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; +import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; +import 'package:cake_wallet/src/widgets/primary_button.dart'; +import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; +import 'package:cake_wallet/src/widgets/template_tile.dart'; +import 'package:dotted_border/dotted_border.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/palette.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/screens/exchange/widgets/present_provider_picker.dart'; -import 'package:cake_wallet/src/screens/exchange/widgets/base_exchange_widget.dart'; import 'package:cake_wallet/src/widgets/trail_button.dart'; import 'package:cake_wallet/view_model/exchange/exchange_view_model.dart'; +import 'package:flutter_mobx/flutter_mobx.dart'; +import 'package:mobx/mobx.dart'; class ExchangePage extends BasePage { ExchangePage(this.exchangeViewModel); final ExchangeViewModel exchangeViewModel; + final depositKey = GlobalKey(); + final receiveKey = GlobalKey(); + final _formKey = GlobalKey(); + var _isReactionsSet = false; @override String get title => S.current.exchange; @@ -21,10 +41,13 @@ class ExchangePage extends BasePage { Color get titleColor => Colors.white; @override - Color get backgroundLightColor => Colors.transparent; + bool get resizeToAvoidBottomPadding => false; @override - Color get backgroundDarkColor => Colors.transparent; + bool get extendBodyBehindAppBar => true; + + @override + AppBarStyle get appBarStyle => AppBarStyle.transparent; @override Widget middle(BuildContext context) => @@ -38,22 +61,530 @@ class ExchangePage extends BasePage { ); @override - Widget body(BuildContext context) => - BaseExchangeWidget( - exchangeViewModel: exchangeViewModel, - leading: leading(context), - middle: middle(context), - trailing: trailing(context), - ); + Widget body(BuildContext context) { + final arrowBottomPurple = Image.asset( + 'assets/images/arrow_bottom_purple_icon.png', + color: Colors.white, + height: 8, + ); + final arrowBottomCakeGreen = Image.asset( + 'assets/images/arrow_bottom_cake_green.png', + color: Colors.white, + height: 8, + ); - @override - Widget build(BuildContext context) { - return Scaffold( - resizeToAvoidBottomPadding: resizeToAvoidBottomPadding, - body: Container( - color: Theme.of(context).backgroundColor, - child: body(context) - ) + final depositWalletName = + exchangeViewModel.depositCurrency == CryptoCurrency.xmr + ? exchangeViewModel.wallet.name + : null; + final receiveWalletName = + exchangeViewModel.receiveCurrency == CryptoCurrency.xmr + ? exchangeViewModel.wallet.name + : null; + + WidgetsBinding.instance + .addPostFrameCallback((_) => _setReactions(context, exchangeViewModel)); + + return Container( + color: Theme.of(context).backgroundColor, + child: Form( + key: _formKey, + child: ScrollableWithBottomSection( + contentPadding: EdgeInsets.only(bottom: 24), + content: Column( + children: [ + Container( + padding: EdgeInsets.only(bottom: 32), + decoration: BoxDecoration( + borderRadius: BorderRadius.only( + bottomLeft: Radius.circular(24), + bottomRight: Radius.circular(24) + ), + gradient: LinearGradient( + colors: [ + Theme.of(context).primaryTextTheme.body1.color, + Theme.of(context).primaryTextTheme.body1.decorationColor, + ], + stops: [0.35, 1.0], + begin: Alignment.topLeft, + end: Alignment.bottomRight), + ), + child: Column( + children: [ + Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.only( + bottomLeft: Radius.circular(24), + bottomRight: Radius.circular(24) + ), + gradient: LinearGradient( + colors: [ + Theme.of(context) + .primaryTextTheme + .subtitle + .color, + Theme.of(context) + .primaryTextTheme + .subtitle + .decorationColor, + ], + begin: Alignment.topLeft, + end: Alignment.bottomRight), + ), + padding: EdgeInsets.fromLTRB(24, 90, 24, 32), + child: Observer( + builder: (_) => ExchangeCard( + key: depositKey, + title: S.of(context).you_will_send, + initialCurrency: + exchangeViewModel.depositCurrency, + initialWalletName: depositWalletName, + initialAddress: exchangeViewModel + .depositCurrency == + exchangeViewModel.wallet.currency + ? exchangeViewModel.wallet.address + : exchangeViewModel.depositAddress, + initialIsAmountEditable: true, + initialIsAddressEditable: exchangeViewModel + .isDepositAddressEnabled, + isAmountEstimated: false, + currencies: CryptoCurrency.all, + onCurrencySelected: (currency) => + exchangeViewModel.changeDepositCurrency( + currency: currency), + imageArrow: arrowBottomPurple, + currencyButtonColor: Colors.transparent, + addressButtonsColor: + Theme.of(context).focusColor, + borderColor: Theme.of(context) + .primaryTextTheme + .body2 + .color, + currencyValueValidator: AmountValidator( + type: exchangeViewModel.wallet.type), + addressTextFieldValidator: AddressValidator( + type: + exchangeViewModel.depositCurrency), + ), + ), + ), + Padding( + padding: EdgeInsets.only(top: 29, left: 24, right: 24), + child: Observer( + builder: (_) => ExchangeCard( + key: receiveKey, + title: S.of(context).you_will_get, + initialCurrency: + exchangeViewModel.receiveCurrency, + initialWalletName: receiveWalletName, + initialAddress: + exchangeViewModel.receiveCurrency == + exchangeViewModel.wallet.currency + ? exchangeViewModel.wallet.address + : exchangeViewModel.receiveAddress, + initialIsAmountEditable: false, + initialIsAddressEditable: + exchangeViewModel.isReceiveAddressEnabled, + isAmountEstimated: true, + currencies: CryptoCurrency.all, + onCurrencySelected: (currency) => + exchangeViewModel.changeReceiveCurrency( + currency: currency), + imageArrow: arrowBottomCakeGreen, + currencyButtonColor: Colors.transparent, + addressButtonsColor: + Theme.of(context).focusColor, + borderColor: Theme.of(context) + .primaryTextTheme + .body2 + .decorationColor, + currencyValueValidator: AmountValidator( + type: exchangeViewModel.wallet.type), + addressTextFieldValidator: AddressValidator( + type: exchangeViewModel.receiveCurrency), + )), + ) + ], + ), + ), + Padding( + padding: EdgeInsets.only(top: 30, left: 24, bottom: 24), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + S.of(context).send_templates, + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w600, + color: Theme.of(context) + .primaryTextTheme + .display4 + .color), + ) + ], + ), + ), + Container( + height: 40, + width: double.infinity, + padding: EdgeInsets.only(left: 24), + child: SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Row( + children: [ + GestureDetector( + onTap: () => Navigator.of(context) + .pushNamed(Routes.exchangeTemplate), + child: Container( + padding: EdgeInsets.only(left: 1, right: 10), + child: DottedBorder( + borderType: BorderType.RRect, + dashPattern: [6, 4], + color: Theme.of(context) + .primaryTextTheme + .display2 + .decorationColor, + strokeWidth: 2, + radius: Radius.circular(20), + child: Container( + height: 34, + width: 75, + padding: EdgeInsets.only( + left: 10, right: 10), + alignment: Alignment.center, + decoration: BoxDecoration( + borderRadius: BorderRadius.all( + Radius.circular(20)), + color: Colors.transparent, + ), + child: Text( + S.of(context).send_new, + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w600, + color: Theme.of(context) + .primaryTextTheme + .display3 + .color), + ), + )), + ), + ), + Observer(builder: (_) { + final templates = exchangeViewModel.templates; + final itemCount = + exchangeViewModel.templates.length; + + return ListView.builder( + scrollDirection: Axis.horizontal, + shrinkWrap: true, + physics: NeverScrollableScrollPhysics(), + itemCount: itemCount, + itemBuilder: (context, index) { + final template = templates[index]; + + return TemplateTile( + key: UniqueKey(), + amount: template.amount, + from: template.depositCurrency, + to: template.receiveCurrency, + onTap: () { + applyTemplate( + exchangeViewModel, template); + }, + onRemove: () { + showDialog( + 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(); + exchangeViewModel + .exchangeTemplateStore + .remove( + template: + template); + exchangeViewModel + .exchangeTemplateStore + .update(); + }, + actionRightButton: () => + Navigator.of( + dialogContext) + .pop()); + }); + }, + ); + }); + }), + ], + ))) + ], + ), + bottomSectionPadding: + EdgeInsets.only(left: 24, right: 24, bottom: 24), + bottomSection: Column(children: [ + Padding( + padding: EdgeInsets.only(bottom: 15), + child: Observer(builder: (_) { + final description = + exchangeViewModel.provider is XMRTOExchangeProvider + ? S.of(context).amount_is_guaranteed + : S.of(context).amount_is_estimate; + return Center( + child: Text( + description, + style: TextStyle( + color: Theme.of(context) + .primaryTextTheme + .display4 + .decorationColor, + fontWeight: FontWeight.w500, + fontSize: 12), + ), + ); + }), + ), + Observer( + builder: (_) => LoadingPrimaryButton( + text: S.of(context).exchange, + onPressed: () { + if (_formKey.currentState.validate()) { + exchangeViewModel.createTrade(); + } + }, + color: Palette.blueCraiola, + textColor: Colors.white, + isLoading: + exchangeViewModel.tradeState is TradeIsCreating, + )), + ]), + )), ); } + + void applyTemplate( + ExchangeViewModel exchangeViewModel, ExchangeTemplate template) { + exchangeViewModel.changeDepositCurrency( + currency: CryptoCurrency.fromString(template.depositCurrency)); + exchangeViewModel.changeReceiveCurrency( + currency: CryptoCurrency.fromString(template.receiveCurrency)); + + switch (template.provider) { + case 'XMR.TO': + exchangeViewModel.changeProvider( + provider: exchangeViewModel.providerList[0]); + break; + case 'ChangeNOW': + exchangeViewModel.changeProvider( + provider: exchangeViewModel.providerList[1]); + break; + case 'MorphToken': + exchangeViewModel.changeProvider( + provider: exchangeViewModel.providerList[2]); + break; + } + + exchangeViewModel.changeDepositAmount(amount: template.amount); + exchangeViewModel.depositAddress = template.depositAddress; + exchangeViewModel.receiveAddress = template.receiveAddress; + } + + void _setReactions( + BuildContext context, ExchangeViewModel exchangeViewModel) { + if (_isReactionsSet) { + return; + } + + final depositAddressController = depositKey.currentState.addressController; + final depositAmountController = depositKey.currentState.amountController; + final receiveAddressController = receiveKey.currentState.addressController; + final receiveAmountController = receiveKey.currentState.amountController; + final limitsState = exchangeViewModel.limitsState; + + if (limitsState is LimitsLoadedSuccessfully) { + final min = limitsState.limits.min != null + ? limitsState.limits.min.toString() + : null; + final max = limitsState.limits.max != null + ? limitsState.limits.max.toString() + : null; + final key = depositKey; + key.currentState.changeLimits(min: min, max: max); + } + + _onCurrencyChange( + exchangeViewModel.receiveCurrency, exchangeViewModel, receiveKey); + _onCurrencyChange( + exchangeViewModel.depositCurrency, exchangeViewModel, depositKey); + + reaction( + (_) => exchangeViewModel.wallet.name, + (String _) => _onWalletNameChange( + exchangeViewModel, exchangeViewModel.receiveCurrency, receiveKey)); + + reaction( + (_) => exchangeViewModel.wallet.name, + (String _) => _onWalletNameChange( + exchangeViewModel, exchangeViewModel.depositCurrency, depositKey)); + + reaction( + (_) => exchangeViewModel.receiveCurrency, + (CryptoCurrency currency) => + _onCurrencyChange(currency, exchangeViewModel, receiveKey)); + + reaction( + (_) => exchangeViewModel.depositCurrency, + (CryptoCurrency currency) => + _onCurrencyChange(currency, exchangeViewModel, depositKey)); + + reaction((_) => exchangeViewModel.depositAmount, (String amount) { + if (depositKey.currentState.amountController.text != amount) { + depositKey.currentState.amountController.text = amount; + } + }); + + reaction((_) => exchangeViewModel.depositAddress, (String address) { + if (depositKey.currentState.addressController.text != address) { + depositKey.currentState.addressController.text = address; + } + }); + + reaction((_) => exchangeViewModel.isDepositAddressEnabled, + (bool isEnabled) { + depositKey.currentState.isAddressEditable(isEditable: isEnabled); + }); + + reaction((_) => exchangeViewModel.receiveAmount, (String amount) { + if (receiveKey.currentState.amountController.text != amount) { + receiveKey.currentState.amountController.text = amount; + } + }); + + reaction((_) => exchangeViewModel.receiveAddress, (String address) { + if (receiveKey.currentState.addressController.text != address) { + receiveKey.currentState.addressController.text = address; + } + }); + + reaction((_) => exchangeViewModel.isReceiveAddressEnabled, + (bool isEnabled) { + receiveKey.currentState.isAddressEditable(isEditable: isEnabled); + }); + + reaction((_) => exchangeViewModel.tradeState, (ExchangeTradeState state) { + if (state is TradeIsCreatedFailure) { + WidgetsBinding.instance.addPostFrameCallback((_) { + showDialog( + context: context, + builder: (BuildContext context) { + return AlertWithOneAction( + alertTitle: S.of(context).error, + alertContent: state.error, + buttonText: S.of(context).ok, + buttonAction: () => Navigator.of(context).pop()); + }); + }); + } + if (state is TradeIsCreatedSuccessfully) { + Navigator.of(context).pushNamed(Routes.exchangeConfirm); + } + }); + + reaction((_) => exchangeViewModel.limitsState, (LimitsState state) { + String min; + String max; + + if (state is LimitsLoadedSuccessfully) { + min = state.limits.min != null ? state.limits.min.toString() : null; + max = state.limits.max != null ? state.limits.max.toString() : null; + } + + if (state is LimitsLoadedFailure) { + min = '0'; + max = '0'; + } + + if (state is LimitsIsLoading) { + min = '...'; + max = '...'; + } + + depositKey.currentState.changeLimits(min: min, max: max); + receiveKey.currentState.changeLimits(min: null, max: null); + }); + + depositAddressController.addListener( + () => exchangeViewModel.depositAddress = depositAddressController.text); + + depositAmountController.addListener(() { + if (depositAmountController.text != exchangeViewModel.depositAmount) { + exchangeViewModel.changeDepositAmount( + amount: depositAmountController.text); + } + }); + + receiveAddressController.addListener( + () => exchangeViewModel.receiveAddress = receiveAddressController.text); + + receiveAmountController.addListener(() { + if (receiveAmountController.text != exchangeViewModel.receiveAmount) { + exchangeViewModel.changeReceiveAmount( + amount: receiveAmountController.text); + } + }); + + reaction((_) => exchangeViewModel.wallet.address, (String address) { + if (exchangeViewModel.depositCurrency == CryptoCurrency.xmr) { + depositKey.currentState.changeAddress(address: address); + } + + if (exchangeViewModel.receiveCurrency == CryptoCurrency.xmr) { + receiveKey.currentState.changeAddress(address: address); + } + }); + + _isReactionsSet = true; + } + + void _onCurrencyChange(CryptoCurrency currency, + ExchangeViewModel exchangeViewModel, GlobalKey key) { + final isCurrentTypeWallet = currency == exchangeViewModel.wallet.currency; + + key.currentState.changeSelectedCurrency(currency); + key.currentState.changeWalletName( + isCurrentTypeWallet ? exchangeViewModel.wallet.name : null); + + key.currentState.changeAddress( + address: isCurrentTypeWallet ? exchangeViewModel.wallet.address : ''); + + key.currentState.changeAmount(amount: ''); + } + + void _onWalletNameChange(ExchangeViewModel exchangeViewModel, + CryptoCurrency currency, GlobalKey key) { + final isCurrentTypeWallet = currency == exchangeViewModel.wallet.currency; + + if (isCurrentTypeWallet) { + key.currentState.changeWalletName(exchangeViewModel.wallet.name); + key.currentState.addressController.text = + exchangeViewModel.wallet.address; + } else if (key.currentState.addressController.text == + exchangeViewModel.wallet.address) { + key.currentState.changeWalletName(null); + key.currentState.addressController.text = null; + } + } } diff --git a/lib/src/screens/exchange/exchange_template_page.dart b/lib/src/screens/exchange/exchange_template_page.dart index 81bb54d1c..2f2563681 100644 --- a/lib/src/screens/exchange/exchange_template_page.dart +++ b/lib/src/screens/exchange/exchange_template_page.dart @@ -1,16 +1,29 @@ import 'dart:ui'; +import 'package:cake_wallet/core/address_validator.dart'; +import 'package:cake_wallet/core/amount_validator.dart'; +import 'package:cake_wallet/src/domain/common/crypto_currency.dart'; +import 'package:cake_wallet/src/domain/exchange/xmrto/xmrto_exchange_provider.dart'; +import 'package:cake_wallet/src/screens/exchange/widgets/exchange_card.dart'; +import 'package:cake_wallet/src/stores/exchange/limits_state.dart'; +import 'package:cake_wallet/src/widgets/primary_button.dart'; +import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/screens/exchange/widgets/present_provider_picker.dart'; -import 'package:cake_wallet/src/screens/exchange/widgets/base_exchange_widget.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/view_model/exchange/exchange_view_model.dart'; +import 'package:flutter_mobx/flutter_mobx.dart'; +import 'package:mobx/mobx.dart'; class ExchangeTemplatePage extends BasePage { ExchangeTemplatePage(this.exchangeViewModel); final ExchangeViewModel exchangeViewModel; + final depositKey = GlobalKey(); + final receiveKey = GlobalKey(); + final _formKey = GlobalKey(); + var _isReactionsSet = false; @override String get title => S.current.exchange_new_template; @@ -19,33 +32,375 @@ class ExchangeTemplatePage extends BasePage { Color get titleColor => Colors.white; @override - Color get backgroundLightColor => Colors.transparent; + bool get resizeToAvoidBottomPadding => false; @override - Color get backgroundDarkColor => Colors.transparent; + bool get extendBodyBehindAppBar => true; + + @override + AppBarStyle get appBarStyle => AppBarStyle.transparent; @override Widget trailing(BuildContext context) => PresentProviderPicker(exchangeViewModel: exchangeViewModel); @override - Widget body(BuildContext context) => - BaseExchangeWidget( - exchangeViewModel: exchangeViewModel, - leading: leading(context), - middle: middle(context), - trailing: trailing(context), - isTemplate: true - ); + Widget body(BuildContext context) { + final arrowBottomPurple = Image.asset( + 'assets/images/arrow_bottom_purple_icon.png', + color: Colors.white, + height: 8, + ); + final arrowBottomCakeGreen = Image.asset( + 'assets/images/arrow_bottom_cake_green.png', + color: Colors.white, + height: 8, + ); - @override - Widget build(BuildContext context) { - return Scaffold( - resizeToAvoidBottomPadding: resizeToAvoidBottomPadding, - body: Container( - color: Theme.of(context).backgroundColor, - child: body(context) - ) + final depositWalletName = + exchangeViewModel.depositCurrency == CryptoCurrency.xmr + ? exchangeViewModel.wallet.name + : null; + final receiveWalletName = + exchangeViewModel.receiveCurrency == CryptoCurrency.xmr + ? exchangeViewModel.wallet.name + : null; + + WidgetsBinding.instance + .addPostFrameCallback((_) => _setReactions(context, exchangeViewModel)); + + return Container( + color: Theme.of(context).backgroundColor, + child: Form( + key: _formKey, + child: ScrollableWithBottomSection( + contentPadding: EdgeInsets.only(bottom: 24), + content: Container( + padding: EdgeInsets.only(bottom: 32), + decoration: BoxDecoration( + borderRadius: BorderRadius.only( + bottomLeft: Radius.circular(24), + bottomRight: Radius.circular(24) + ), + gradient: LinearGradient( + colors: [ + Theme.of(context).primaryTextTheme.body1.color, + Theme.of(context).primaryTextTheme.body1.decorationColor, + ], + stops: [0.35, 1.0], + begin: Alignment.topLeft, + end: Alignment.bottomRight), + ), + child: Column( + children: [ + Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.only( + bottomLeft: Radius.circular(24), + bottomRight: Radius.circular(24) + ), + gradient: LinearGradient( + colors: [ + Theme.of(context) + .primaryTextTheme + .subtitle + .color, + Theme.of(context) + .primaryTextTheme + .subtitle + .decorationColor, + ], + begin: Alignment.topLeft, + end: Alignment.bottomRight), + ), + padding: EdgeInsets.fromLTRB(24, 90, 24, 32), + child: Observer( + builder: (_) => ExchangeCard( + key: depositKey, + title: S.of(context).you_will_send, + initialCurrency: + exchangeViewModel.depositCurrency, + initialWalletName: depositWalletName, + initialAddress: exchangeViewModel + .depositCurrency == + exchangeViewModel.wallet.currency + ? exchangeViewModel.wallet.address + : exchangeViewModel.depositAddress, + initialIsAmountEditable: true, + initialIsAddressEditable: exchangeViewModel + .isDepositAddressEnabled, + isAmountEstimated: false, + currencies: CryptoCurrency.all, + onCurrencySelected: (currency) => + exchangeViewModel.changeDepositCurrency( + currency: currency), + imageArrow: arrowBottomPurple, + currencyButtonColor: Colors.transparent, + addressButtonsColor: + Theme.of(context).focusColor, + borderColor: Theme.of(context) + .primaryTextTheme + .body2 + .color, + currencyValueValidator: AmountValidator( + type: exchangeViewModel.wallet.type), + addressTextFieldValidator: AddressValidator( + type: + exchangeViewModel.depositCurrency), + ), + ), + ), + Padding( + padding: EdgeInsets.only(top: 29, left: 24, right: 24), + child: Observer( + builder: (_) => ExchangeCard( + key: receiveKey, + title: S.of(context).you_will_get, + initialCurrency: + exchangeViewModel.receiveCurrency, + initialWalletName: receiveWalletName, + initialAddress: + exchangeViewModel.receiveCurrency == + exchangeViewModel.wallet.currency + ? exchangeViewModel.wallet.address + : exchangeViewModel.receiveAddress, + initialIsAmountEditable: false, + initialIsAddressEditable: + exchangeViewModel.isReceiveAddressEnabled, + isAmountEstimated: true, + currencies: CryptoCurrency.all, + onCurrencySelected: (currency) => + exchangeViewModel.changeReceiveCurrency( + currency: currency), + imageArrow: arrowBottomCakeGreen, + currencyButtonColor: Colors.transparent, + addressButtonsColor: + Theme.of(context).focusColor, + borderColor: Theme.of(context) + .primaryTextTheme + .body2 + .decorationColor, + currencyValueValidator: AmountValidator( + type: exchangeViewModel.wallet.type), + addressTextFieldValidator: AddressValidator( + type: exchangeViewModel.receiveCurrency), + )), + ) + ], + ), + ), + bottomSectionPadding: + EdgeInsets.only(left: 24, right: 24, bottom: 24), + bottomSection: Column(children: [ + Padding( + padding: EdgeInsets.only(bottom: 15), + child: Observer(builder: (_) { + final description = + exchangeViewModel.provider is XMRTOExchangeProvider + ? S.of(context).amount_is_guaranteed + : S.of(context).amount_is_estimate; + return Center( + child: Text( + description, + style: TextStyle( + color: Theme.of(context) + .primaryTextTheme + .display4 + .decorationColor, + fontWeight: FontWeight.w500, + fontSize: 12), + ), + ); + }), + ), + PrimaryButton( + onPressed: () { + if (_formKey.currentState.validate()) { + exchangeViewModel.exchangeTemplateStore.addTemplate( + amount: exchangeViewModel.depositAmount, + depositCurrency: + exchangeViewModel.depositCurrency.toString(), + receiveCurrency: + exchangeViewModel.receiveCurrency.toString(), + provider: exchangeViewModel.provider.toString(), + depositAddress: exchangeViewModel.depositAddress, + receiveAddress: exchangeViewModel.receiveAddress); + exchangeViewModel.exchangeTemplateStore.update(); + Navigator.of(context).pop(); + } + }, + text: S.of(context).save, + color: Colors.green, + textColor: Colors.white), + ]), + )) ); } + + void _setReactions( + BuildContext context, ExchangeViewModel exchangeViewModel) { + if (_isReactionsSet) { + return; + } + + final depositAddressController = depositKey.currentState.addressController; + final depositAmountController = depositKey.currentState.amountController; + final receiveAddressController = receiveKey.currentState.addressController; + final receiveAmountController = receiveKey.currentState.amountController; + final limitsState = exchangeViewModel.limitsState; + + if (limitsState is LimitsLoadedSuccessfully) { + final min = limitsState.limits.min != null + ? limitsState.limits.min.toString() + : null; + final max = limitsState.limits.max != null + ? limitsState.limits.max.toString() + : null; + final key = depositKey; + key.currentState.changeLimits(min: min, max: max); + } + + _onCurrencyChange( + exchangeViewModel.receiveCurrency, exchangeViewModel, receiveKey); + _onCurrencyChange( + exchangeViewModel.depositCurrency, exchangeViewModel, depositKey); + + reaction( + (_) => exchangeViewModel.wallet.name, + (String _) => _onWalletNameChange( + exchangeViewModel, exchangeViewModel.receiveCurrency, receiveKey)); + + reaction( + (_) => exchangeViewModel.wallet.name, + (String _) => _onWalletNameChange( + exchangeViewModel, exchangeViewModel.depositCurrency, depositKey)); + + reaction( + (_) => exchangeViewModel.receiveCurrency, + (CryptoCurrency currency) => + _onCurrencyChange(currency, exchangeViewModel, receiveKey)); + + reaction( + (_) => exchangeViewModel.depositCurrency, + (CryptoCurrency currency) => + _onCurrencyChange(currency, exchangeViewModel, depositKey)); + + reaction((_) => exchangeViewModel.depositAmount, (String amount) { + if (depositKey.currentState.amountController.text != amount) { + depositKey.currentState.amountController.text = amount; + } + }); + + reaction((_) => exchangeViewModel.depositAddress, (String address) { + if (depositKey.currentState.addressController.text != address) { + depositKey.currentState.addressController.text = address; + } + }); + + reaction((_) => exchangeViewModel.isDepositAddressEnabled, + (bool isEnabled) { + depositKey.currentState.isAddressEditable(isEditable: isEnabled); + }); + + reaction((_) => exchangeViewModel.receiveAmount, (String amount) { + if (receiveKey.currentState.amountController.text != amount) { + receiveKey.currentState.amountController.text = amount; + } + }); + + reaction((_) => exchangeViewModel.receiveAddress, (String address) { + if (receiveKey.currentState.addressController.text != address) { + receiveKey.currentState.addressController.text = address; + } + }); + + reaction((_) => exchangeViewModel.isReceiveAddressEnabled, + (bool isEnabled) { + receiveKey.currentState.isAddressEditable(isEditable: isEnabled); + }); + + reaction((_) => exchangeViewModel.limitsState, (LimitsState state) { + String min; + String max; + + if (state is LimitsLoadedSuccessfully) { + min = state.limits.min != null ? state.limits.min.toString() : null; + max = state.limits.max != null ? state.limits.max.toString() : null; + } + + if (state is LimitsLoadedFailure) { + min = '0'; + max = '0'; + } + + if (state is LimitsIsLoading) { + min = '...'; + max = '...'; + } + + depositKey.currentState.changeLimits(min: min, max: max); + receiveKey.currentState.changeLimits(min: null, max: null); + }); + + depositAddressController.addListener( + () => exchangeViewModel.depositAddress = depositAddressController.text); + + depositAmountController.addListener(() { + if (depositAmountController.text != exchangeViewModel.depositAmount) { + exchangeViewModel.changeDepositAmount( + amount: depositAmountController.text); + } + }); + + receiveAddressController.addListener( + () => exchangeViewModel.receiveAddress = receiveAddressController.text); + + receiveAmountController.addListener(() { + if (receiveAmountController.text != exchangeViewModel.receiveAmount) { + exchangeViewModel.changeReceiveAmount( + amount: receiveAmountController.text); + } + }); + + reaction((_) => exchangeViewModel.wallet.address, (String address) { + if (exchangeViewModel.depositCurrency == CryptoCurrency.xmr) { + depositKey.currentState.changeAddress(address: address); + } + + if (exchangeViewModel.receiveCurrency == CryptoCurrency.xmr) { + receiveKey.currentState.changeAddress(address: address); + } + }); + + _isReactionsSet = true; + } + + void _onCurrencyChange(CryptoCurrency currency, + ExchangeViewModel exchangeViewModel, GlobalKey key) { + final isCurrentTypeWallet = currency == exchangeViewModel.wallet.currency; + + key.currentState.changeSelectedCurrency(currency); + key.currentState.changeWalletName( + isCurrentTypeWallet ? exchangeViewModel.wallet.name : null); + + key.currentState.changeAddress( + address: isCurrentTypeWallet ? exchangeViewModel.wallet.address : ''); + + key.currentState.changeAmount(amount: ''); + } + + void _onWalletNameChange(ExchangeViewModel exchangeViewModel, + CryptoCurrency currency, GlobalKey key) { + final isCurrentTypeWallet = currency == exchangeViewModel.wallet.currency; + + if (isCurrentTypeWallet) { + key.currentState.changeWalletName(exchangeViewModel.wallet.name); + key.currentState.addressController.text = + exchangeViewModel.wallet.address; + } else if (key.currentState.addressController.text == + exchangeViewModel.wallet.address) { + key.currentState.changeWalletName(null); + key.currentState.addressController.text = null; + } + } } \ No newline at end of file diff --git a/lib/src/screens/exchange/widgets/base_exchange_widget.dart b/lib/src/screens/exchange/widgets/base_exchange_widget.dart deleted file mode 100644 index 44e0162ae..000000000 --- a/lib/src/screens/exchange/widgets/base_exchange_widget.dart +++ /dev/null @@ -1,618 +0,0 @@ -import 'dart:ui'; -import 'package:cake_wallet/palette.dart'; -import 'package:cake_wallet/src/domain/exchange/exchange_template.dart'; -import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; -import 'package:cake_wallet/src/widgets/template_tile.dart'; -import 'package:dotted_border/dotted_border.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_mobx/flutter_mobx.dart'; -import 'package:mobx/mobx.dart'; -import 'package:cake_wallet/routes.dart'; -import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cake_wallet/src/domain/common/crypto_currency.dart'; -import 'package:cake_wallet/src/domain/exchange/xmrto/xmrto_exchange_provider.dart'; -import 'package:cake_wallet/src/stores/exchange/exchange_trade_state.dart'; -import 'package:cake_wallet/src/stores/exchange/limits_state.dart'; -import 'package:cake_wallet/src/screens/exchange/widgets/exchange_card.dart'; -import 'package:cake_wallet/src/widgets/primary_button.dart'; -import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; -import 'package:cake_wallet/src/widgets/top_panel.dart'; -import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; -import 'package:cake_wallet/view_model/exchange/exchange_view_model.dart'; -import 'package:cake_wallet/core/address_validator.dart'; -import 'package:cake_wallet/core/amount_validator.dart'; - -class BaseExchangeWidget extends StatefulWidget { - BaseExchangeWidget({ - @required this.exchangeViewModel, - this.leading, - this.middle, - this.trailing, - this.isTemplate = false, - }); - - final ExchangeViewModel exchangeViewModel; - final Widget leading; - final Widget middle; - final Widget trailing; - final bool isTemplate; - - @override - BaseExchangeWidgetState createState() => BaseExchangeWidgetState( - exchangeViewModel: exchangeViewModel, - leading: leading, - middle: middle, - trailing: trailing, - isTemplate: isTemplate); -} - -class BaseExchangeWidgetState extends State { - BaseExchangeWidgetState({ - @required this.exchangeViewModel, - @required this.leading, - @required this.middle, - @required this.trailing, - @required this.isTemplate, - }); - - final ExchangeViewModel exchangeViewModel; - final Widget leading; - final Widget middle; - final Widget trailing; - final bool isTemplate; - final double topPanelHeight = 290; - - final depositKey = GlobalKey(); - final receiveKey = GlobalKey(); - final _formKey = GlobalKey(); - var _isReactionsSet = false; - - @override - Widget build(BuildContext context) { - final arrowBottomPurple = Image.asset( - 'assets/images/arrow_bottom_purple_icon.png', - color: Colors.white, - height: 8, - ); - final arrowBottomCakeGreen = Image.asset( - 'assets/images/arrow_bottom_cake_green.png', - color: Colors.white, - height: 8, - ); - - final depositWalletName = - exchangeViewModel.depositCurrency == CryptoCurrency.xmr - ? exchangeViewModel.wallet.name - : null; - final receiveWalletName = - exchangeViewModel.receiveCurrency == CryptoCurrency.xmr - ? exchangeViewModel.wallet.name - : null; - - WidgetsBinding.instance - .addPostFrameCallback((_) => _setReactions(context, exchangeViewModel)); - - return Form( - key: _formKey, - child: ScrollableWithBottomSection( - contentPadding: EdgeInsets.only(bottom: 24), - content: Column( - children: [ - TopPanel( - gradient: LinearGradient(colors: [ - Theme.of(context).primaryTextTheme.body1.color, - Theme.of(context).primaryTextTheme.body1.decorationColor, - ], stops: [ - 0.35, - 1.0 - ], begin: Alignment.topLeft, end: Alignment.bottomRight), - edgeInsets: EdgeInsets.only(bottom: 32), - widget: Column( - children: [ - TopPanel( - edgeInsets: EdgeInsets.all(0), - gradient: LinearGradient( - colors: [ - Theme.of(context) - .primaryTextTheme - .subtitle - .color, - Theme.of(context) - .primaryTextTheme - .subtitle - .decorationColor, - ], - begin: Alignment.topLeft, - end: Alignment.bottomRight), - widget: Column( - children: [ - CupertinoNavigationBar( - leading: leading, - middle: middle, - trailing: trailing, - backgroundColor: Colors.transparent, - border: null, - ), - Padding( - padding: EdgeInsets.fromLTRB(24, 29, 24, 32), - child: Observer( - builder: (_) => ExchangeCard( - key: depositKey, - title: S.of(context).you_will_send, - initialCurrency: - exchangeViewModel.depositCurrency, - initialWalletName: depositWalletName, - initialAddress: exchangeViewModel - .depositCurrency == - exchangeViewModel.wallet.currency - ? exchangeViewModel.wallet.address - : exchangeViewModel.depositAddress, - initialIsAmountEditable: true, - initialIsAddressEditable: exchangeViewModel - .isDepositAddressEnabled, - isAmountEstimated: false, - currencies: CryptoCurrency.all, - onCurrencySelected: (currency) => - exchangeViewModel.changeDepositCurrency( - currency: currency), - imageArrow: arrowBottomPurple, - currencyButtonColor: Colors.transparent, - addressButtonsColor: - Theme.of(context).focusColor, - borderColor: Theme.of(context) - .primaryTextTheme - .body2 - .color, - currencyValueValidator: AmountValidator( - type: exchangeViewModel.wallet.type), - addressTextFieldValidator: AddressValidator( - type: - exchangeViewModel.depositCurrency), - ), - ), - ) - ], - )), - Padding( - padding: EdgeInsets.only(top: 29, left: 24, right: 24), - child: Observer( - builder: (_) => ExchangeCard( - key: receiveKey, - title: S.of(context).you_will_get, - initialCurrency: - exchangeViewModel.receiveCurrency, - initialWalletName: receiveWalletName, - initialAddress: - exchangeViewModel.receiveCurrency == - exchangeViewModel.wallet.currency - ? exchangeViewModel.wallet.address - : exchangeViewModel.receiveAddress, - initialIsAmountEditable: false, - initialIsAddressEditable: - exchangeViewModel.isReceiveAddressEnabled, - isAmountEstimated: true, - currencies: CryptoCurrency.all, - onCurrencySelected: (currency) => - exchangeViewModel.changeReceiveCurrency( - currency: currency), - imageArrow: arrowBottomCakeGreen, - currencyButtonColor: Colors.transparent, - addressButtonsColor: - Theme.of(context).focusColor, - borderColor: Theme.of(context) - .primaryTextTheme - .body2 - .decorationColor, - currencyValueValidator: AmountValidator( - type: exchangeViewModel.wallet.type), - addressTextFieldValidator: AddressValidator( - type: exchangeViewModel.receiveCurrency), - )), - ) - ], - )), - isTemplate - ? Offstage() - : Padding( - padding: EdgeInsets.only(top: 30, left: 24, bottom: 24), - child: Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Text( - S.of(context).send_templates, - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.w600, - color: Theme.of(context) - .primaryTextTheme - .display4 - .color), - ) - ], - ), - ), - isTemplate - ? Offstage() - : Container( - height: 40, - width: double.infinity, - padding: EdgeInsets.only(left: 24), - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: Row( - children: [ - GestureDetector( - onTap: () => Navigator.of(context) - .pushNamed(Routes.exchangeTemplate), - child: Container( - padding: EdgeInsets.only(left: 1, right: 10), - child: DottedBorder( - borderType: BorderType.RRect, - dashPattern: [6, 4], - color: Theme.of(context) - .primaryTextTheme - .display2 - .decorationColor, - strokeWidth: 2, - radius: Radius.circular(20), - child: Container( - height: 34, - width: 75, - padding: EdgeInsets.only( - left: 10, right: 10), - alignment: Alignment.center, - decoration: BoxDecoration( - borderRadius: BorderRadius.all( - Radius.circular(20)), - color: Colors.transparent, - ), - child: Text( - S.of(context).send_new, - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w600, - color: Theme.of(context) - .primaryTextTheme - .display3 - .color), - ), - )), - ), - ), - Observer(builder: (_) { - final templates = exchangeViewModel.templates; - final itemCount = - exchangeViewModel.templates.length; - - return ListView.builder( - scrollDirection: Axis.horizontal, - shrinkWrap: true, - physics: NeverScrollableScrollPhysics(), - itemCount: itemCount, - itemBuilder: (context, index) { - final template = templates[index]; - - return TemplateTile( - key: UniqueKey(), - amount: template.amount, - from: template.depositCurrency, - to: template.receiveCurrency, - onTap: () { - applyTemplate( - exchangeViewModel, template); - }, - onRemove: () { - showDialog( - 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(); - exchangeViewModel - .exchangeTemplateStore - .remove( - template: - template); - exchangeViewModel - .exchangeTemplateStore - .update(); - }, - actionRightButton: () => - Navigator.of( - dialogContext) - .pop()); - }); - }, - ); - }); - }), - ], - ))) - ], - ), - bottomSectionPadding: - EdgeInsets.only(left: 24, right: 24, bottom: 24), - bottomSection: Column(children: [ - Padding( - padding: EdgeInsets.only(bottom: 15), - child: Observer(builder: (_) { - final description = - exchangeViewModel.provider is XMRTOExchangeProvider - ? S.of(context).amount_is_guaranteed - : S.of(context).amount_is_estimate; - return Center( - child: Text( - description, - style: TextStyle( - color: Theme.of(context) - .primaryTextTheme - .display4 - .decorationColor, - fontWeight: FontWeight.w500, - fontSize: 12), - ), - ); - }), - ), - isTemplate - ? PrimaryButton( - onPressed: () { - if (_formKey.currentState.validate()) { - exchangeViewModel.exchangeTemplateStore.addTemplate( - amount: exchangeViewModel.depositAmount, - depositCurrency: - exchangeViewModel.depositCurrency.toString(), - receiveCurrency: - exchangeViewModel.receiveCurrency.toString(), - provider: exchangeViewModel.provider.toString(), - depositAddress: exchangeViewModel.depositAddress, - receiveAddress: exchangeViewModel.receiveAddress); - exchangeViewModel.exchangeTemplateStore.update(); - Navigator.of(context).pop(); - } - }, - text: S.of(context).save, - color: Colors.green, - textColor: Colors.white) - : Observer( - builder: (_) => LoadingPrimaryButton( - text: S.of(context).exchange, - onPressed: () { - if (_formKey.currentState.validate()) { - exchangeViewModel.createTrade(); - } - }, - color: Palette.blueCraiola, - textColor: Colors.white, - isLoading: - exchangeViewModel.tradeState is TradeIsCreating, - )), - ]), - )); - } - - void applyTemplate( - ExchangeViewModel exchangeViewModel, ExchangeTemplate template) { - exchangeViewModel.changeDepositCurrency( - currency: CryptoCurrency.fromString(template.depositCurrency)); - exchangeViewModel.changeReceiveCurrency( - currency: CryptoCurrency.fromString(template.receiveCurrency)); - - switch (template.provider) { - case 'XMR.TO': - exchangeViewModel.changeProvider( - provider: exchangeViewModel.providerList[0]); - break; - case 'ChangeNOW': - exchangeViewModel.changeProvider( - provider: exchangeViewModel.providerList[1]); - break; - case 'MorphToken': - exchangeViewModel.changeProvider( - provider: exchangeViewModel.providerList[2]); - break; - } - - exchangeViewModel.changeDepositAmount(amount: template.amount); - exchangeViewModel.depositAddress = template.depositAddress; - exchangeViewModel.receiveAddress = template.receiveAddress; - } - - void _setReactions( - BuildContext context, ExchangeViewModel exchangeViewModel) { - if (_isReactionsSet) { - return; - } - - final depositAddressController = depositKey.currentState.addressController; - final depositAmountController = depositKey.currentState.amountController; - final receiveAddressController = receiveKey.currentState.addressController; - final receiveAmountController = receiveKey.currentState.amountController; - final limitsState = exchangeViewModel.limitsState; - - if (limitsState is LimitsLoadedSuccessfully) { - final min = limitsState.limits.min != null - ? limitsState.limits.min.toString() - : null; - final max = limitsState.limits.max != null - ? limitsState.limits.max.toString() - : null; - final key = depositKey; - key.currentState.changeLimits(min: min, max: max); - } - - _onCurrencyChange( - exchangeViewModel.receiveCurrency, exchangeViewModel, receiveKey); - _onCurrencyChange( - exchangeViewModel.depositCurrency, exchangeViewModel, depositKey); - - reaction( - (_) => exchangeViewModel.wallet.name, - (String _) => _onWalletNameChange( - exchangeViewModel, exchangeViewModel.receiveCurrency, receiveKey)); - - reaction( - (_) => exchangeViewModel.wallet.name, - (String _) => _onWalletNameChange( - exchangeViewModel, exchangeViewModel.depositCurrency, depositKey)); - - reaction( - (_) => exchangeViewModel.receiveCurrency, - (CryptoCurrency currency) => - _onCurrencyChange(currency, exchangeViewModel, receiveKey)); - - reaction( - (_) => exchangeViewModel.depositCurrency, - (CryptoCurrency currency) => - _onCurrencyChange(currency, exchangeViewModel, depositKey)); - - reaction((_) => exchangeViewModel.depositAmount, (String amount) { - if (depositKey.currentState.amountController.text != amount) { - depositKey.currentState.amountController.text = amount; - } - }); - - reaction((_) => exchangeViewModel.depositAddress, (String address) { - if (depositKey.currentState.addressController.text != address) { - depositKey.currentState.addressController.text = address; - } - }); - - reaction((_) => exchangeViewModel.isDepositAddressEnabled, - (bool isEnabled) { - depositKey.currentState.isAddressEditable(isEditable: isEnabled); - }); - - reaction((_) => exchangeViewModel.receiveAmount, (String amount) { - if (receiveKey.currentState.amountController.text != amount) { - receiveKey.currentState.amountController.text = amount; - } - }); - - reaction((_) => exchangeViewModel.receiveAddress, (String address) { - if (receiveKey.currentState.addressController.text != address) { - receiveKey.currentState.addressController.text = address; - } - }); - - reaction((_) => exchangeViewModel.isReceiveAddressEnabled, - (bool isEnabled) { - receiveKey.currentState.isAddressEditable(isEditable: isEnabled); - }); - - reaction((_) => exchangeViewModel.tradeState, (ExchangeTradeState state) { - if (state is TradeIsCreatedFailure) { - WidgetsBinding.instance.addPostFrameCallback((_) { - showDialog( - context: context, - builder: (BuildContext context) { - return AlertWithOneAction( - alertTitle: S.of(context).error, - alertContent: state.error, - buttonText: S.of(context).ok, - buttonAction: () => Navigator.of(context).pop()); - }); - }); - } - if (state is TradeIsCreatedSuccessfully) { - Navigator.of(context).pushNamed(Routes.exchangeConfirm); - } - }); - - reaction((_) => exchangeViewModel.limitsState, (LimitsState state) { - String min; - String max; - - if (state is LimitsLoadedSuccessfully) { - min = state.limits.min != null ? state.limits.min.toString() : null; - max = state.limits.max != null ? state.limits.max.toString() : null; - } - - if (state is LimitsLoadedFailure) { - min = '0'; - max = '0'; - } - - if (state is LimitsIsLoading) { - min = '...'; - max = '...'; - } - - depositKey.currentState.changeLimits(min: min, max: max); - receiveKey.currentState.changeLimits(min: null, max: null); - }); - - depositAddressController.addListener( - () => exchangeViewModel.depositAddress = depositAddressController.text); - - depositAmountController.addListener(() { - if (depositAmountController.text != exchangeViewModel.depositAmount) { - exchangeViewModel.changeDepositAmount( - amount: depositAmountController.text); - } - }); - - receiveAddressController.addListener( - () => exchangeViewModel.receiveAddress = receiveAddressController.text); - - receiveAmountController.addListener(() { - if (receiveAmountController.text != exchangeViewModel.receiveAmount) { - exchangeViewModel.changeReceiveAmount( - amount: receiveAmountController.text); - } - }); - - reaction((_) => exchangeViewModel.wallet.address, (String address) { - if (exchangeViewModel.depositCurrency == CryptoCurrency.xmr) { - depositKey.currentState.changeAddress(address: address); - } - - if (exchangeViewModel.receiveCurrency == CryptoCurrency.xmr) { - receiveKey.currentState.changeAddress(address: address); - } - }); - - _isReactionsSet = true; - } - - void _onCurrencyChange(CryptoCurrency currency, - ExchangeViewModel exchangeViewModel, GlobalKey key) { - final isCurrentTypeWallet = currency == exchangeViewModel.wallet.currency; - - key.currentState.changeSelectedCurrency(currency); - key.currentState.changeWalletName( - isCurrentTypeWallet ? exchangeViewModel.wallet.name : null); - - key.currentState.changeAddress( - address: isCurrentTypeWallet ? exchangeViewModel.wallet.address : ''); - - key.currentState.changeAmount(amount: ''); - } - - void _onWalletNameChange(ExchangeViewModel exchangeViewModel, - CryptoCurrency currency, GlobalKey key) { - final isCurrentTypeWallet = currency == exchangeViewModel.wallet.currency; - - if (isCurrentTypeWallet) { - key.currentState.changeWalletName(exchangeViewModel.wallet.name); - key.currentState.addressController.text = - exchangeViewModel.wallet.address; - } else if (key.currentState.addressController.text == - exchangeViewModel.wallet.address) { - key.currentState.changeWalletName(null); - key.currentState.addressController.text = null; - } - } -} diff --git a/lib/src/screens/send/send_page.dart b/lib/src/screens/send/send_page.dart index edbf1c2f5..434d37ba8 100644 --- a/lib/src/screens/send/send_page.dart +++ b/lib/src/screens/send/send_page.dart @@ -16,7 +16,6 @@ import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; import 'package:cake_wallet/view_model/send/send_view_model.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cake_wallet/src/widgets/top_panel.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; import 'package:cake_wallet/src/screens/send/widgets/confirm_sending_alert.dart'; @@ -43,98 +42,188 @@ class SendPage extends BasePage { Color get titleColor => Colors.white; @override - Color get backgroundLightColor => Colors.transparent; + bool get resizeToAvoidBottomPadding => false; @override - bool get resizeToAvoidBottomPadding => false; + bool get extendBodyBehindAppBar => true; + + @override + AppBarStyle get appBarStyle => AppBarStyle.transparent; @override Widget trailing(context) => TrailButton( caption: S.of(context).clear, onPressed: () => sendViewModel.reset()); - @override - Color get backgroundDarkColor => Colors.transparent; - - @override - Widget build(BuildContext context) { - return Scaffold( - resizeToAvoidBottomPadding: resizeToAvoidBottomPadding, - body: Container( - color: Theme.of(context).backgroundColor, child: body(context))); - } - @override Widget body(BuildContext context) { _setEffects(context); - return ScrollableWithBottomSection( - contentPadding: EdgeInsets.only(bottom: 24), - content: Column( - children: [ - TopPanel( - edgeInsets: EdgeInsets.all(0), - gradient: LinearGradient(colors: [ - Theme.of(context).primaryTextTheme.subhead.color, - Theme.of(context).primaryTextTheme.subhead.decorationColor, - ], begin: Alignment.topLeft, end: Alignment.bottomRight), - widget: Form( - key: _formKey, - child: Column(children: [ - CupertinoNavigationBar( - leading: leading(context), - middle: middle(context), - trailing: trailing(context), - backgroundColor: Colors.transparent, - border: null, + return Container( + color: Theme.of(context).backgroundColor, + child: ScrollableWithBottomSection( + contentPadding: EdgeInsets.only(bottom: 24), + content: Column( + children: [ + Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.only( + bottomLeft: Radius.circular(24), + bottomRight: Radius.circular(24) + ), + gradient: LinearGradient(colors: [ + Theme.of(context).primaryTextTheme.subhead.color, + Theme.of(context).primaryTextTheme.subhead.decorationColor, + ], begin: Alignment.topLeft, end: Alignment.bottomRight), ), - Padding( - padding: EdgeInsets.fromLTRB(24, 24, 24, 32), - child: Column( - children: [ - AddressTextField( - controller: _addressController, - focusNode: _focusNode, - onURIScanned: (uri) { - var address = ''; - var amount = ''; + child: Form( + key: _formKey, + child: Column(children: [ + Padding( + padding: EdgeInsets.fromLTRB(24, 90, 24, 32), + child: Column( + children: [ + AddressTextField( + controller: _addressController, + focusNode: _focusNode, + onURIScanned: (uri) { + var address = ''; + var amount = ''; - if (uri != null) { - address = uri.path; - amount = uri.queryParameters['tx_amount']; - } else { - address = uri.toString(); - } + if (uri != null) { + address = uri.path; + amount = uri.queryParameters['tx_amount']; + } else { + address = uri.toString(); + } - _addressController.text = address; - _cryptoAmountController.text = amount; - }, - options: [ - AddressTextFieldOption.paste, - AddressTextFieldOption.qrCode, - AddressTextFieldOption.addressBook - ], - buttonColor: - Theme.of(context).primaryTextTheme.display1.color, - borderColor: - Theme.of(context).primaryTextTheme.headline.color, - textStyle: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: Colors.white), - hintStyle: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: Theme.of(context) - .primaryTextTheme - .headline - .decorationColor), - validator: sendViewModel.addressValidator, - ), - Observer(builder: (_) { - return Padding( - padding: const EdgeInsets.only(top: 20), - child: BaseTextFormField( - controller: _cryptoAmountController, + _addressController.text = address; + _cryptoAmountController.text = amount; + }, + options: [ + AddressTextFieldOption.paste, + AddressTextFieldOption.qrCode, + AddressTextFieldOption.addressBook + ], + buttonColor: + Theme.of(context).primaryTextTheme.display1.color, + borderColor: + Theme.of(context).primaryTextTheme.headline.color, + textStyle: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w500, + color: Colors.white), + hintStyle: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w500, + color: Theme.of(context) + .primaryTextTheme + .headline + .decorationColor), + validator: sendViewModel.addressValidator, + ), + Observer(builder: (_) { + return Padding( + padding: const EdgeInsets.only(top: 20), + child: BaseTextFormField( + controller: _cryptoAmountController, + keyboardType: TextInputType.numberWithOptions( + signed: false, decimal: true), + inputFormatters: [ + BlacklistingTextInputFormatter( + RegExp('[\\-|\\ |\\,]')) + ], + 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: 12, + fontWeight: FontWeight.bold, + color: Theme.of(context) + .primaryTextTheme + .display1 + .decorationColor)), + ), + ), + ), + 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 + .decorationColor, + fontWeight: FontWeight.w500, + fontSize: 14), + validator: sendViewModel.amountValidator)); + }), + Observer( + builder: (_) => Padding( + padding: EdgeInsets.only(top: 10), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Text( + S.of(context).available_balance + ':', + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w600, + color: Theme.of(context) + .primaryTextTheme + .headline + .decorationColor), + )), + Text( + sendViewModel.balance, + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w600, + color: Theme.of(context) + .primaryTextTheme + .headline + .decorationColor), + ) + ], + ), + )), + Padding( + padding: const EdgeInsets.only(top: 20), + child: BaseTextFormField( + controller: _fiatAmountController, keyboardType: TextInputType.numberWithOptions( signed: false, decimal: true), inputFormatters: [ @@ -143,43 +232,14 @@ class SendPage extends BasePage { ], prefixIcon: Padding( padding: EdgeInsets.only(top: 9), - child: - Text(sendViewModel.currency.title + ':', + child: Text(sendViewModel.fiat.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: 12, - fontWeight: FontWeight.bold, - color: Theme.of(context) - .primaryTextTheme - .display1 - .decorationColor)), - ), - ), - ), - hintText: '0.0000', + hintText: '0.00', borderColor: Theme.of(context) .primaryTextTheme .headline @@ -195,262 +255,194 @@ class SendPage extends BasePage { .decorationColor, fontWeight: FontWeight.w500, fontSize: 14), - validator: sendViewModel.amountValidator)); - }), - Observer( - builder: (_) => Padding( - padding: EdgeInsets.only(top: 10), - child: Row( - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: Text( - S.of(context).available_balance + ':', - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Theme.of(context) - .primaryTextTheme - .headline - .decorationColor), - )), - Text( - sendViewModel.balance, + )), + Observer( + builder: (_) => GestureDetector( + onTap: () => + _setTransactionPriority(context), + child: Container( + padding: EdgeInsets.only(top: 24), + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text(S.of(context).send_estimated_fee, + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w500, + //color: Theme.of(context).primaryTextTheme.display2.color, + color: Colors.white)), + Container( + child: Row( + children: [ + Text( + sendViewModel.estimatedFee + .toString() + + ' ' + + sendViewModel + .currency.title, + style: TextStyle( + fontSize: 12, + fontWeight: + FontWeight.w600, + //color: Theme.of(context).primaryTextTheme.display2.color, + color: Colors.white)), + Padding( + padding: + EdgeInsets.only(left: 5), + child: Icon( + Icons.arrow_forward_ios, + size: 12, + color: Colors.white, + ), + ) + ], + ), + ) + ], + ), + ), + )) + ], + ), + ) + ]), + ), + ), + Padding( + padding: EdgeInsets.only(top: 30, left: 24, bottom: 24), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + S.of(context).send_templates, + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w600, + color: Theme.of(context) + .primaryTextTheme + .display4 + .color), + ) + ], + ), + ), + Container( + height: 40, + width: double.infinity, + padding: EdgeInsets.only(left: 24), + child: SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Row( + children: [ + GestureDetector( + onTap: () => Navigator.of(context) + .pushNamed(Routes.sendTemplate), + child: Container( + padding: EdgeInsets.only(left: 1, right: 10), + child: DottedBorder( + borderType: BorderType.RRect, + dashPattern: [6, 4], + color: Theme.of(context) + .primaryTextTheme + .display2 + .decorationColor, + strokeWidth: 2, + radius: Radius.circular(20), + child: Container( + height: 34, + width: 75, + padding: EdgeInsets.only(left: 10, right: 10), + alignment: Alignment.center, + decoration: BoxDecoration( + borderRadius: + BorderRadius.all(Radius.circular(20)), + color: Colors.transparent, + ), + child: Text( + S.of(context).send_new, style: TextStyle( - fontSize: 12, + fontSize: 14, fontWeight: FontWeight.w600, color: Theme.of(context) .primaryTextTheme - .headline - .decorationColor), - ) - ], - ), - )), - Padding( - padding: const EdgeInsets.only(top: 20), - child: BaseTextFormField( - controller: _fiatAmountController, - keyboardType: TextInputType.numberWithOptions( - signed: false, decimal: true), - inputFormatters: [ - BlacklistingTextInputFormatter( - RegExp('[\\-|\\ |\\,]')) - ], - prefixIcon: Padding( - padding: EdgeInsets.only(top: 9), - child: Text(sendViewModel.fiat.title + ':', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: Colors.white, - )), - ), - hintText: '0.00', - 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 - .decorationColor, - fontWeight: FontWeight.w500, - fontSize: 14), - )), - Observer( - builder: (_) => GestureDetector( - onTap: () => - _setTransactionPriority(context), - child: Container( - padding: EdgeInsets.only(top: 24), - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Text(S.of(context).send_estimated_fee, - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w500, - //color: Theme.of(context).primaryTextTheme.display2.color, - color: Colors.white)), - Container( - child: Row( - children: [ - Text( - sendViewModel.estimatedFee - .toString() + - ' ' + - sendViewModel - .currency.title, - style: TextStyle( - fontSize: 12, - fontWeight: - FontWeight.w600, - //color: Theme.of(context).primaryTextTheme.display2.color, - color: Colors.white)), - Padding( - padding: - EdgeInsets.only(left: 5), - child: Icon( - Icons.arrow_forward_ios, - size: 12, - color: Colors.white, - ), - ) - ], - ), - ) - ], - ), - ), - )) + .display3 + .color), + ), + )), + ), + ), + // 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 TemplateTile( + // key: UniqueKey(), + // to: template.name, + // amount: template.amount, + // from: template.cryptoCurrency, + // onTap: () { + // _addressController.text = template.address; + // _cryptoAmountController.text = template.amount; + // getOpenaliasRecord(context); + // }, + // onRemove: () { + // showDialog( + // 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() + // ); + // } + // ); + // }, + // ); + // } + // ); + // } + // ) ], ), - ) - ]), - ), + ), + ) + ], ), - Padding( - padding: EdgeInsets.only(top: 30, left: 24, bottom: 24), - child: Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Text( - S.of(context).send_templates, - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.w600, - color: Theme.of(context) - .primaryTextTheme - .display4 - .color), - ) - ], - ), - ), - Container( - height: 40, - width: double.infinity, - padding: EdgeInsets.only(left: 24), - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: Row( - children: [ - GestureDetector( - onTap: () => Navigator.of(context) - .pushNamed(Routes.sendTemplate), - child: Container( - padding: EdgeInsets.only(left: 1, right: 10), - child: DottedBorder( - borderType: BorderType.RRect, - dashPattern: [6, 4], - color: Theme.of(context) - .primaryTextTheme - .display2 - .decorationColor, - strokeWidth: 2, - radius: Radius.circular(20), - child: Container( - height: 34, - width: 75, - padding: EdgeInsets.only(left: 10, right: 10), - alignment: Alignment.center, - decoration: BoxDecoration( - borderRadius: - BorderRadius.all(Radius.circular(20)), - color: Colors.transparent, - ), - child: Text( - S.of(context).send_new, - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w600, - color: Theme.of(context) - .primaryTextTheme - .display3 - .color), - ), - )), - ), - ), - // 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 TemplateTile( - // key: UniqueKey(), - // to: template.name, - // amount: template.amount, - // from: template.cryptoCurrency, - // onTap: () { - // _addressController.text = template.address; - // _cryptoAmountController.text = template.amount; - // getOpenaliasRecord(context); - // }, - // onRemove: () { - // showDialog( - // 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() - // ); - // } - // ); - // }, - // ); - // } - // ); - // } - // ) - ], - ), - ), - ) - ], + bottomSectionPadding: EdgeInsets.only(left: 24, right: 24, bottom: 24), + bottomSection: Observer(builder: (_) { + return LoadingPrimaryButton( + onPressed: () { + if (_formKey.currentState.validate()) { + print('SENT!!!'); + } + }, + text: S.of(context).send, + color: Palette.blueCraiola, + textColor: Colors.white, + isLoading: sendViewModel.state is TransactionIsCreating || + sendViewModel.state is TransactionCommitting, + isDisabled: + false // FIXME !(syncStore.status is SyncedSyncStatus), + ); + }) ), - bottomSectionPadding: EdgeInsets.only(left: 24, right: 24, bottom: 24), - bottomSection: Observer(builder: (_) { - return LoadingPrimaryButton( - onPressed: () { - if (_formKey.currentState.validate()) { - print('SENT!!!'); - } - }, - text: S.of(context).send, - color: Palette.blueCraiola, - textColor: Colors.white, - isLoading: sendViewModel.state is TransactionIsCreating || - sendViewModel.state is TransactionCommitting, - isDisabled: - false // FIXME !(syncStore.status is SyncedSyncStatus), - ); - }) ); } diff --git a/lib/src/screens/send/send_template_page.dart b/lib/src/screens/send/send_template_page.dart index 5487dc71e..fcda9b7af 100644 --- a/lib/src/screens/send/send_template_page.dart +++ b/lib/src/screens/send/send_template_page.dart @@ -1,14 +1,27 @@ +import 'package:cake_wallet/src/widgets/address_text_field.dart'; +import 'package:cake_wallet/src/widgets/base_text_form_field.dart'; +import 'package:cake_wallet/src/widgets/primary_button.dart'; +import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/view_model/send/send_view_model.dart'; -import 'package:cake_wallet/src/screens/send/widgets/base_send_widget.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_mobx/flutter_mobx.dart'; +import 'package:mobx/mobx.dart'; class SendTemplatePage extends BasePage { SendTemplatePage({@required this.sendViewModel}); final SendViewModel sendViewModel; + final _addressController = TextEditingController(); + final _cryptoAmountController = TextEditingController(); + final _fiatAmountController = TextEditingController(); + final _nameController = TextEditingController(); + final _formKey = GlobalKey(); + + bool _effectsInstalled = false; @override String get title => S.current.exchange_new_template; @@ -16,27 +29,234 @@ class SendTemplatePage extends BasePage { @override Color get titleColor => Colors.white; - @override - Color get backgroundLightColor => Colors.transparent; - - @override - Color get backgroundDarkColor => Colors.transparent; - @override bool get resizeToAvoidBottomPadding => false; @override - Widget body(BuildContext context) => BaseSendWidget( - sendViewModel: sendViewModel, - leading: leading(context), - middle: middle(context), - isTemplate: true); + bool get extendBodyBehindAppBar => true; @override - Widget build(BuildContext context) { - return Scaffold( - resizeToAvoidBottomPadding: resizeToAvoidBottomPadding, - body: Container( - color: Theme.of(context).backgroundColor, child: body(context))); + AppBarStyle get appBarStyle => AppBarStyle.transparent; + + @override + Widget body(BuildContext context) { + _setEffects(context); + + return Container( + color: Theme.of(context).backgroundColor, + child: ScrollableWithBottomSection( + contentPadding: EdgeInsets.only(bottom: 24), + content: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.only( + bottomLeft: Radius.circular(24), + bottomRight: Radius.circular(24) + ), + gradient: LinearGradient(colors: [ + Theme.of(context).primaryTextTheme.subhead.color, + Theme.of(context).primaryTextTheme.subhead.decorationColor, + ], begin: Alignment.topLeft, end: Alignment.bottomRight), + ), + child: Form( + key: _formKey, + child: Column(children: [ + Padding( + padding: EdgeInsets.fromLTRB(24, 90, 24, 32), + child: Column( + children: [ + BaseTextFormField( + controller: _nameController, + hintText: S.of(context).send_name, + 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 + .decorationColor, + fontWeight: FontWeight.w500, + fontSize: 14), + validator: sendViewModel.templateValidator, + ), + Padding( + padding: EdgeInsets.only(top: 20), + child: AddressTextField( + controller: _addressController, + onURIScanned: (uri) { + var address = ''; + var amount = ''; + + if (uri != null) { + address = uri.path; + amount = uri.queryParameters['tx_amount']; + } else { + address = uri.toString(); + } + + _addressController.text = address; + _cryptoAmountController.text = amount; + }, + options: [ + AddressTextFieldOption.paste, + AddressTextFieldOption.qrCode, + AddressTextFieldOption.addressBook + ], + buttonColor: + Theme.of(context).primaryTextTheme.display1.color, + borderColor: + Theme.of(context).primaryTextTheme.headline.color, + textStyle: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w500, + color: Colors.white), + hintStyle: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w500, + color: Theme.of(context) + .primaryTextTheme + .headline + .decorationColor), + validator: sendViewModel.addressValidator, + ), + ), + Observer(builder: (_) { + return Padding( + padding: const EdgeInsets.only(top: 20), + child: BaseTextFormField( + controller: _cryptoAmountController, + keyboardType: TextInputType.numberWithOptions( + signed: false, decimal: true), + inputFormatters: [ + BlacklistingTextInputFormatter( + RegExp('[\\-|\\ |\\,]')) + ], + prefixIcon: Padding( + padding: EdgeInsets.only(top: 9), + child: + Text(sendViewModel.currency.title + ':', + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + color: Colors.white, + )), + ), + 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 + .decorationColor, + fontWeight: FontWeight.w500, + fontSize: 14), + validator: sendViewModel.amountValidator)); + }), + Padding( + padding: const EdgeInsets.only(top: 20), + child: BaseTextFormField( + controller: _fiatAmountController, + keyboardType: TextInputType.numberWithOptions( + signed: false, decimal: true), + inputFormatters: [ + BlacklistingTextInputFormatter( + RegExp('[\\-|\\ |\\,]')) + ], + prefixIcon: Padding( + padding: EdgeInsets.only(top: 9), + child: Text(sendViewModel.fiat.title + ':', + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + color: Colors.white, + )), + ), + hintText: '0.00', + 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 + .decorationColor, + fontWeight: FontWeight.w500, + fontSize: 14), + )), + ], + ), + ) + ]), + ), + ), + bottomSectionPadding: EdgeInsets.only(left: 24, right: 24, bottom: 24), + 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(); + Navigator.of(context).pop(); + } + }, + text: S.of(context).save, + color: Colors.green, + textColor: Colors.white), + ), + ); + } + + void _setEffects(BuildContext context) { + if (_effectsInstalled) { + return; + } + + reaction((_) => sendViewModel.fiatAmount, (String amount) { + if (amount != _fiatAmountController.text) { + _fiatAmountController.text = amount; + } + }); + + reaction((_) => sendViewModel.cryptoAmount, (String amount) { + if (amount != _cryptoAmountController.text) { + _cryptoAmountController.text = amount; + } + }); + + reaction((_) => sendViewModel.address, (String address) { + if (address != _addressController.text) { + _addressController.text = address; + } + }); + + _addressController.addListener(() { + final address = _addressController.text; + + if (sendViewModel.address != address) { + sendViewModel.address = address; + } + }); + + _effectsInstalled = true; } } diff --git a/lib/src/screens/send/widgets/base_send_widget.dart b/lib/src/screens/send/widgets/base_send_widget.dart deleted file mode 100644 index bfbf3ae9a..000000000 --- a/lib/src/screens/send/widgets/base_send_widget.dart +++ /dev/null @@ -1,709 +0,0 @@ -import 'dart:ui'; -import 'package:cake_wallet/src/domain/common/transaction_priority.dart'; -import 'package:cake_wallet/src/widgets/picker.dart'; -import 'package:cake_wallet/src/widgets/primary_button.dart'; -import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; -import 'package:cake_wallet/view_model/send/send_view_model_state.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:cake_wallet/view_model/send/send_view_model.dart'; -import 'package:flutter/services.dart'; -import 'package:flutter_mobx/flutter_mobx.dart'; -import 'package:mobx/mobx.dart'; -import 'package:cake_wallet/palette.dart'; -import 'package:cake_wallet/src/widgets/address_text_field.dart'; -import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cake_wallet/src/widgets/top_panel.dart'; -import 'package:dotted_border/dotted_border.dart'; -import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; -import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; -import 'package:cake_wallet/src/screens/send/widgets/confirm_sending_alert.dart'; -import 'package:cake_wallet/src/screens/send/widgets/sending_alert.dart'; -import 'package:cake_wallet/src/widgets/template_tile.dart'; -import 'package:cake_wallet/src/widgets/base_text_form_field.dart'; -import 'package:cake_wallet/routes.dart'; - -class BaseSendWidget extends StatelessWidget { - BaseSendWidget( - {@required this.sendViewModel, - @required this.leading, - @required this.middle, - this.isTemplate = false}); - - final SendViewModel sendViewModel; - final bool isTemplate; - final Widget leading; - final Widget middle; - - final _addressController = TextEditingController(); - final _cryptoAmountController = TextEditingController(); - final _fiatAmountController = TextEditingController(); - final _nameController = TextEditingController(); - final _focusNode = FocusNode(); - final _formKey = GlobalKey(); - - bool _effectsInstalled = false; - - @override - Widget build(BuildContext context) { - _setEffects(context); - - return ScrollableWithBottomSection( - contentPadding: EdgeInsets.only(bottom: 24), - content: Column( - children: [ - TopPanel( - edgeInsets: EdgeInsets.all(0), - gradient: LinearGradient(colors: [ - Theme.of(context).primaryTextTheme.subhead.color, - Theme.of(context).primaryTextTheme.subhead.decorationColor, - ], begin: Alignment.topLeft, end: Alignment.bottomRight), - widget: Form( - key: _formKey, - child: Column(children: [ - CupertinoNavigationBar( - leading: leading, - middle: middle, - backgroundColor: Colors.transparent, - border: null, - ), - Padding( - padding: EdgeInsets.fromLTRB(24, 24, 24, 32), - child: Column( - children: [ - isTemplate - ? BaseTextFormField( - controller: _nameController, - hintText: S.of(context).send_name, - 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 - .decorationColor, - fontWeight: FontWeight.w500, - fontSize: 14), - validator: sendViewModel.templateValidator, - ) - : Offstage(), - Padding( - padding: EdgeInsets.only(top: isTemplate ? 20 : 0), - child: AddressTextField( - controller: _addressController, - // placeholder: S - // .of(context) - // .send_address(sendViewModel.cryptoCurrencyTitle), - focusNode: _focusNode, - onURIScanned: (uri) { - var address = ''; - var amount = ''; - - if (uri != null) { - address = uri.path; - amount = uri.queryParameters['tx_amount']; - } else { - address = uri.toString(); - } - - _addressController.text = address; - _cryptoAmountController.text = amount; - }, - options: [ - AddressTextFieldOption.paste, - AddressTextFieldOption.qrCode, - AddressTextFieldOption.addressBook - ], - buttonColor: - Theme.of(context).primaryTextTheme.display1.color, - borderColor: - Theme.of(context).primaryTextTheme.headline.color, - textStyle: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: Colors.white), - hintStyle: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: Theme.of(context) - .primaryTextTheme - .headline - .decorationColor), - validator: sendViewModel.addressValidator, - ), - ), - Observer(builder: (_) { - return Padding( - padding: const EdgeInsets.only(top: 20), - child: BaseTextFormField( - controller: _cryptoAmountController, - keyboardType: TextInputType.numberWithOptions( - signed: false, decimal: true), - inputFormatters: [ - BlacklistingTextInputFormatter( - RegExp('[\\-|\\ |\\,]')) - ], - prefixIcon: Padding( - padding: EdgeInsets.only(top: 9), - child: - Text(sendViewModel.currency.title + ':', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: Colors.white, - )), - ), - suffixIcon: isTemplate - ? Offstage() - : 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) - .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.amountValidator)); - }), - isTemplate - ? Offstage() - : Observer( - builder: (_) => Padding( - padding: EdgeInsets.only(top: 10), - child: Row( - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: Text( - S.of(context).available_balance + ':', - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Theme.of(context) - .primaryTextTheme - .headline - .decorationColor), - )), - Text( - sendViewModel.balance, - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Theme.of(context) - .primaryTextTheme - .headline - .decorationColor), - ) - ], - ), - )), - Padding( - padding: const EdgeInsets.only(top: 20), - child: BaseTextFormField( - controller: _fiatAmountController, - keyboardType: TextInputType.numberWithOptions( - signed: false, decimal: true), - inputFormatters: [ - BlacklistingTextInputFormatter( - RegExp('[\\-|\\ |\\,]')) - ], - prefixIcon: Padding( - padding: EdgeInsets.only(top: 9), - child: Text(sendViewModel.fiat.title + ':', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: Colors.white, - )), - ), - hintText: '0.00', - 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 - .decorationColor, - fontWeight: FontWeight.w500, - fontSize: 14), - )), - isTemplate - ? Offstage() - : Observer( - builder: (_) => GestureDetector( - onTap: () => - _setTransactionPriority(context), - child: Container( - padding: EdgeInsets.only(top: 24), - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Text(S.of(context).send_estimated_fee, - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w500, - //color: Theme.of(context).primaryTextTheme.display2.color, - color: Colors.white)), - Container( - child: Row( - children: [ - Text( - sendViewModel.estimatedFee - .toString() + - ' ' + - sendViewModel - .currency.title, - style: TextStyle( - fontSize: 12, - fontWeight: - FontWeight.w600, - //color: Theme.of(context).primaryTextTheme.display2.color, - color: Colors.white)), - Padding( - padding: - EdgeInsets.only(left: 5), - child: Icon( - Icons.arrow_forward_ios, - size: 12, - color: Colors.white, - ), - ) - ], - ), - ) - ], - ), - ), - )) - ], - ), - ) - ]), - ), - ), - isTemplate - ? Offstage() - : Padding( - padding: EdgeInsets.only(top: 30, left: 24, bottom: 24), - child: Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Text( - S.of(context).send_templates, - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.w600, - color: Theme.of(context) - .primaryTextTheme - .display4 - .color), - ) - ], - ), - ), - isTemplate - ? Offstage() - : Container( - height: 40, - width: double.infinity, - padding: EdgeInsets.only(left: 24), - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: Row( - children: [ - GestureDetector( - onTap: () => Navigator.of(context) - .pushNamed(Routes.sendTemplate), - child: Container( - padding: EdgeInsets.only(left: 1, right: 10), - child: DottedBorder( - borderType: BorderType.RRect, - dashPattern: [6, 4], - color: Theme.of(context) - .primaryTextTheme - .display2 - .decorationColor, - strokeWidth: 2, - radius: Radius.circular(20), - child: Container( - height: 34, - width: 75, - padding: EdgeInsets.only(left: 10, right: 10), - alignment: Alignment.center, - decoration: BoxDecoration( - borderRadius: - BorderRadius.all(Radius.circular(20)), - color: Colors.transparent, - ), - child: Text( - S.of(context).send_new, - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w600, - color: Theme.of(context) - .primaryTextTheme - .display3 - .color), - ), - )), - ), - ), - // 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 TemplateTile( - // key: UniqueKey(), - // to: template.name, - // amount: template.amount, - // from: template.cryptoCurrency, - // onTap: () { - // _addressController.text = template.address; - // _cryptoAmountController.text = template.amount; - // getOpenaliasRecord(context); - // }, - // onRemove: () { - // showDialog( - // 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() - // ); - // } - // ); - // }, - // ); - // } - // ); - // } - // ) - ], - ), - ), - ) - ], - ), - bottomSectionPadding: EdgeInsets.only(left: 24, right: 24, bottom: 24), - bottomSection: isTemplate - ? 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(); - Navigator.of(context).pop(); - } - }, - text: S.of(context).save, - color: Colors.green, - textColor: Colors.white) - : Observer(builder: (_) { - return LoadingPrimaryButton( - onPressed: () { - if (_formKey.currentState.validate()) { - print('SENT!!!'); - } - }, - text: S.of(context).send, - color: Palette.blueCraiola, - textColor: Colors.white, - isLoading: sendViewModel.state is TransactionIsCreating || - sendViewModel.state is TransactionCommitting, - isDisabled: - false // FIXME !(syncStore.status is SyncedSyncStatus), - ); - }), - ); - } - - void _setEffects(BuildContext context) { - if (_effectsInstalled) { - return; - } - - reaction((_) => sendViewModel.sendAll, (bool all) { - if (all) { - _cryptoAmountController.text = S.current.all; - _fiatAmountController.text = null; - } - }); - - reaction((_) => sendViewModel.fiatAmount, (String amount) { - if (amount != _fiatAmountController.text) { - _fiatAmountController.text = amount; - } - }); - - reaction((_) => sendViewModel.cryptoAmount, (String amount) { - if (sendViewModel.sendAll && amount != S.current.all) { - sendViewModel.sendAll = false; - } - - if (amount != _cryptoAmountController.text) { - _cryptoAmountController.text = amount; - } - }); - - reaction((_) => sendViewModel.address, (String address) { - if (address != _addressController.text) { - _addressController.text = address; - } - }); - - _addressController.addListener(() { - final address = _addressController.text; - - if (sendViewModel.address != address) { - sendViewModel.address = address; - } - }); - - reaction((_) => sendViewModel.state, (SendViewModelState state) { - if (state is SendingFailed) { - WidgetsBinding.instance.addPostFrameCallback((_) { - showDialog( - context: context, - builder: (BuildContext context) { - return AlertWithOneAction( - alertTitle: S.of(context).error, - alertContent: state.error, - buttonText: S.of(context).ok, - buttonAction: () => Navigator.of(context).pop()); - }); - }); - } - - if (state is TransactionCreatedSuccessfully) { - WidgetsBinding.instance.addPostFrameCallback((_) { - showDialog( - context: context, - builder: (BuildContext context) { - return ConfirmSendingAlert( - alertTitle: S.of(context).confirm_sending, - amount: S.of(context).send_amount, - amountValue: - sendViewModel.pendingTransaction.amountFormatted, - fee: S.of(context).send_fee, - feeValue: sendViewModel.pendingTransaction.feeFormatted, - leftButtonText: S.of(context).ok, - rightButtonText: S.of(context).cancel, - actionLeftButton: () { - Navigator.of(context).pop(); - sendViewModel.commitTransaction(); - showDialog( - context: context, - builder: (BuildContext context) { - return Observer(builder: (_) { - final state = sendViewModel.state; - - if (state is TransactionCommitted) { - return Stack( - children: [ - Container( - color: Theme.of(context).backgroundColor, - child: Center( - child: Image.asset( - 'assets/images/birthday_cake.png'), - ), - ), - Center( - child: Padding( - padding: EdgeInsets.only( - top: 220, left: 24, right: 24), - child: Text( - S.of(context).send_success, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - fontWeight: FontWeight.bold, - color: Theme.of(context) - .primaryTextTheme - .title - .color, - decoration: TextDecoration.none, - ), - ), - ), - ), - Positioned( - left: 24, - right: 24, - bottom: 24, - child: PrimaryButton( - onPressed: () => - Navigator.of(context).pop(), - text: S.of(context).send_got_it, - color: Colors.blue, - textColor: Colors.white)) - ], - ); - } - - return Stack( - children: [ - Container( - color: Theme.of(context).backgroundColor, - child: Center( - child: Image.asset( - 'assets/images/birthday_cake.png'), - ), - ), - BackdropFilter( - filter: ImageFilter.blur( - sigmaX: 3.0, sigmaY: 3.0), - child: Container( - decoration: BoxDecoration( - color: Theme.of(context) - .backgroundColor - .withOpacity(0.25)), - child: Center( - child: Padding( - padding: EdgeInsets.only(top: 220), - child: Text( - S.of(context).send_sending, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 22, - fontWeight: FontWeight.bold, - color: Theme.of(context) - .primaryTextTheme - .title - .color, - decoration: TextDecoration.none, - ), - ), - ), - ), - ), - ) - ], - ); - }); - }); - }, - actionRightButton: () => Navigator.of(context).pop()); - }); - }); - } - - if (state is TransactionCommitted) { - WidgetsBinding.instance.addPostFrameCallback((_) { - _addressController.text = ''; - _cryptoAmountController.text = ''; - }); - } - }); - - _effectsInstalled = true; - } - - Future getOpenaliasRecord(BuildContext context) async { - // final isOpenalias = - // await sendViewModel.isOpenaliasRecord(_addressController.text); - - // if (isOpenalias) { - // _addressController.text = sendViewModel.recordAddress; - - // await showDialog( - // 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()); - // }); - // } - } - - Future _setTransactionPriority(BuildContext context) async { - final items = TransactionPriority.all; - final selectedItem = items.indexOf(sendViewModel.transactionPriority); - - await showDialog( - builder: (_) => Picker( - items: items, - selectedAtIndex: selectedItem, - title: S.of(context).please_select, - mainAxisAlignment: MainAxisAlignment.center, - onItemSelected: (TransactionPriority priority) => null, - // sendViewModel.setTransactionPriority(priority), - isAlwaysShowScrollThumb: true, - ), - context: context); - } -} diff --git a/lib/src/widgets/top_panel.dart b/lib/src/widgets/top_panel.dart deleted file mode 100644 index d456d1a39..000000000 --- a/lib/src/widgets/top_panel.dart +++ /dev/null @@ -1,44 +0,0 @@ -import 'package:flutter/material.dart'; - -class TopPanel extends StatefulWidget { - TopPanel({ - @required this.widget, - this.edgeInsets = const EdgeInsets.all(24), - this.color, - this.gradient - }); - - final Color color; - final Widget widget; - final EdgeInsets edgeInsets; - final Gradient gradient; - - @override - TopPanelState createState() => TopPanelState(widget, edgeInsets, color, gradient); -} - -class TopPanelState extends State { - TopPanelState(this._widget, this._edgeInsets, this._color, this._gradient); - - final Color _color; - final Widget _widget; - final EdgeInsets _edgeInsets; - final Gradient _gradient; - - @override - Widget build(BuildContext context) { - return Container( - width: double.infinity, - padding: _edgeInsets, - decoration: BoxDecoration( - borderRadius: BorderRadius.only( - bottomLeft: Radius.circular(24), - bottomRight: Radius.circular(24) - ), - color: _color, - gradient: _gradient - ), - child: _widget, - ); - } -} \ No newline at end of file