import 'dart:ui'; import 'package:cake_wallet/exchange/exchange_provider.dart'; import 'package:cake_wallet/exchange/exchange_template.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; import 'package:cake_wallet/src/widgets/keyboard_done_button.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:keyboard_actions/keyboard_actions.dart'; import 'package:keyboard_actions/keyboard_actions_config.dart'; import 'package:keyboard_actions/keyboard_actions_item.dart'; import 'package:mobx/mobx.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cake_wallet/exchange/xmrto/xmrto_exchange_provider.dart'; // import 'package:cake_wallet/exchange/exchange_trade_state.dart'; // import 'package:cake_wallet/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/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'; import 'package:cake_wallet/src/screens/exchange/widgets/present_provider_picker.dart'; class ExchangeTemplatePage extends BasePage { ExchangeTemplatePage(this.exchangeViewModel); final ExchangeViewModel exchangeViewModel; final depositKey = GlobalKey(); final receiveKey = GlobalKey(); final _formKey = GlobalKey(); final _depositAmountFocus = FocusNode(); final _receiveAmountFocus = FocusNode(); var _isReactionsSet = false; @override String get title => S.current.exchange_new_template; @override Color get titleColor => Colors.white; @override bool get extendBodyBehindAppBar => true; @override AppBarStyle get appBarStyle => AppBarStyle.transparent; @override Widget trailing(BuildContext context) => PresentProviderPicker(exchangeViewModel: exchangeViewModel); @override 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, ); 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 KeyboardActions( disableScroll: true, config: KeyboardActionsConfig( keyboardActionsPlatform: KeyboardActionsPlatform.IOS, keyboardBarColor: Theme.of(context).accentTextTheme.body2.backgroundColor, nextFocus: false, actions: [ KeyboardActionsItem( focusNode: _depositAmountFocus, toolbarButtons: [(_) => KeyboardDoneButton()]), KeyboardActionsItem( focusNode: _receiveAmountFocus, toolbarButtons: [(_) => KeyboardDoneButton()]) ]), child: 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( amountFocusNode: _depositAmountFocus, key: depositKey, title: S.of(context).you_will_send, initialCurrency: exchangeViewModel.depositCurrency, initialWalletName: depositWalletName, initialAddress: exchangeViewModel .depositCurrency == exchangeViewModel.wallet.currency ? exchangeViewModel.wallet.walletAddresses.address : exchangeViewModel.depositAddress, initialIsAmountEditable: true, initialIsAddressEditable: exchangeViewModel .isDepositAddressEnabled, isAmountEstimated: false, hasRefundAddress: true, isMoneroWallet: exchangeViewModel.isMoneroWallet, 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( amountFocusNode: _receiveAmountFocus, key: receiveKey, title: S.of(context).you_will_get, initialCurrency: exchangeViewModel.receiveCurrency, initialWalletName: receiveWalletName, initialAddress: exchangeViewModel.receiveCurrency == exchangeViewModel.wallet.currency ? exchangeViewModel.wallet.walletAddresses.address : exchangeViewModel.receiveAddress, initialIsAmountEditable: exchangeViewModel.provider is XMRTOExchangeProvider ? true : false, initialIsAddressEditable: exchangeViewModel.isReceiveAddressEnabled, isAmountEstimated: true, isMoneroWallet: exchangeViewModel.isMoneroWallet, currencies: exchangeViewModel.receiveCurrencies, 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, textAlign: TextAlign.center, style: TextStyle( color: Theme.of(context) .primaryTextTheme .display4 .decorationColor, fontWeight: FontWeight.w500, fontSize: 12), ), ); }), ), PrimaryButton( onPressed: () { if (_formKey.currentState.validate()) { exchangeViewModel.addTemplate( amount: exchangeViewModel.depositAmount, depositCurrency: exchangeViewModel.depositCurrency.toString(), receiveCurrency: exchangeViewModel.receiveCurrency.toString(), provider: exchangeViewModel.provider.toString(), depositAddress: exchangeViewModel.depositAddress, receiveAddress: exchangeViewModel.receiveAddress); exchangeViewModel.updateTemplate(); 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; // FIXME: FIXME // 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.provider, (ExchangeProvider provider) { provider is XMRTOExchangeProvider ? receiveKey.currentState.isAmountEditable(isEditable: true) : receiveKey.currentState.isAmountEditable(isEditable: false); }); /*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); exchangeViewModel.isReceiveAmountEntered = false; } }); receiveAddressController.addListener( () => exchangeViewModel.receiveAddress = receiveAddressController.text); receiveAmountController.addListener(() { if (receiveAmountController.text != exchangeViewModel.receiveAmount) { exchangeViewModel.changeReceiveAmount( amount: receiveAmountController.text); exchangeViewModel.isReceiveAmountEntered = true; } }); reaction((_) => exchangeViewModel.wallet.walletAddresses.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.walletAddresses.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.walletAddresses.address; } else if (key.currentState.addressController.text == exchangeViewModel.wallet.walletAddresses.address) { key.currentState.changeWalletName(null); key.currentState.addressController.text = null; } } }