mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2025-05-11 02:52:13 +00:00
* [skip-ci] wip * [skip-ci] styles still need updating * working but needs style updates * fix checkbox caption color * sort mweb coins to be last when selecting inputs * ui fixes * [skip-ci] default to mweb-checkbox being off * adaptable page view builder + workaround for keyboard actions * Fix checkbox themeing and send card sizing * Update lib/src/screens/send/widgets/send_card.dart --------- Co-authored-by: tuxpizza <tuxsudo@tux.pizza> Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>
626 lines
25 KiB
Dart
626 lines
25 KiB
Dart
import 'package:cake_wallet/entities/priority_for_wallet_type.dart';
|
|
import 'package:cake_wallet/src/screens/receive/widgets/currency_input_field.dart';
|
|
import 'package:cake_wallet/src/widgets/picker.dart';
|
|
import 'package:cake_wallet/src/widgets/standard_checkbox.dart';
|
|
import 'package:cake_wallet/themes/extensions/keyboard_theme.dart';
|
|
import 'package:cake_wallet/src/screens/exchange/widgets/currency_picker.dart';
|
|
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
|
|
import 'package:cake_wallet/utils/payment_request.dart';
|
|
import 'package:cake_wallet/utils/responsive_layout_util.dart';
|
|
import 'package:cw_core/crypto_currency.dart';
|
|
import 'package:cw_core/currency.dart';
|
|
import 'package:cake_wallet/routes.dart';
|
|
import 'package:cake_wallet/src/widgets/keyboard_done_button.dart';
|
|
import 'package:cake_wallet/view_model/send/output.dart';
|
|
import 'package:cw_core/transaction_priority.dart';
|
|
import 'package:cw_core/unspent_coin_type.dart';
|
|
import 'package:cw_core/wallet_type.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_mobx/flutter_mobx.dart';
|
|
import 'package:mobx/mobx.dart';
|
|
import 'package:keyboard_actions/keyboard_actions.dart';
|
|
import 'package:cake_wallet/view_model/send/send_view_model.dart';
|
|
import 'package:cake_wallet/utils/show_pop_up.dart';
|
|
import 'package:cake_wallet/src/widgets/address_text_field.dart';
|
|
import 'package:cake_wallet/generated/i18n.dart';
|
|
import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
|
|
import 'package:cake_wallet/themes/extensions/send_page_theme.dart';
|
|
|
|
import '../../../../themes/extensions/cake_text_theme.dart';
|
|
import '../../../../themes/theme_base.dart';
|
|
|
|
class SendCard extends StatefulWidget {
|
|
SendCard({
|
|
Key? key,
|
|
required this.output,
|
|
required this.sendViewModel,
|
|
required this.currentTheme,
|
|
this.initialPaymentRequest,
|
|
this.cryptoAmountFocus,
|
|
this.fiatAmountFocus,
|
|
}) : super(key: key);
|
|
|
|
final Output output;
|
|
final SendViewModel sendViewModel;
|
|
final PaymentRequest? initialPaymentRequest;
|
|
final FocusNode? cryptoAmountFocus;
|
|
final FocusNode? fiatAmountFocus;
|
|
final ThemeBase currentTheme;
|
|
|
|
|
|
@override
|
|
SendCardState createState() => SendCardState(
|
|
output: output,
|
|
sendViewModel: sendViewModel,
|
|
initialPaymentRequest: initialPaymentRequest,
|
|
currentTheme: currentTheme
|
|
// cryptoAmountFocus: cryptoAmountFocus ?? FocusNode(),
|
|
// fiatAmountFocus: fiatAmountFocus ?? FocusNode(),
|
|
// cryptoAmountFocus: FocusNode(),
|
|
// fiatAmountFocus: FocusNode(),
|
|
);
|
|
}
|
|
|
|
class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<SendCard> {
|
|
SendCardState({
|
|
required this.output,
|
|
required this.sendViewModel,
|
|
this.initialPaymentRequest,
|
|
required this.currentTheme,
|
|
}) : addressController = TextEditingController(),
|
|
cryptoAmountController = TextEditingController(),
|
|
fiatAmountController = TextEditingController(),
|
|
noteController = TextEditingController(),
|
|
extractedAddressController = TextEditingController(),
|
|
addressFocusNode = FocusNode();
|
|
|
|
static const prefixIconWidth = 34.0;
|
|
static const prefixIconHeight = 34.0;
|
|
|
|
final ThemeBase currentTheme;
|
|
final Output output;
|
|
final SendViewModel sendViewModel;
|
|
final PaymentRequest? initialPaymentRequest;
|
|
|
|
final TextEditingController addressController;
|
|
final TextEditingController cryptoAmountController;
|
|
final TextEditingController fiatAmountController;
|
|
final TextEditingController noteController;
|
|
final TextEditingController extractedAddressController;
|
|
final FocusNode addressFocusNode;
|
|
|
|
bool _effectsInstalled = false;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
|
|
/// if the current wallet doesn't match the one in the qr code
|
|
if (initialPaymentRequest != null &&
|
|
sendViewModel.walletCurrencyName != initialPaymentRequest!.scheme.toLowerCase()) {
|
|
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
|
if (mounted) {
|
|
showPopUp<void>(
|
|
context: context,
|
|
builder: (BuildContext context) {
|
|
return AlertWithOneAction(
|
|
alertTitle: S.of(context).error,
|
|
alertContent: S.of(context).unmatched_currencies,
|
|
buttonText: S.of(context).ok,
|
|
buttonAction: () => Navigator.of(context).pop());
|
|
});
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
super.build(context);
|
|
_setEffects(context);
|
|
|
|
// return Stack(
|
|
// children: [
|
|
// return KeyboardActions(
|
|
// config: KeyboardActionsConfig(
|
|
// keyboardActionsPlatform: KeyboardActionsPlatform.IOS,
|
|
// keyboardBarColor: Theme.of(context).extension<KeyboardTheme>()!.keyboardBarColor,
|
|
// nextFocus: false,
|
|
// actions: [
|
|
// KeyboardActionsItem(
|
|
// focusNode: cryptoAmountFocus,
|
|
// toolbarButtons: [(_) => KeyboardDoneButton()],
|
|
// ),
|
|
// KeyboardActionsItem(
|
|
// focusNode: fiatAmountFocus,
|
|
// toolbarButtons: [(_) => KeyboardDoneButton()],
|
|
// )
|
|
// ],
|
|
// ),
|
|
// // child: Container(
|
|
// // height: 0,
|
|
// // color: Colors.transparent,
|
|
// // ), child:
|
|
// child: SizedBox(
|
|
// height: 100,
|
|
// width: 100,
|
|
// child: Text('Send Card'),
|
|
// ),
|
|
// );
|
|
return Container(
|
|
decoration: responsiveLayoutUtil.shouldRenderMobileUI
|
|
? BoxDecoration(
|
|
borderRadius: BorderRadius.only(
|
|
bottomLeft: Radius.circular(24), bottomRight: Radius.circular(24)),
|
|
gradient: LinearGradient(
|
|
colors: [
|
|
Theme.of(context).extension<SendPageTheme>()!.firstGradientColor,
|
|
Theme.of(context).extension<SendPageTheme>()!.secondGradientColor,
|
|
],
|
|
begin: Alignment.topLeft,
|
|
end: Alignment.bottomRight,
|
|
),
|
|
)
|
|
: null,
|
|
child: Padding(
|
|
padding: EdgeInsets.fromLTRB(
|
|
24,
|
|
responsiveLayoutUtil.shouldRenderMobileUI ? 110 : 55,
|
|
24,
|
|
responsiveLayoutUtil.shouldRenderMobileUI ? 32 : 0,
|
|
),
|
|
child: Observer(
|
|
builder: (_) => Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: <Widget>[
|
|
Observer(builder: (_) {
|
|
final validator = output.isParsedAddress
|
|
? sendViewModel.textValidator
|
|
: sendViewModel.addressValidator;
|
|
|
|
return AddressTextField(
|
|
addressKey: ValueKey('send_page_address_textfield_key'),
|
|
focusNode: addressFocusNode,
|
|
controller: addressController,
|
|
onURIScanned: (uri) {
|
|
final paymentRequest = PaymentRequest.fromUri(uri);
|
|
addressController.text = paymentRequest.address;
|
|
cryptoAmountController.text = paymentRequest.amount;
|
|
noteController.text = paymentRequest.note;
|
|
},
|
|
options: [
|
|
AddressTextFieldOption.paste,
|
|
AddressTextFieldOption.qrCode,
|
|
AddressTextFieldOption.addressBook
|
|
],
|
|
buttonColor: Theme.of(context).extension<SendPageTheme>()!.textFieldButtonColor,
|
|
borderColor: Theme.of(context).extension<SendPageTheme>()!.textFieldBorderColor,
|
|
textStyle:
|
|
TextStyle(fontSize: 14, fontWeight: FontWeight.w500, color: Colors.white),
|
|
hintStyle: TextStyle(
|
|
fontSize: 14,
|
|
fontWeight: FontWeight.w500,
|
|
color: Theme.of(context).extension<SendPageTheme>()!.textFieldHintColor),
|
|
onPushPasteButton: (context) async {
|
|
output.resetParsedAddress();
|
|
await output.fetchParsedAddress(context);
|
|
},
|
|
onPushAddressBookButton: (context) async {
|
|
output.resetParsedAddress();
|
|
},
|
|
onSelectedContact: (contact) {
|
|
output.loadContact(contact);
|
|
},
|
|
validator: validator,
|
|
selectedCurrency: sendViewModel.selectedCryptoCurrency,
|
|
);
|
|
}),
|
|
if (output.isParsedAddress)
|
|
Padding(
|
|
padding: const EdgeInsets.only(top: 20),
|
|
child: BaseTextFormField(
|
|
controller: extractedAddressController,
|
|
readOnly: true,
|
|
borderColor:
|
|
Theme.of(context).extension<SendPageTheme>()!.textFieldBorderColor,
|
|
textStyle: TextStyle(
|
|
fontSize: 14, fontWeight: FontWeight.w500, color: Colors.white),
|
|
validator: sendViewModel.addressValidator)),
|
|
CurrencyAmountTextField(
|
|
currencyPickerButtonKey: ValueKey('send_page_currency_picker_button_key'),
|
|
amountTextfieldKey: ValueKey('send_page_amount_textfield_key'),
|
|
sendAllButtonKey: ValueKey('send_page_send_all_button_key'),
|
|
currencyAmountTextFieldWidgetKey:
|
|
ValueKey('send_page_crypto_currency_amount_textfield_widget_key'),
|
|
selectedCurrency: sendViewModel.selectedCryptoCurrency.title,
|
|
amountFocusNode: widget.cryptoAmountFocus,
|
|
amountController: cryptoAmountController,
|
|
isAmountEditable: true,
|
|
onTapPicker: () => _presentPicker(context),
|
|
isPickerEnable: sendViewModel.hasMultipleTokens,
|
|
tag: sendViewModel.selectedCryptoCurrency.tag,
|
|
allAmountButton:
|
|
!sendViewModel.isBatchSending && sendViewModel.shouldDisplaySendALL,
|
|
currencyValueValidator: output.sendAll
|
|
? sendViewModel.allAmountValidator
|
|
: sendViewModel.amountValidator,
|
|
allAmountCallback: () async => output.setSendAll(sendViewModel.balance)),
|
|
Divider(
|
|
height: 1,
|
|
color: Theme.of(context).extension<SendPageTheme>()!.textFieldHintColor),
|
|
Observer(
|
|
builder: (_) => Padding(
|
|
padding: EdgeInsets.only(top: 10),
|
|
child: Row(
|
|
mainAxisSize: MainAxisSize.max,
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: <Widget>[
|
|
Expanded(
|
|
child: Text(
|
|
S.of(context).available_balance + ':',
|
|
style: TextStyle(
|
|
fontSize: 12,
|
|
fontWeight: FontWeight.w600,
|
|
color:
|
|
Theme.of(context).extension<SendPageTheme>()!.textFieldHintColor),
|
|
),
|
|
),
|
|
Text(
|
|
sendViewModel.balance,
|
|
style: TextStyle(
|
|
fontSize: 12,
|
|
fontWeight: FontWeight.w600,
|
|
color:
|
|
Theme.of(context).extension<SendPageTheme>()!.textFieldHintColor),
|
|
)
|
|
],
|
|
),
|
|
),
|
|
),
|
|
if (!sendViewModel.isFiatDisabled)
|
|
CurrencyAmountTextField(
|
|
amountTextfieldKey: ValueKey('send_page_fiat_amount_textfield_key'),
|
|
currencyAmountTextFieldWidgetKey:
|
|
ValueKey('send_page_fiat_currency_amount_textfield_widget_key'),
|
|
selectedCurrency: sendViewModel.fiat.title,
|
|
amountFocusNode: widget.fiatAmountFocus,
|
|
amountController: fiatAmountController,
|
|
hintText: '0.00',
|
|
isAmountEditable: true,
|
|
allAmountButton: false),
|
|
Divider(
|
|
height: 1,
|
|
color: Theme.of(context).extension<SendPageTheme>()!.textFieldHintColor),
|
|
Padding(
|
|
padding: EdgeInsets.only(top: 20),
|
|
child: BaseTextFormField(
|
|
key: ValueKey('send_page_note_textfield_key'),
|
|
controller: noteController,
|
|
keyboardType: TextInputType.multiline,
|
|
maxLines: null,
|
|
borderColor: Theme.of(context).extension<SendPageTheme>()!.textFieldBorderColor,
|
|
textStyle:
|
|
TextStyle(fontSize: 14, fontWeight: FontWeight.w500, color: Colors.white),
|
|
hintText: S.of(context).note_optional,
|
|
placeholderTextStyle: TextStyle(
|
|
fontSize: 14,
|
|
fontWeight: FontWeight.w500,
|
|
color: Theme.of(context).extension<SendPageTheme>()!.textFieldHintColor),
|
|
),
|
|
),
|
|
if (sendViewModel.hasFees)
|
|
Observer(
|
|
builder: (_) => GestureDetector(
|
|
key: ValueKey('send_page_select_fee_priority_button_key'),
|
|
onTap: sendViewModel.hasFeesPriority
|
|
? () => pickTransactionPriority(context)
|
|
: () {},
|
|
child: Container(
|
|
padding: EdgeInsets.only(top: 24),
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: <Widget>[
|
|
Text(
|
|
S.of(context).send_estimated_fee,
|
|
style: TextStyle(
|
|
fontSize: 12, fontWeight: FontWeight.w500, color: Colors.white),
|
|
),
|
|
Container(
|
|
child: Row(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: <Widget>[
|
|
Column(
|
|
mainAxisAlignment: MainAxisAlignment.start,
|
|
crossAxisAlignment: CrossAxisAlignment.end,
|
|
children: [
|
|
Text(
|
|
output.estimatedFee.toString() +
|
|
' ' +
|
|
sendViewModel.currency.toString(),
|
|
style: TextStyle(
|
|
fontSize: 12,
|
|
fontWeight: FontWeight.w600,
|
|
color: Colors.white,
|
|
),
|
|
),
|
|
Padding(
|
|
padding: EdgeInsets.only(top: 5),
|
|
child: sendViewModel.isFiatDisabled
|
|
? const SizedBox(height: 14)
|
|
: Text(
|
|
output.estimatedFeeFiatAmount +
|
|
' ' +
|
|
sendViewModel.fiat.title,
|
|
style: TextStyle(
|
|
fontSize: 12,
|
|
fontWeight: FontWeight.w600,
|
|
color: Theme.of(context)
|
|
.extension<SendPageTheme>()!
|
|
.textFieldHintColor,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
Padding(
|
|
padding: EdgeInsets.only(top: 2, left: 5),
|
|
child: Icon(
|
|
Icons.arrow_forward_ios,
|
|
size: 12,
|
|
color: Colors.white,
|
|
),
|
|
)
|
|
],
|
|
),
|
|
)
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
if (sendViewModel.hasCoinControl)
|
|
Padding(
|
|
padding: EdgeInsets.only(top: 6),
|
|
child: GestureDetector(
|
|
key: ValueKey('send_page_unspent_coin_button_key'),
|
|
onTap: () => Navigator.of(context).pushNamed(
|
|
Routes.unspentCoinsList,
|
|
arguments: widget.sendViewModel.coinTypeToSpendFrom,
|
|
),
|
|
child: Container(
|
|
color: Colors.transparent,
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
Text(
|
|
S.of(context).coin_control,
|
|
style: TextStyle(
|
|
fontSize: 12, fontWeight: FontWeight.w600, color: Colors.white),
|
|
),
|
|
Icon(
|
|
Icons.arrow_forward_ios,
|
|
size: 12,
|
|
color: Colors.white,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
if (sendViewModel.currency == CryptoCurrency.ltc)
|
|
Observer(
|
|
builder: (_) => Padding(
|
|
padding: EdgeInsets.only(top: 14),
|
|
child: GestureDetector(
|
|
key: ValueKey('send_page_unspent_coin_button_key'),
|
|
onTap: () {
|
|
bool value =
|
|
widget.sendViewModel.coinTypeToSpendFrom == UnspentCoinType.any;
|
|
sendViewModel.setAllowMwebCoins(!value);
|
|
},
|
|
child: Container(
|
|
color: Colors.transparent,
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
StandardCheckbox(
|
|
caption: S.of(context).litecoin_mweb_allow_coins,
|
|
captionColor: Colors.white,
|
|
borderColor: currentTheme.type == ThemeType.bright
|
|
? Colors.white
|
|
: Theme.of(context).extension<CakeTextTheme>()!.secondaryTextColor,
|
|
iconColor: currentTheme.type == ThemeType.bright
|
|
? Colors.white
|
|
: Theme.of(context).primaryColor,
|
|
value:
|
|
widget.sendViewModel.coinTypeToSpendFrom == UnspentCoinType.any,
|
|
onChanged: (bool? value) {
|
|
sendViewModel.setAllowMwebCoins(value ?? false);
|
|
},
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
void _setEffects(BuildContext context) {
|
|
if (_effectsInstalled) {
|
|
return;
|
|
}
|
|
|
|
if (output.address.isNotEmpty) {
|
|
addressController.text = output.address;
|
|
}
|
|
if (output.cryptoAmount.isNotEmpty) {
|
|
cryptoAmountController.text = output.cryptoAmount;
|
|
}
|
|
fiatAmountController.text = output.fiatAmount;
|
|
noteController.text = output.note;
|
|
extractedAddressController.text = output.extractedAddress;
|
|
|
|
cryptoAmountController.addListener(() {
|
|
final amount = cryptoAmountController.text;
|
|
|
|
if (output.sendAll && amount != S.current.all) {
|
|
output.sendAll = false;
|
|
}
|
|
|
|
if (amount != output.cryptoAmount) {
|
|
output.setCryptoAmount(amount);
|
|
}
|
|
});
|
|
|
|
fiatAmountController.addListener(() {
|
|
final amount = fiatAmountController.text;
|
|
|
|
if (amount != output.fiatAmount) {
|
|
output.sendAll = false;
|
|
output.setFiatAmount(amount);
|
|
}
|
|
});
|
|
|
|
noteController.addListener(() {
|
|
final note = noteController.text;
|
|
|
|
if (note != output.note) {
|
|
output.note = note;
|
|
}
|
|
});
|
|
|
|
reaction((_) => output.sendAll, (bool all) {
|
|
if (all) {
|
|
cryptoAmountController.text = S.current.all;
|
|
fiatAmountController.text = '';
|
|
}
|
|
});
|
|
|
|
reaction((_) => sendViewModel.selectedCryptoCurrency, (Currency currency) {
|
|
if (output.sendAll) {
|
|
output.setSendAll(sendViewModel.balance);
|
|
}
|
|
|
|
output.setCryptoAmount(cryptoAmountController.text);
|
|
});
|
|
|
|
reaction((_) => output.fiatAmount, (String amount) {
|
|
if (amount != fiatAmountController.text) {
|
|
fiatAmountController.text = amount;
|
|
}
|
|
});
|
|
|
|
reaction((_) => output.cryptoAmount, (String amount) {
|
|
if (output.sendAll && amount != S.current.all) {
|
|
output.sendAll = false;
|
|
}
|
|
|
|
if (amount != cryptoAmountController.text) {
|
|
cryptoAmountController.text = amount;
|
|
}
|
|
});
|
|
|
|
reaction((_) => output.address, (String address) {
|
|
if (address != addressController.text) {
|
|
addressController.text = address;
|
|
}
|
|
});
|
|
|
|
addressController.addListener(() {
|
|
final address = addressController.text;
|
|
|
|
if (output.address != address) {
|
|
output.resetParsedAddress();
|
|
output.address = address;
|
|
}
|
|
});
|
|
|
|
reaction((_) => output.note, (String note) {
|
|
if (note != noteController.text) {
|
|
noteController.text = note;
|
|
}
|
|
});
|
|
|
|
addressFocusNode.addListener(() async {
|
|
if (!addressFocusNode.hasFocus && addressController.text.isNotEmpty) {
|
|
await output.fetchParsedAddress(context);
|
|
}
|
|
});
|
|
|
|
reaction((_) => output.extractedAddress, (String extractedAddress) {
|
|
extractedAddressController.text = extractedAddress;
|
|
});
|
|
|
|
if (initialPaymentRequest != null &&
|
|
sendViewModel.walletCurrencyName == initialPaymentRequest!.scheme.toLowerCase()) {
|
|
addressController.text = initialPaymentRequest!.address;
|
|
cryptoAmountController.text = initialPaymentRequest!.amount;
|
|
noteController.text = initialPaymentRequest!.note;
|
|
}
|
|
|
|
_effectsInstalled = true;
|
|
}
|
|
|
|
Future<void> pickTransactionPriority(BuildContext context) async {
|
|
final items = priorityForWalletType(sendViewModel.walletType);
|
|
final selectedItem = items.indexOf(sendViewModel.transactionPriority);
|
|
final customItemIndex = sendViewModel.getCustomPriorityIndex(items);
|
|
final isBitcoinWallet = sendViewModel.walletType == WalletType.bitcoin;
|
|
final maxCustomFeeRate = sendViewModel.maxCustomFeeRate?.toDouble();
|
|
double? customFeeRate = isBitcoinWallet ? sendViewModel.customBitcoinFeeRate.toDouble() : null;
|
|
|
|
await showPopUp<void>(
|
|
context: context,
|
|
builder: (BuildContext context) {
|
|
int selectedIdx = selectedItem;
|
|
return StatefulBuilder(
|
|
builder: (BuildContext context, StateSetter setState) {
|
|
return Picker(
|
|
items: items,
|
|
displayItem: (TransactionPriority priority) =>
|
|
sendViewModel.displayFeeRate(priority, customFeeRate?.round()),
|
|
selectedAtIndex: selectedIdx,
|
|
customItemIndex: customItemIndex,
|
|
maxValue: maxCustomFeeRate,
|
|
title: S.of(context).please_select,
|
|
headerEnabled: !isBitcoinWallet,
|
|
closeOnItemSelected: !isBitcoinWallet,
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
sliderValue: customFeeRate,
|
|
onSliderChanged: (double newValue) => setState(() => customFeeRate = newValue),
|
|
onItemSelected: (TransactionPriority priority) {
|
|
sendViewModel.setTransactionPriority(priority);
|
|
setState(() => selectedIdx = items.indexOf(priority));
|
|
},
|
|
);
|
|
},
|
|
);
|
|
},
|
|
);
|
|
if (isBitcoinWallet) sendViewModel.customBitcoinFeeRate = customFeeRate!.round();
|
|
}
|
|
|
|
void _presentPicker(BuildContext context) {
|
|
showPopUp<void>(
|
|
context: context,
|
|
builder: (_) => CurrencyPicker(
|
|
key: ValueKey('send_page_currency_picker_dialog_button_key'),
|
|
selectedAtIndex: sendViewModel.currencies.indexOf(sendViewModel.selectedCryptoCurrency),
|
|
items: sendViewModel.currencies,
|
|
hintText: S.of(context).search_currency,
|
|
onItemSelected: (Currency cur) =>
|
|
sendViewModel.selectedCryptoCurrency = (cur as CryptoCurrency),
|
|
),
|
|
);
|
|
}
|
|
|
|
@override
|
|
bool get wantKeepAlive => true;
|
|
}
|