dev
dart 221 lines 7.42 KB
Raw
1 import 'package:cake_wallet/bitcoin/bitcoin.dart';
2 import 'package:cake_wallet/src/widgets/standard_switch.dart';
3 import 'package:cake_wallet/utils/date_picker.dart';
4 import 'package:cake_wallet/wownero/wownero.dart';
5 import 'package:cake_wallet/zcash/zcash.dart';
6 import 'package:cw_core/wallet_type.dart';
7 import 'package:flutter/material.dart';
8 import 'package:intl/intl.dart';
9 import 'package:cake_wallet/generated/i18n.dart';
10 import 'package:cake_wallet/monero/monero.dart';
11 import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
12 import 'package:cake_wallet/decred/decred.dart';
13
14 class BlockchainHeightWidget extends StatefulWidget {
15 BlockchainHeightWidget({
16 GlobalKey? key,
17 this.onHeightChange,
18 this.focusNode,
19 this.onHeightOrDateEntered,
20 this.hasDatePicker = true,
21 this.isSilentPaymentsScan = false,
22 this.isMwebScan = false,
23 this.toggleSingleScan,
24 this.doSingleScan = false,
25 this.bitcoinMempoolAPIEnabled,
26 required this.walletType,
27 this.blockHeightTextFieldKey,
28 this.heightController,
29 }) : super(key: key);
30
31 final Function(int)? onHeightChange;
32 final Function(bool)? onHeightOrDateEntered;
33 final FocusNode? focusNode;
34 final bool hasDatePicker;
35 final bool isSilentPaymentsScan;
36 final bool isMwebScan;
37 final TextEditingController? heightController;
38 final bool doSingleScan;
39 final Future<bool>? bitcoinMempoolAPIEnabled;
40 final Function()? toggleSingleScan;
41 final WalletType walletType;
42 final Key? blockHeightTextFieldKey;
43 @override
44 State<StatefulWidget> createState() => BlockchainHeightState();
45 }
46
47 class BlockchainHeightState extends State<BlockchainHeightWidget> {
48 final dateController = TextEditingController();
49 late final TextEditingController restoreHeightController;
50
51 int get height => _height;
52 int _height = 0;
53
54 @override
55 void initState() {
56 restoreHeightController = widget.heightController ?? TextEditingController();
57
58 restoreHeightController.addListener(() {
59 if (restoreHeightController.text.isNotEmpty) {
60 widget.onHeightOrDateEntered?.call(true);
61 } else {
62 widget.onHeightOrDateEntered?.call(false);
63 dateController.text = '';
64 }
65 try {
66 final int _height;
67 if (restoreHeightController.text.isNotEmpty) {
68 final digits = restoreHeightController.text.replaceAll(RegExp(r'[^0-9]'), '');
69 _height = int.tryParse(digits) ?? 0;
70 } else {
71 _height = 0;
72 }
73 _changeHeight(_height);
74 } catch (_) {
75 _changeHeight(0);
76 }
77 });
78
79 super.initState();
80 }
81
82 @override
83 Widget build(BuildContext context) {
84 return Column(
85 crossAxisAlignment: CrossAxisAlignment.start,
86 children: <Widget>[
87 Row(
88 children: <Widget>[
89 Flexible(
90 child: Container(
91 padding: EdgeInsets.only(top: 20.0, bottom: 10.0),
92 child: BaseTextFormField(
93 key: widget.blockHeightTextFieldKey,
94 focusNode: widget.focusNode,
95 controller: restoreHeightController,
96 keyboardType: TextInputType.numberWithOptions(
97 signed: false,
98 decimal: false,
99 ),
100 hintText: widget.isSilentPaymentsScan
101 ? S.of(context).silent_payments_scan_from_height
102 : S.of(context).widgets_restore_from_blockheight,
103 ),
104 ),
105 )
106 ],
107 ),
108 if (widget.hasDatePicker) ...[
109 Padding(
110 padding: EdgeInsets.only(top: 15, bottom: 15),
111 child: Text(
112 S.of(context).widgets_or,
113 style: Theme.of(context).textTheme.bodyMedium?.copyWith(
114 fontSize: 16,
115 fontWeight: FontWeight.w500,
116 color: Theme.of(context).colorScheme.onSurfaceVariant,
117 ),
118 ),
119 ),
120 Row(
121 children: <Widget>[
122 Flexible(
123 child: Container(
124 child: InkWell(
125 onTap: () => _selectDate(context),
126 child: IgnorePointer(
127 child: BaseTextFormField(
128 controller: dateController,
129 hintText: widget.isSilentPaymentsScan
130 ? S.of(context).silent_payments_scan_from_date
131 : S.of(context).widgets_restore_from_date,
132 ),
133 ),
134 ),
135 ))
136 ],
137 ),
138 if (widget.isSilentPaymentsScan)
139 Padding(
140 padding: EdgeInsets.only(top: 24),
141 child: Row(
142 mainAxisAlignment: MainAxisAlignment.spaceBetween,
143 children: [
144 Text(
145 S.of(context).scan_one_block,
146 style: Theme.of(context).textTheme.bodyMedium?.copyWith(
147 color: Theme.of(context).colorScheme.onSurfaceVariant,
148 ),
149 ),
150 Padding(
151 padding: const EdgeInsets.only(right: 8),
152 child: StandardSwitch(
153 value: widget.doSingleScan,
154 onTapped: () => widget.toggleSingleScan?.call(),
155 ),
156 )
157 ],
158 ),
159 ),
160 Padding(
161 padding: EdgeInsets.only(left: 40, right: 40, top: 24),
162 child: Text(
163 widget.isSilentPaymentsScan
164 ? S.of(context).silent_payments_scan_from_date_or_blockheight
165 : S.of(context).restore_from_date_or_blockheight,
166 textAlign: TextAlign.center,
167 style: Theme.of(context).textTheme.bodySmall?.copyWith(
168 color: Theme.of(context).colorScheme.onSurfaceVariant,
169 ),
170 ),
171 )
172 ]
173 ],
174 );
175 }
176
177 Future<void> _selectDate(BuildContext context) async {
178 final now = DateTime.now();
179 final date = await getDate(
180 context: context,
181 initialDate: now.subtract(Duration(days: 1)),
182 firstDate: DateTime(2014, DateTime.may),
183 lastDate: now);
184
185 if (date != null) {
186 int height;
187 if (widget.isMwebScan) {
188 height = bitcoin!.getLitecoinHeightByDate(date: date);
189 } else if (widget.isSilentPaymentsScan) {
190 height = await bitcoin!.getHeightByDate(
191 date: date,
192 bitcoinMempoolAPIEnabled: await widget.bitcoinMempoolAPIEnabled,
193 );
194 } else {
195 if (widget.walletType == WalletType.decred) {
196 height = decred!.heightByDate(date);
197 } else if (widget.walletType == WalletType.monero) {
198 height = monero!.getHeightByDate(date: date);
199 } else if (widget.walletType == WalletType.wownero) {
200 height = wownero!.getHeightByDate(date: date);
201 } else if (widget.walletType == WalletType.zcash) {
202 height = await zcash!.getHeightByDate(date);
203 } else {
204 throw Exception("unknown currency in BlockchainHeightWidget");
205 }
206 }
207 if (mounted) {
208 setState(() {
209 dateController.text = DateFormat('yyyy-MM-dd').format(date);
210 restoreHeightController.text = '$height';
211 _changeHeight(height);
212 });
213 }
214 }
215 }
216
217 void _changeHeight(int height) {
218 _height = height;
219 widget.onHeightChange?.call(height);
220 }
221 }