CAKE-49 | refactored send page
OleksandrSobol committed
Sep 21, 2020 at 22:01 UTC
45c8b74bf14578ffaa2b3499fe43512014317893
3 files changed
+636
-611
lib/di.dart
+2
-2
@@ -257,8 +257,8 @@ Future setup(
257
getIt.registerFactory(
258
() => SendPage(sendViewModel: getIt.get<SendViewModel>()));
259
260
- // getIt.registerFactory(
261
- // () => SendTemplatePage(sendViewModel: getIt.get<SendViewModel>()));
260
+ getIt.registerFactory(
261
+ () => SendTemplatePage(sendViewModel: getIt.get<SendViewModel>()));
262
263
getIt.registerFactory(() => WalletListViewModel(
264
walletInfoSource, getIt.get<AppStore>(), getIt.get<KeyService>()));
lib/src/screens/send/send_page.dart
+622
-590
@@ -1,4 +1,7 @@
1
import 'dart:ui';
2
+import 'package:cake_wallet/src/domain/common/transaction_priority.dart';
3
+import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
4
+import 'package:cake_wallet/src/widgets/picker.dart';
5
import 'package:flutter/cupertino.dart';
6
import 'package:flutter/material.dart';
7
import 'package:flutter/services.dart';
@@ -19,22 +22,22 @@ import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
22
import 'package:cake_wallet/src/screens/send/widgets/confirm_sending_alert.dart';
23
import 'package:cake_wallet/view_model/send/send_view_model_state.dart';
24
import 'package:cake_wallet/src/widgets/trail_button.dart';
22
-
23
-import 'package:flutter/cupertino.dart';
24
-import 'package:flutter/material.dart';
25
-import 'package:cake_wallet/src/screens/base_page.dart';
26
-import 'package:cake_wallet/src/screens/send/widgets/base_send_widget.dart';
27
-
28
-// FIXME: Refactor this screen.
25
+import 'package:dotted_border/dotted_border.dart';
26
27
class SendPage extends BasePage {
28
SendPage({@required this.sendViewModel});
29
30
final SendViewModel sendViewModel;
31
+ final _addressController = TextEditingController();
32
+ final _cryptoAmountController = TextEditingController();
33
+ final _fiatAmountController = TextEditingController();
34
+ final _focusNode = FocusNode();
35
+ final _formKey = GlobalKey<FormState>();
36
+
37
+ bool _effectsInstalled = false;
38
35
- // ???
39
@override
37
- String get title => 'SEND';
40
+ String get title => S.current.send;
41
42
@override
43
Color get titleColor => Colors.white;
@@ -48,64 +51,9 @@ class SendPage extends BasePage {
51
@override
52
Widget trailing(context) => TrailButton(
53
caption: S.of(context).clear, onPressed: () => sendViewModel.reset());
51
- Color get backgroundDarkColor => Colors.transparent;
52
-
53
- // @override
54
- // State<StatefulWidget> createState() => SendFormState();
55
-
56
- final _addressController = TextEditingController();
57
- final _cryptoAmountController = TextEditingController();
58
- final _fiatAmountController = TextEditingController();
59
-
60
- final _focusNode = FocusNode();
61
-
62
- bool _effectsInstalled = false;
63
-
64
- final _formKey = GlobalKey<FormState>();
65
-
66
- // @override
67
- // void initState() {
68
- // _focusNode.addListener(() {
69
- // if (!_focusNode.hasFocus && _addressController.text.isNotEmpty) {
70
- // getOpenaliasRecord(context);
71
- // }
72
- // });
73
-
74
- // super.initState();
75
- // }
76
-
77
- Future<void> getOpenaliasRecord(BuildContext context) async {
78
-// final sendStore = Provider.of<SendStore>(context);
79
-// final isOpenalias =
80
-// await sendStore.isOpenaliasRecord(_addressController.text);
81
-//
82
-// if (isOpenalias) {
83
-// _addressController.text = sendStore.recordAddress;
84
-//
85
-// await showDialog<void>(
86
-// context: context,
87
-// builder: (BuildContext context) {
88
-// return AlertWithOneAction(
89
-// alertTitle: S.of(context).openalias_alert_title,
90
-// alertContent:
91
-// S.of(context).openalias_alert_content(sendStore.recordName),
92
-// buttonText: S.of(context).ok,
93
-// buttonAction: () => Navigator.of(context).pop());
94
-// });
95
-// }
96
- }
97
-
98
- // @override
99
- // Widget body(BuildContext context) {
100
- // return super.build(context);
101
- // }
54
55
@override
104
- Widget body(BuildContext context) => BaseSendWidget(
105
- sendViewModel: sendViewModel,
106
- leading: leading(context),
107
- middle: middle(context),
108
- );
56
+ Color get backgroundDarkColor => Colors.transparent;
57
58
@override
59
Widget build(BuildContext context) {
@@ -115,529 +63,613 @@ class SendPage extends BasePage {
63
color: Theme.of(context).backgroundColor, child: body(context)));
64
}
65
118
-// @override
119
-// Widget build(BuildContext context) {
120
-// _setEffects(context);
121
-
122
-// return Container(
123
-// color: Theme.of(context).backgroundColor,
124
-// child: ScrollableWithBottomSection(
125
-// contentPadding: EdgeInsets.only(bottom: 24),
126
-// content: Column(
127
-// children: <Widget>[
128
-// TopPanel(
129
-// color: Theme.of(context).accentTextTheme.title.backgroundColor,
130
-// widget: Form(
131
-// key: _formKey,
132
-// child: Column(children: <Widget>[
133
-// AddressTextField(
134
-// controller: _addressController,
135
-// placeholder: 'Address',
136
-// //S.of(context).send_monero_address, FIXME: placeholder for btc and xmr address text field.
137
-// focusNode: _focusNode,
138
-// onURIScanned: (uri) {
139
-// var address = '';
140
-// var amount = '';
141
-
142
-// if (uri != null) {
143
-// address = uri.path;
144
-// amount = uri.queryParameters['tx_amount'];
145
-// } else {
146
-// address = uri.toString();
147
-// }
148
-
149
-// _addressController.text = address;
150
-// _cryptoAmountController.text = amount;
151
-// },
152
-// options: [
153
-// AddressTextFieldOption.qrCode,
154
-// AddressTextFieldOption.addressBook
155
-// ],
156
-// buttonColor: Theme.of(context).accentTextTheme.title.color,
157
-// validator: widget.sendViewModel.addressValidator,
158
-// ),
159
-// Padding(
160
-// padding: const EdgeInsets.only(top: 20),
161
-// child: TextFormField(
162
-// onChanged: (value) =>
163
-// widget.sendViewModel.setCryptoAmount(value),
164
-// style: TextStyle(
165
-// fontSize: 16.0,
166
-// color:
167
-// Theme.of(context).primaryTextTheme.title.color),
168
-// controller: _cryptoAmountController,
169
-// keyboardType: TextInputType.numberWithOptions(
170
-// signed: false, decimal: true),
171
-// // inputFormatters: [
172
-// // BlacklistingTextInputFormatter(
173
-// // RegExp('[\\-|\\ |\\,]'))
174
-// // ],
175
-// decoration: InputDecoration(
176
-// prefixIcon: Padding(
177
-// padding: EdgeInsets.only(top: 12),
178
-// child: Text(
179
-// '${widget.sendViewModel.currency.toString()}:',
180
-// style: TextStyle(
181
-// fontSize: 16,
182
-// fontWeight: FontWeight.w500,
183
-// color: Theme.of(context)
184
-// .primaryTextTheme
185
-// .title
186
-// .color,
187
-// )),
188
-// ),
189
-// suffixIcon: Padding(
190
-// padding: EdgeInsets.only(bottom: 5),
191
-// child: Container(
192
-// height: 32,
193
-// width: 32,
194
-// margin: EdgeInsets.only(
195
-// left: 12, bottom: 7, top: 4),
196
-// decoration: BoxDecoration(
197
-// color: Theme.of(context)
198
-// .accentTextTheme
199
-// .title
200
-// .color,
201
-// borderRadius:
202
-// BorderRadius.all(Radius.circular(6))),
203
-// child: InkWell(
204
-// onTap: () => widget.sendViewModel.setAll(),
205
-// child: Center(
206
-// child: Text(S.of(context).all,
207
-// textAlign: TextAlign.center,
208
-// style: TextStyle(
209
-// fontSize: 9,
210
-// fontWeight: FontWeight.bold,
211
-// color: Theme.of(context)
212
-// .primaryTextTheme
213
-// .caption
214
-// .color)),
215
-// ),
216
-// ),
217
-// )),
218
-// hintStyle: TextStyle(
219
-// fontSize: 16.0,
220
-// color: Theme.of(context)
221
-// .primaryTextTheme
222
-// .title
223
-// .color),
224
-// hintText: '0.0000',
225
-// focusedBorder: UnderlineInputBorder(
226
-// borderSide: BorderSide(
227
-// color: Theme.of(context).dividerColor,
228
-// width: 1.0)),
229
-// enabledBorder: UnderlineInputBorder(
230
-// borderSide: BorderSide(
231
-// color: Theme.of(context).dividerColor,
232
-// width: 1.0))),
233
-// validator: (String value) {
234
-// if (widget.sendViewModel.all) {
235
-// return null;
236
-// }
237
-
238
-// return widget.sendViewModel.amountValidator
239
-// .call(value);
240
-// }),
241
-// ),
242
-// Padding(
243
-// padding: const EdgeInsets.only(top: 20),
244
-// child: TextFormField(
245
-// onChanged: (value) =>
246
-// widget.sendViewModel.setFiatAmount(value),
247
-// style: TextStyle(
248
-// fontSize: 16.0,
249
-// color:
250
-// Theme.of(context).primaryTextTheme.title.color),
251
-// controller: _fiatAmountController,
252
-// keyboardType: TextInputType.numberWithOptions(
253
-// signed: false, decimal: true),
254
-// // inputFormatters: [
255
-// // BlacklistingTextInputFormatter(
256
-// // RegExp('[\\-|\\ |\\,]'))
257
-// // ],
258
-// decoration: InputDecoration(
259
-// prefixIcon: Padding(
260
-// padding: EdgeInsets.only(top: 12),
261
-// child: Text(
262
-// '${widget.sendViewModel.fiat.toString()}:',
263
-// style: TextStyle(
264
-// fontSize: 16,
265
-// fontWeight: FontWeight.w500,
266
-// color: Theme.of(context)
267
-// .primaryTextTheme
268
-// .title
269
-// .color,
270
-// )),
271
-// ),
272
-// hintStyle: TextStyle(
273
-// fontSize: 16.0,
274
-// color: Theme.of(context)
275
-// .primaryTextTheme
276
-// .caption
277
-// .color),
278
-// hintText: '0.00',
279
-// focusedBorder: UnderlineInputBorder(
280
-// borderSide: BorderSide(
281
-// color: Theme.of(context).dividerColor,
282
-// width: 1.0)),
283
-// enabledBorder: UnderlineInputBorder(
284
-// borderSide: BorderSide(
285
-// color: Theme.of(context).dividerColor,
286
-// width: 1.0)))),
287
-// ),
288
-// Padding(
289
-// padding: const EdgeInsets.only(top: 20),
290
-// child: Row(
291
-// mainAxisAlignment: MainAxisAlignment.spaceBetween,
292
-// children: <Widget>[
293
-// Text(S.of(context).send_estimated_fee,
294
-// style: TextStyle(
295
-// fontSize: 12,
296
-// fontWeight: FontWeight.w600,
297
-// color: Theme.of(context)
298
-// .primaryTextTheme
299
-// .title
300
-// .color,
301
-// )),
302
-// Text(
303
-// '${widget.sendViewModel.estimatedFee} ${widget.sendViewModel.currency.toString()}',
304
-// style: TextStyle(
305
-// fontSize: 12,
306
-// fontWeight: FontWeight.w600,
307
-// color: Theme.of(context)
308
-// .primaryTextTheme
309
-// .title
310
-// .color,
311
-// ))
312
-// ],
313
-// ),
314
-// )
315
-// ]),
316
-// ),
317
-// ),
318
-// // Padding(
319
-// // padding: EdgeInsets.only(top: 32, left: 24, bottom: 24),
320
-// // child: Row(
321
-// // mainAxisAlignment: MainAxisAlignment.start,
322
-// // children: <Widget>[
323
-// // Text(
324
-// // S.of(context).send_templates,
325
-// // style: TextStyle(
326
-// // fontSize: 18,
327
-// // fontWeight: FontWeight.w600,
328
-// // color:
329
-// // Theme.of(context).primaryTextTheme.caption.color),
330
-// // )
331
-// // ],
332
-// // ),
333
-// // ),
334
-// // Container(
335
-// // height: 40,
336
-// // width: double.infinity,
337
-// // padding: EdgeInsets.only(left: 24),
338
-// // child: Observer(builder: (_) {
339
-// // final itemCount = sendTemplateStore.templates.length + 1;
340
-// //
341
-// // return ListView.builder(
342
-// // scrollDirection: Axis.horizontal,
343
-// // itemCount: itemCount,
344
-// // itemBuilder: (context, index) {
345
-// // if (index == 0) {
346
-// // return GestureDetector(
347
-// // onTap: () => Navigator.of(context)
348
-// // .pushNamed(Routes.sendTemplate),
349
-// // child: Container(
350
-// // padding: EdgeInsets.only(right: 10),
351
-// // child: DottedBorder(
352
-// // borderType: BorderType.RRect,
353
-// // dashPattern: [8, 4],
354
-// // color: Theme.of(context)
355
-// // .accentTextTheme
356
-// // .title
357
-// // .backgroundColor,
358
-// // strokeWidth: 2,
359
-// // radius: Radius.circular(20),
360
-// // child: Container(
361
-// // height: 40,
362
-// // width: 75,
363
-// // padding: EdgeInsets.only(left: 10, right: 10),
364
-// // alignment: Alignment.center,
365
-// // decoration: BoxDecoration(
366
-// // borderRadius:
367
-// // BorderRadius.all(Radius.circular(20)),
368
-// // color: Colors.transparent,
369
-// // ),
370
-// // child: Text(
371
-// // S.of(context).send_new,
372
-// // style: TextStyle(
373
-// // fontSize: 14,
374
-// // fontWeight: FontWeight.w600,
375
-// // color: Theme.of(context)
376
-// // .primaryTextTheme
377
-// // .caption
378
-// // .color),
379
-// // ),
380
-// // )),
381
-// // ),
382
-// // );
383
-// // }
384
-// //
385
-// // index -= 1;
386
-// //
387
-// // final template = sendTemplateStore.templates[index];
388
-// //
389
-// // return TemplateTile(
390
-// // to: template.name,
391
-// // amount: template.amount,
392
-// // from: template.cryptoCurrency,
393
-// // onTap: () {
394
-// // _addressController.text = template.address;
395
-// // _cryptoAmountController.text = template.amount;
396
-// // getOpenaliasRecord(context);
397
-// // });
398
-// // });
399
-// // }),
400
-// // )
401
-// ],
402
-// ),
403
-// bottomSectionPadding: EdgeInsets.only(left: 24, right: 24, bottom: 24),
404
-// bottomSection: Observer(builder: (_) {
405
-// return LoadingPrimaryButton(
406
-// onPressed: () async {
407
-// FocusScope.of(context).requestFocus(FocusNode());
408
-
409
-// if (!_formKey.currentState.validate()) {
410
-// return;
411
-// }
412
-
413
-// await showDialog<void>(
414
-// context: context,
415
-// builder: (dialogContext) {
416
-// return AlertWithTwoActions(
417
-// alertTitle: S.of(context).send_creating_transaction,
418
-// alertContent: S.of(context).confirm_sending,
419
-// leftButtonText: S.of(context).send,
420
-// rightButtonText: S.of(context).cancel,
421
-// actionLeftButton: () async {
422
-// await Navigator.of(dialogContext)
423
-// .popAndPushNamed(Routes.auth, arguments:
424
-// (bool isAuthenticatedSuccessfully,
425
-// AuthPageState auth) {
426
-// if (!isAuthenticatedSuccessfully) {
427
-// return;
428
-// }
429
-
430
-// Navigator.of(auth.context).pop();
431
-// widget.sendViewModel.createTransaction();
432
-// });
433
-// },
434
-// actionRightButton: () => Navigator.of(context).pop());
435
-// });
436
-// },
437
-// text: S.of(context).send,
438
-// color: Colors.blue,
439
-// textColor: Colors.white,
440
-// isLoading: widget.sendViewModel.state is TransactionIsCreating ||
441
-// widget.sendViewModel.state is TransactionCommitting,
442
-// isDisabled: !widget.sendViewModel.isReadyForSend);
443
-// }),
444
-// ),
445
-// );
446
-// }
447
-
448
-// void _setEffects(BuildContext context) {
449
-// if (_effectsInstalled) {
450
-// return;
451
-// }
452
-
453
-// reaction((_) => widget.sendViewModel.all, (bool all) {
454
-// if (all) {
455
-// _cryptoAmountController.text = S.current.all;
456
-// _fiatAmountController.text = null;
457
-// }
458
-// });
459
-
460
-// reaction((_) => widget.sendViewModel.fiatAmount, (String amount) {
461
-// if (amount != _fiatAmountController.text) {
462
-// _fiatAmountController.text = amount;
463
-// }
464
-// });
465
-
466
-// reaction((_) => widget.sendViewModel.cryptoAmount, (String amount) {
467
-// if (widget.sendViewModel.all && amount != S.current.all) {
468
-// widget.sendViewModel.all = false;
469
-// }
470
-
471
-// if (amount != _cryptoAmountController.text) {
472
-// _cryptoAmountController.text = amount;
473
-// }
474
-// });
475
-
476
-// reaction((_) => widget.sendViewModel.address, (String address) {
477
-// if (address != _addressController.text) {
478
-// _addressController.text = address;
479
-// }
480
-// });
481
-
482
-// _addressController.addListener(() {
483
-// final address = _addressController.text;
484
-
485
-// if (widget.sendViewModel.address != address) {
486
-// widget.sendViewModel.address = address;
487
-// }
488
-// });
489
-
490
-// reaction((_) => widget.sendViewModel.state, (SendViewModelState state) {
491
-// if (state is SendingFailed) {
492
-// WidgetsBinding.instance.addPostFrameCallback((_) {
493
-// showDialog<void>(
494
-// context: context,
495
-// builder: (BuildContext context) {
496
-// return AlertWithOneAction(
497
-// alertTitle: S.of(context).error,
498
-// alertContent: state.error,
499
-// buttonText: S.of(context).ok,
500
-// buttonAction: () => Navigator.of(context).pop());
501
-// });
502
-// });
503
-// }
504
-
505
-// if (state is TransactionCreatedSuccessfully) {
506
-// WidgetsBinding.instance.addPostFrameCallback((_) {
507
-// showDialog<void>(
508
-// context: context,
509
-// builder: (BuildContext context) {
510
-// return ConfirmSendingAlert(
511
-// alertTitle: S.of(context).confirm_sending,
512
-// amount: S.of(context).send_amount,
513
-// amountValue:
514
-// widget.sendViewModel.pendingTransaction.amountFormatted,
515
-// fee: S.of(context).send_fee,
516
-// feeValue:
517
-// widget.sendViewModel.pendingTransaction.feeFormatted,
518
-// leftButtonText: S.of(context).ok,
519
-// rightButtonText: S.of(context).cancel,
520
-// actionLeftButton: () {
521
-// Navigator.of(context).pop();
522
-// widget.sendViewModel.commitTransaction();
523
-// showDialog<void>(
524
-// context: context,
525
-// builder: (BuildContext context) {
526
-// return Observer(builder: (_) {
527
-// final state = widget.sendViewModel.state;
528
-
529
-// if (state is TransactionCommitted) {
530
-// return Stack(
531
-// children: <Widget>[
532
-// Container(
533
-// color: Theme.of(context).backgroundColor,
534
-// child: Center(
535
-// child: Image.asset(
536
-// 'assets/images/birthday_cake.png'),
537
-// ),
538
-// ),
539
-// Center(
540
-// child: Padding(
541
-// padding: EdgeInsets.only(
542
-// top: 220, left: 24, right: 24),
543
-// child: Text(
544
-// S.of(context).send_success,
545
-// textAlign: TextAlign.center,
546
-// style: TextStyle(
547
-// fontSize: 22,
548
-// fontWeight: FontWeight.bold,
549
-// color: Theme.of(context)
550
-// .primaryTextTheme
551
-// .title
552
-// .color,
553
-// decoration: TextDecoration.none,
554
-// ),
555
-// ),
556
-// ),
557
-// ),
558
-// Positioned(
559
-// left: 24,
560
-// right: 24,
561
-// bottom: 24,
562
-// child: PrimaryButton(
563
-// onPressed: () =>
564
-// Navigator.of(context).pop(),
565
-// text: S.of(context).send_got_it,
566
-// color: Colors.blue,
567
-// textColor: Colors.white))
568
-// ],
569
-// );
570
-// }
571
-
572
-// return Stack(
573
-// children: <Widget>[
574
-// Container(
575
-// color: Theme.of(context).backgroundColor,
576
-// child: Center(
577
-// child: Image.asset(
578
-// 'assets/images/birthday_cake.png'),
579
-// ),
580
-// ),
581
-// BackdropFilter(
582
-// filter: ImageFilter.blur(
583
-// sigmaX: 3.0, sigmaY: 3.0),
584
-// child: Container(
585
-// decoration: BoxDecoration(
586
-// color: Theme.of(context)
587
-// .backgroundColor
588
-// .withOpacity(0.25)),
589
-// child: Center(
590
-// child: Padding(
591
-// padding: EdgeInsets.only(top: 220),
592
-// child: Text(
593
-// S.of(context).send_sending,
594
-// textAlign: TextAlign.center,
595
-// style: TextStyle(
596
-// fontSize: 22,
597
-// fontWeight: FontWeight.bold,
598
-// color: Theme.of(context)
599
-// .primaryTextTheme
600
-// .title
601
-// .color,
602
-// decoration: TextDecoration.none,
603
-// ),
604
-// ),
605
-// ),
606
-// ),
607
-// ),
608
-// )
609
-// ],
610
-// );
611
-// });
612
-// });
613
-// },
614
-// actionRightButton: () => Navigator.of(context).pop());
615
-// });
616
-// });
617
-// }
618
-
619
-// if (state is TransactionCommitted) {
620
-// WidgetsBinding.instance.addPostFrameCallback((_) {
621
-// _addressController.text = '';
622
-// _cryptoAmountController.text = '';
623
-// });
624
-// }
625
-// });
626
-
627
-// _effectsInstalled = true;
628
-// }
629
-
630
-// Widget body(BuildContext context) => BaseSendWidget(
631
-// sendViewModel: sendViewModel,
632
-// leading: leading(context),
633
-// middle: middle(context),
634
-// );
635
-
636
-// @override
637
-// Widget build(BuildContext context) {
638
-// return Scaffold(
639
-// resizeToAvoidBottomPadding: resizeToAvoidBottomPadding,
640
-// body: Container(
641
-// color: Theme.of(context).backgroundColor, child: body(context)));
642
-// }
66
+ @override
67
+ Widget body(BuildContext context) {
68
+ _setEffects(context);
69
+
70
+ return ScrollableWithBottomSection(
71
+ contentPadding: EdgeInsets.only(bottom: 24),
72
+ content: Column(
73
+ children: <Widget>[
74
+ TopPanel(
75
+ edgeInsets: EdgeInsets.all(0),
76
+ gradient: LinearGradient(colors: [
77
+ Theme.of(context).primaryTextTheme.subhead.color,
78
+ Theme.of(context).primaryTextTheme.subhead.decorationColor,
79
+ ], begin: Alignment.topLeft, end: Alignment.bottomRight),
80
+ widget: Form(
81
+ key: _formKey,
82
+ child: Column(children: <Widget>[
83
+ CupertinoNavigationBar(
84
+ leading: leading(context),
85
+ middle: middle(context),
86
+ trailing: trailing(context),
87
+ backgroundColor: Colors.transparent,
88
+ border: null,
89
+ ),
90
+ Padding(
91
+ padding: EdgeInsets.fromLTRB(24, 24, 24, 32),
92
+ child: Column(
93
+ children: <Widget>[
94
+ AddressTextField(
95
+ controller: _addressController,
96
+ focusNode: _focusNode,
97
+ onURIScanned: (uri) {
98
+ var address = '';
99
+ var amount = '';
100
+
101
+ if (uri != null) {
102
+ address = uri.path;
103
+ amount = uri.queryParameters['tx_amount'];
104
+ } else {
105
+ address = uri.toString();
106
+ }
107
+
108
+ _addressController.text = address;
109
+ _cryptoAmountController.text = amount;
110
+ },
111
+ options: [
112
+ AddressTextFieldOption.paste,
113
+ AddressTextFieldOption.qrCode,
114
+ AddressTextFieldOption.addressBook
115
+ ],
116
+ buttonColor:
117
+ Theme.of(context).primaryTextTheme.display1.color,
118
+ borderColor:
119
+ Theme.of(context).primaryTextTheme.headline.color,
120
+ textStyle: TextStyle(
121
+ fontSize: 14,
122
+ fontWeight: FontWeight.w500,
123
+ color: Colors.white),
124
+ hintStyle: TextStyle(
125
+ fontSize: 14,
126
+ fontWeight: FontWeight.w500,
127
+ color: Theme.of(context)
128
+ .primaryTextTheme
129
+ .headline
130
+ .decorationColor),
131
+ validator: sendViewModel.addressValidator,
132
+ ),
133
+ Observer(builder: (_) {
134
+ return Padding(
135
+ padding: const EdgeInsets.only(top: 20),
136
+ child: BaseTextFormField(
137
+ controller: _cryptoAmountController,
138
+ keyboardType: TextInputType.numberWithOptions(
139
+ signed: false, decimal: true),
140
+ inputFormatters: [
141
+ BlacklistingTextInputFormatter(
142
+ RegExp('[\\-|\\ |\\,]'))
143
+ ],
144
+ prefixIcon: Padding(
145
+ padding: EdgeInsets.only(top: 9),
146
+ child:
147
+ Text(sendViewModel.currency.title + ':',
148
+ style: TextStyle(
149
+ fontSize: 16,
150
+ fontWeight: FontWeight.w600,
151
+ color: Colors.white,
152
+ )),
153
+ ),
154
+ suffixIcon: Container(
155
+ height: 32,
156
+ width: 32,
157
+ margin: EdgeInsets.only(
158
+ left: 14, top: 4, bottom: 10),
159
+ decoration: BoxDecoration(
160
+ color: Theme.of(context)
161
+ .primaryTextTheme
162
+ .display1
163
+ .color,
164
+ borderRadius: BorderRadius.all(
165
+ Radius.circular(6))),
166
+ child: InkWell(
167
+ onTap: () =>
168
+ sendViewModel.setSendAll(),
169
+ child: Center(
170
+ child: Text(S.of(context).all,
171
+ textAlign: TextAlign.center,
172
+ style: TextStyle(
173
+ fontSize: 12,
174
+ fontWeight: FontWeight.bold,
175
+ color: Theme.of(context)
176
+ .primaryTextTheme
177
+ .display1
178
+ .decorationColor)),
179
+ ),
180
+ ),
181
+ ),
182
+ hintText: '0.0000',
183
+ borderColor: Theme.of(context)
184
+ .primaryTextTheme
185
+ .headline
186
+ .color,
187
+ textStyle: TextStyle(
188
+ fontSize: 14,
189
+ fontWeight: FontWeight.w500,
190
+ color: Colors.white),
191
+ placeholderTextStyle: TextStyle(
192
+ color: Theme.of(context)
193
+ .primaryTextTheme
194
+ .headline
195
+ .decorationColor,
196
+ fontWeight: FontWeight.w500,
197
+ fontSize: 14),
198
+ validator: sendViewModel.amountValidator));
199
+ }),
200
+ Observer(
201
+ builder: (_) => Padding(
202
+ padding: EdgeInsets.only(top: 10),
203
+ child: Row(
204
+ mainAxisSize: MainAxisSize.max,
205
+ mainAxisAlignment:
206
+ MainAxisAlignment.spaceBetween,
207
+ children: <Widget>[
208
+ Expanded(
209
+ child: Text(
210
+ S.of(context).available_balance + ':',
211
+ style: TextStyle(
212
+ fontSize: 12,
213
+ fontWeight: FontWeight.w600,
214
+ color: Theme.of(context)
215
+ .primaryTextTheme
216
+ .headline
217
+ .decorationColor),
218
+ )),
219
+ Text(
220
+ sendViewModel.balance,
221
+ style: TextStyle(
222
+ fontSize: 12,
223
+ fontWeight: FontWeight.w600,
224
+ color: Theme.of(context)
225
+ .primaryTextTheme
226
+ .headline
227
+ .decorationColor),
228
+ )
229
+ ],
230
+ ),
231
+ )),
232
+ Padding(
233
+ padding: const EdgeInsets.only(top: 20),
234
+ child: BaseTextFormField(
235
+ controller: _fiatAmountController,
236
+ keyboardType: TextInputType.numberWithOptions(
237
+ signed: false, decimal: true),
238
+ inputFormatters: [
239
+ BlacklistingTextInputFormatter(
240
+ RegExp('[\\-|\\ |\\,]'))
241
+ ],
242
+ prefixIcon: Padding(
243
+ padding: EdgeInsets.only(top: 9),
244
+ child: Text(sendViewModel.fiat.title + ':',
245
+ style: TextStyle(
246
+ fontSize: 16,
247
+ fontWeight: FontWeight.w600,
248
+ color: Colors.white,
249
+ )),
250
+ ),
251
+ hintText: '0.00',
252
+ borderColor: Theme.of(context)
253
+ .primaryTextTheme
254
+ .headline
255
+ .color,
256
+ textStyle: TextStyle(
257
+ fontSize: 14,
258
+ fontWeight: FontWeight.w500,
259
+ color: Colors.white),
260
+ placeholderTextStyle: TextStyle(
261
+ color: Theme.of(context)
262
+ .primaryTextTheme
263
+ .headline
264
+ .decorationColor,
265
+ fontWeight: FontWeight.w500,
266
+ fontSize: 14),
267
+ )),
268
+ Observer(
269
+ builder: (_) => GestureDetector(
270
+ onTap: () =>
271
+ _setTransactionPriority(context),
272
+ child: Container(
273
+ padding: EdgeInsets.only(top: 24),
274
+ child: Row(
275
+ mainAxisAlignment:
276
+ MainAxisAlignment.spaceBetween,
277
+ children: <Widget>[
278
+ Text(S.of(context).send_estimated_fee,
279
+ style: TextStyle(
280
+ fontSize: 12,
281
+ fontWeight: FontWeight.w500,
282
+ //color: Theme.of(context).primaryTextTheme.display2.color,
283
+ color: Colors.white)),
284
+ Container(
285
+ child: Row(
286
+ children: <Widget>[
287
+ Text(
288
+ sendViewModel.estimatedFee
289
+ .toString() +
290
+ ' ' +
291
+ sendViewModel
292
+ .currency.title,
293
+ style: TextStyle(
294
+ fontSize: 12,
295
+ fontWeight:
296
+ FontWeight.w600,
297
+ //color: Theme.of(context).primaryTextTheme.display2.color,
298
+ color: Colors.white)),
299
+ Padding(
300
+ padding:
301
+ EdgeInsets.only(left: 5),
302
+ child: Icon(
303
+ Icons.arrow_forward_ios,
304
+ size: 12,
305
+ color: Colors.white,
306
+ ),
307
+ )
308
+ ],
309
+ ),
310
+ )
311
+ ],
312
+ ),
313
+ ),
314
+ ))
315
+ ],
316
+ ),
317
+ )
318
+ ]),
319
+ ),
320
+ ),
321
+ Padding(
322
+ padding: EdgeInsets.only(top: 30, left: 24, bottom: 24),
323
+ child: Row(
324
+ mainAxisAlignment: MainAxisAlignment.start,
325
+ children: <Widget>[
326
+ Text(
327
+ S.of(context).send_templates,
328
+ style: TextStyle(
329
+ fontSize: 18,
330
+ fontWeight: FontWeight.w600,
331
+ color: Theme.of(context)
332
+ .primaryTextTheme
333
+ .display4
334
+ .color),
335
+ )
336
+ ],
337
+ ),
338
+ ),
339
+ Container(
340
+ height: 40,
341
+ width: double.infinity,
342
+ padding: EdgeInsets.only(left: 24),
343
+ child: SingleChildScrollView(
344
+ scrollDirection: Axis.horizontal,
345
+ child: Row(
346
+ children: <Widget>[
347
+ GestureDetector(
348
+ onTap: () => Navigator.of(context)
349
+ .pushNamed(Routes.sendTemplate),
350
+ child: Container(
351
+ padding: EdgeInsets.only(left: 1, right: 10),
352
+ child: DottedBorder(
353
+ borderType: BorderType.RRect,
354
+ dashPattern: [6, 4],
355
+ color: Theme.of(context)
356
+ .primaryTextTheme
357
+ .display2
358
+ .decorationColor,
359
+ strokeWidth: 2,
360
+ radius: Radius.circular(20),
361
+ child: Container(
362
+ height: 34,
363
+ width: 75,
364
+ padding: EdgeInsets.only(left: 10, right: 10),
365
+ alignment: Alignment.center,
366
+ decoration: BoxDecoration(
367
+ borderRadius:
368
+ BorderRadius.all(Radius.circular(20)),
369
+ color: Colors.transparent,
370
+ ),
371
+ child: Text(
372
+ S.of(context).send_new,
373
+ style: TextStyle(
374
+ fontSize: 14,
375
+ fontWeight: FontWeight.w600,
376
+ color: Theme.of(context)
377
+ .primaryTextTheme
378
+ .display3
379
+ .color),
380
+ ),
381
+ )),
382
+ ),
383
+ ),
384
+ // Observer(
385
+ // builder: (_) {
386
+ // final templates = sendViewModel.templates;
387
+ // final itemCount = templates.length;
388
+
389
+ // return ListView.builder(
390
+ // scrollDirection: Axis.horizontal,
391
+ // shrinkWrap: true,
392
+ // physics: NeverScrollableScrollPhysics(),
393
+ // itemCount: itemCount,
394
+ // itemBuilder: (context, index) {
395
+ // final template = templates[index];
396
+
397
+ // return TemplateTile(
398
+ // key: UniqueKey(),
399
+ // to: template.name,
400
+ // amount: template.amount,
401
+ // from: template.cryptoCurrency,
402
+ // onTap: () {
403
+ // _addressController.text = template.address;
404
+ // _cryptoAmountController.text = template.amount;
405
+ // getOpenaliasRecord(context);
406
+ // },
407
+ // onRemove: () {
408
+ // showDialog<void>(
409
+ // context: context,
410
+ // builder: (dialogContext) {
411
+ // return AlertWithTwoActions(
412
+ // alertTitle: S.of(context).template,
413
+ // alertContent: S.of(context).confirm_delete_template,
414
+ // leftButtonText: S.of(context).delete,
415
+ // rightButtonText: S.of(context).cancel,
416
+ // actionLeftButton: () {
417
+ // Navigator.of(dialogContext).pop();
418
+ // sendViewModel.sendTemplateStore.remove(template: template);
419
+ // sendViewModel.sendTemplateStore.update();
420
+ // },
421
+ // actionRightButton: () => Navigator.of(dialogContext).pop()
422
+ // );
423
+ // }
424
+ // );
425
+ // },
426
+ // );
427
+ // }
428
+ // );
429
+ // }
430
+ // )
431
+ ],
432
+ ),
433
+ ),
434
+ )
435
+ ],
436
+ ),
437
+ bottomSectionPadding: EdgeInsets.only(left: 24, right: 24, bottom: 24),
438
+ bottomSection: Observer(builder: (_) {
439
+ return LoadingPrimaryButton(
440
+ onPressed: () {
441
+ if (_formKey.currentState.validate()) {
442
+ print('SENT!!!');
443
+ }
444
+ },
445
+ text: S.of(context).send,
446
+ color: Palette.blueCraiola,
447
+ textColor: Colors.white,
448
+ isLoading: sendViewModel.state is TransactionIsCreating ||
449
+ sendViewModel.state is TransactionCommitting,
450
+ isDisabled:
451
+ false // FIXME !(syncStore.status is SyncedSyncStatus),
452
+ );
453
+ })
454
+ );
455
+ }
456
+
457
+ void _setEffects(BuildContext context) {
458
+ if (_effectsInstalled) {
459
+ return;
460
+ }
461
+
462
+ reaction((_) => sendViewModel.sendAll, (bool all) {
463
+ if (all) {
464
+ _cryptoAmountController.text = S.current.all;
465
+ _fiatAmountController.text = null;
466
+ }
467
+ });
468
+
469
+ reaction((_) => sendViewModel.fiatAmount, (String amount) {
470
+ if (amount != _fiatAmountController.text) {
471
+ _fiatAmountController.text = amount;
472
+ }
473
+ });
474
+
475
+ reaction((_) => sendViewModel.cryptoAmount, (String amount) {
476
+ if (sendViewModel.sendAll && amount != S.current.all) {
477
+ sendViewModel.sendAll = false;
478
+ }
479
+
480
+ if (amount != _cryptoAmountController.text) {
481
+ _cryptoAmountController.text = amount;
482
+ }
483
+ });
484
+
485
+ reaction((_) => sendViewModel.address, (String address) {
486
+ if (address != _addressController.text) {
487
+ _addressController.text = address;
488
+ }
489
+ });
490
+
491
+ _addressController.addListener(() {
492
+ final address = _addressController.text;
493
+
494
+ if (sendViewModel.address != address) {
495
+ sendViewModel.address = address;
496
+ }
497
+ });
498
+
499
+ reaction((_) => sendViewModel.state, (SendViewModelState state) {
500
+ if (state is SendingFailed) {
501
+ WidgetsBinding.instance.addPostFrameCallback((_) {
502
+ showDialog<void>(
503
+ context: context,
504
+ builder: (BuildContext context) {
505
+ return AlertWithOneAction(
506
+ alertTitle: S.of(context).error,
507
+ alertContent: state.error,
508
+ buttonText: S.of(context).ok,
509
+ buttonAction: () => Navigator.of(context).pop());
510
+ });
511
+ });
512
+ }
513
+
514
+ if (state is TransactionCreatedSuccessfully) {
515
+ WidgetsBinding.instance.addPostFrameCallback((_) {
516
+ showDialog<void>(
517
+ context: context,
518
+ builder: (BuildContext context) {
519
+ return ConfirmSendingAlert(
520
+ alertTitle: S.of(context).confirm_sending,
521
+ amount: S.of(context).send_amount,
522
+ amountValue:
523
+ sendViewModel.pendingTransaction.amountFormatted,
524
+ fee: S.of(context).send_fee,
525
+ feeValue: sendViewModel.pendingTransaction.feeFormatted,
526
+ leftButtonText: S.of(context).ok,
527
+ rightButtonText: S.of(context).cancel,
528
+ actionLeftButton: () {
529
+ Navigator.of(context).pop();
530
+ sendViewModel.commitTransaction();
531
+ showDialog<void>(
532
+ context: context,
533
+ builder: (BuildContext context) {
534
+ return Observer(builder: (_) {
535
+ final state = sendViewModel.state;
536
+
537
+ if (state is TransactionCommitted) {
538
+ return Stack(
539
+ children: <Widget>[
540
+ Container(
541
+ color: Theme.of(context).backgroundColor,
542
+ child: Center(
543
+ child: Image.asset(
544
+ 'assets/images/birthday_cake.png'),
545
+ ),
546
+ ),
547
+ Center(
548
+ child: Padding(
549
+ padding: EdgeInsets.only(
550
+ top: 220, left: 24, right: 24),
551
+ child: Text(
552
+ S.of(context).send_success,
553
+ textAlign: TextAlign.center,
554
+ style: TextStyle(
555
+ fontSize: 22,
556
+ fontWeight: FontWeight.bold,
557
+ color: Theme.of(context)
558
+ .primaryTextTheme
559
+ .title
560
+ .color,
561
+ decoration: TextDecoration.none,
562
+ ),
563
+ ),
564
+ ),
565
+ ),
566
+ Positioned(
567
+ left: 24,
568
+ right: 24,
569
+ bottom: 24,
570
+ child: PrimaryButton(
571
+ onPressed: () =>
572
+ Navigator.of(context).pop(),
573
+ text: S.of(context).send_got_it,
574
+ color: Colors.blue,
575
+ textColor: Colors.white))
576
+ ],
577
+ );
578
+ }
579
+
580
+ return Stack(
581
+ children: <Widget>[
582
+ Container(
583
+ color: Theme.of(context).backgroundColor,
584
+ child: Center(
585
+ child: Image.asset(
586
+ 'assets/images/birthday_cake.png'),
587
+ ),
588
+ ),
589
+ BackdropFilter(
590
+ filter: ImageFilter.blur(
591
+ sigmaX: 3.0, sigmaY: 3.0),
592
+ child: Container(
593
+ decoration: BoxDecoration(
594
+ color: Theme.of(context)
595
+ .backgroundColor
596
+ .withOpacity(0.25)),
597
+ child: Center(
598
+ child: Padding(
599
+ padding: EdgeInsets.only(top: 220),
600
+ child: Text(
601
+ S.of(context).send_sending,
602
+ textAlign: TextAlign.center,
603
+ style: TextStyle(
604
+ fontSize: 22,
605
+ fontWeight: FontWeight.bold,
606
+ color: Theme.of(context)
607
+ .primaryTextTheme
608
+ .title
609
+ .color,
610
+ decoration: TextDecoration.none,
611
+ ),
612
+ ),
613
+ ),
614
+ ),
615
+ ),
616
+ )
617
+ ],
618
+ );
619
+ });
620
+ });
621
+ },
622
+ actionRightButton: () => Navigator.of(context).pop());
623
+ });
624
+ });
625
+ }
626
+
627
+ if (state is TransactionCommitted) {
628
+ WidgetsBinding.instance.addPostFrameCallback((_) {
629
+ _addressController.text = '';
630
+ _cryptoAmountController.text = '';
631
+ });
632
+ }
633
+ });
634
+
635
+ _effectsInstalled = true;
636
+ }
637
+
638
+ Future<void> getOpenaliasRecord(BuildContext context) async {
639
+ // final isOpenalias =
640
+ // await sendViewModel.isOpenaliasRecord(_addressController.text);
641
+
642
+ // if (isOpenalias) {
643
+ // _addressController.text = sendViewModel.recordAddress;
644
+
645
+ // await showDialog<void>(
646
+ // context: context,
647
+ // builder: (BuildContext context) {
648
+ // return AlertWithOneAction(
649
+ // alertTitle: S.of(context).openalias_alert_title,
650
+ // alertContent: S
651
+ // .of(context)
652
+ // .openalias_alert_content(sendViewModel.recordName),
653
+ // buttonText: S.of(context).ok,
654
+ // buttonAction: () => Navigator.of(context).pop());
655
+ // });
656
+ // }
657
+ }
658
+
659
+ Future<void> _setTransactionPriority(BuildContext context) async {
660
+ final items = TransactionPriority.all;
661
+ final selectedItem = items.indexOf(sendViewModel.transactionPriority);
662
+
663
+ await showDialog<void>(
664
+ builder: (_) => Picker(
665
+ items: items,
666
+ selectedAtIndex: selectedItem,
667
+ title: S.of(context).please_select,
668
+ mainAxisAlignment: MainAxisAlignment.center,
669
+ onItemSelected: (TransactionPriority priority) => null,
670
+ // sendViewModel.setTransactionPriority(priority),
671
+ isAlwaysShowScrollThumb: true,
672
+ ),
673
+ context: context);
674
+ }
675
}
pubspec.lock
+12
-19
@@ -42,7 +42,7 @@ packages:
42
name: async
43
url: "https://pub.dartlang.org"
44
source: hosted
45
- version: "2.4.2"
45
+ version: "2.4.1"
46
auto_size_text:
47
dependency: "direct main"
48
description:
@@ -210,7 +210,7 @@ packages:
210
name: collection
211
url: "https://pub.dartlang.org"
212
source: hosted
213
- version: "1.14.13"
213
+ version: "1.14.12"
214
convert:
215
dependency: transitive
216
description:
@@ -224,7 +224,7 @@ packages:
224
name: crypto
225
url: "https://pub.dartlang.org"
226
source: hosted
227
- version: "2.1.5"
227
+ version: "2.1.4"
228
csslib:
229
dependency: transitive
230
description:
@@ -302,13 +302,6 @@ packages:
302
url: "https://pub.dartlang.org"
303
source: hosted
304
version: "1.0.2"
305
- fake_async:
306
- dependency: transitive
307
- description:
308
- name: fake_async
309
- url: "https://pub.dartlang.org"
310
- source: hosted
311
- version: "1.1.0"
305
ffi:
306
dependency: transitive
307
description:
@@ -475,7 +468,7 @@ packages:
468
name: image
469
url: "https://pub.dartlang.org"
470
source: hosted
478
- version: "2.1.14"
471
+ version: "2.1.12"
472
intl:
473
dependency: "direct main"
474
description:
@@ -524,7 +517,7 @@ packages:
517
name: matcher
518
url: "https://pub.dartlang.org"
519
source: hosted
527
- version: "0.12.8"
520
+ version: "0.12.6"
521
meta:
522
dependency: transitive
523
description:
@@ -594,7 +587,7 @@ packages:
587
name: path
588
url: "https://pub.dartlang.org"
589
source: hosted
597
- version: "1.7.0"
590
+ version: "1.6.4"
591
path_drawing:
592
dependency: transitive
593
description:
@@ -650,7 +643,7 @@ packages:
643
name: petitparser
644
url: "https://pub.dartlang.org"
645
source: hosted
653
- version: "3.0.4"
646
+ version: "2.4.0"
647
platform:
648
dependency: transitive
649
description:
@@ -830,7 +823,7 @@ packages:
823
name: stack_trace
824
url: "https://pub.dartlang.org"
825
source: hosted
833
- version: "1.9.5"
826
+ version: "1.9.3"
827
stream_channel:
828
dependency: transitive
829
description:
@@ -865,7 +858,7 @@ packages:
858
name: test_api
859
url: "https://pub.dartlang.org"
860
source: hosted
868
- version: "0.2.17"
861
+ version: "0.2.15"
862
time:
863
dependency: transitive
864
description:
@@ -886,7 +879,7 @@ packages:
879
name: typed_data
880
url: "https://pub.dartlang.org"
881
source: hosted
889
- version: "1.2.0"
882
+ version: "1.1.6"
883
url_launcher:
884
dependency: "direct main"
885
description:
@@ -963,7 +956,7 @@ packages:
956
name: xml
957
url: "https://pub.dartlang.org"
958
source: hosted
966
- version: "4.2.0"
959
+ version: "3.6.1"
960
yaml:
961
dependency: "direct main"
962
description:
@@ -972,5 +965,5 @@ packages:
965
source: hosted
966
version: "2.2.1"
967
sdks:
975
- dart: ">=2.9.0-14.0.dev <3.0.0"
968
+ dart: ">=2.7.0 <3.0.0"
969
flutter: ">=1.12.13+hotfix.5 <2.0.0"