import 'package:cake_wallet/bitcoin/bitcoin.dart'; import 'package:cake_wallet/src/widgets/standard_switch.dart'; import 'package:cake_wallet/utils/date_picker.dart'; import 'package:cake_wallet/wownero/wownero.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/monero/monero.dart'; import 'package:cake_wallet/src/widgets/base_text_form_field.dart'; import 'package:cake_wallet/decred/decred.dart'; class BlockchainHeightWidget extends StatefulWidget { BlockchainHeightWidget({ GlobalKey? key, this.onHeightChange, this.focusNode, this.onHeightOrDateEntered, this.hasDatePicker = true, this.isSilentPaymentsScan = false, this.isMwebScan = false, this.toggleSingleScan, this.doSingleScan = false, this.bitcoinMempoolAPIEnabled, required this.walletType, this.blockHeightTextFieldKey, }) : super(key: key); final Function(int)? onHeightChange; final Function(bool)? onHeightOrDateEntered; final FocusNode? focusNode; final bool hasDatePicker; final bool isSilentPaymentsScan; final bool isMwebScan; final bool doSingleScan; final Future? bitcoinMempoolAPIEnabled; final Function()? toggleSingleScan; final WalletType walletType; final Key? blockHeightTextFieldKey; @override State createState() => BlockchainHeightState(); } class BlockchainHeightState extends State { final dateController = TextEditingController(); final restoreHeightController = TextEditingController(); int get height => _height; int _height = 0; @override void initState() { restoreHeightController.addListener(() { if (restoreHeightController.text.isNotEmpty) { widget.onHeightOrDateEntered?.call(true); } else { widget.onHeightOrDateEntered?.call(false); dateController.text = ''; } try { _changeHeight( restoreHeightController.text.isNotEmpty ? int.parse(restoreHeightController.text) : 0); } catch (_) { _changeHeight(0); } }); super.initState(); } @override Widget build(BuildContext context) { return GestureDetector( behavior: HitTestBehavior.opaque, onTap: () => FocusScope.of(context).unfocus(), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Flexible( child: Container( padding: EdgeInsets.only(top: 20.0, bottom: 10.0), child: BaseTextFormField( key: widget.blockHeightTextFieldKey, focusNode: widget.focusNode, controller: restoreHeightController, keyboardType: TextInputType.numberWithOptions( signed: false, decimal: false, ), hintText: widget.isSilentPaymentsScan ? S.of(context).silent_payments_scan_from_height : S.of(context).widgets_restore_from_blockheight, ), ), ) ], ), if (widget.hasDatePicker) ...[ Padding( padding: EdgeInsets.only(top: 15, bottom: 15), child: Text( S.of(context).widgets_or, style: Theme.of(context).textTheme.bodyMedium?.copyWith( fontSize: 16, fontWeight: FontWeight.w500, color: Theme.of(context).colorScheme.onSurfaceVariant, ), ), ), Row( children: [ Flexible( child: Container( child: InkWell( onTap: () => _selectDate(context), child: IgnorePointer( child: BaseTextFormField( controller: dateController, hintText: widget.isSilentPaymentsScan ? S.of(context).silent_payments_scan_from_date : S.of(context).widgets_restore_from_date, ), ), ), )) ], ), if (widget.isSilentPaymentsScan) Padding( padding: EdgeInsets.only(top: 24), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( S.of(context).scan_one_block, style: Theme.of(context).textTheme.bodyMedium?.copyWith( color: Theme.of(context).colorScheme.onSurfaceVariant, ), ), Padding( padding: const EdgeInsets.only(right: 8), child: StandardSwitch( value: widget.doSingleScan, onTaped: () => widget.toggleSingleScan?.call(), ), ) ], ), ), Padding( padding: EdgeInsets.only(left: 40, right: 40, top: 24), child: Text( widget.isSilentPaymentsScan ? S.of(context).silent_payments_scan_from_date_or_blockheight : S.of(context).restore_from_date_or_blockheight, textAlign: TextAlign.center, style: Theme.of(context).textTheme.bodySmall?.copyWith( color: Theme.of(context).colorScheme.onSurfaceVariant, ), ), ) ] ], ), ); } Future _selectDate(BuildContext context) async { final now = DateTime.now(); final date = await getDate( context: context, initialDate: now.subtract(Duration(days: 1)), firstDate: DateTime(2014, DateTime.may), lastDate: now); if (date != null) { int height; if (widget.isMwebScan) { height = bitcoin!.getLitecoinHeightByDate(date: date); } else if (widget.isSilentPaymentsScan) { height = await bitcoin!.getHeightByDate( date: date, bitcoinMempoolAPIEnabled: await widget.bitcoinMempoolAPIEnabled, ); } else { if (widget.walletType == WalletType.decred) { height = decred!.heightByDate(date); } else if (widget.walletType == WalletType.monero) { height = monero!.getHeightByDate(date: date); } else { assert(widget.walletType == WalletType.wownero, "unknown currency in BlockchainHeightWidget"); height = wownero!.getHeightByDate(date: date); } } if (mounted) { setState(() { dateController.text = DateFormat('yyyy-MM-dd').format(date); restoreHeightController.text = '$height'; _changeHeight(height); }); } } } void _changeHeight(int height) { _height = height; widget.onHeightChange?.call(height); } }