CAKE-49 | deleted base send widget, base exchange widget and top panel; added extendBodyBehindAppBar property and transparent AppBar style to base page; refactored send page, send template page, exchange page and exchange template page
OleksandrSobol committed
Sep 22, 2020 at 21:32 UTC
585f90b2fb263e7ea3c7839d6c21b020b0c47a42
8 files changed
+1527
-1789
lib/src/screens/base_page.dart
+18
-7
@@ -6,7 +6,7 @@ import 'package:cake_wallet/themes.dart';
6
import 'package:cake_wallet/theme_changer.dart';
7
import 'package:cake_wallet/palette.dart';
8
9
-enum AppBarStyle { regular, withShadow }
9
+enum AppBarStyle { regular, withShadow, transparent }
10
11
abstract class BasePage extends StatelessWidget {
12
String get title => null;
@@ -21,6 +21,8 @@ abstract class BasePage extends StatelessWidget {
21
22
bool get resizeToAvoidBottomPadding => true;
23
24
+ bool get extendBodyBehindAppBar => false;
25
+
26
Widget get endDrawer => null;
27
28
AppBarStyle get appBarStyle => AppBarStyle.regular;
@@ -85,6 +87,8 @@ abstract class BasePage extends StatelessWidget {
87
ObstructingPreferredSizeWidget appBar(BuildContext context) {
88
final _themeChanger = Provider.of<ThemeChanger>(context);
89
final _isDarkTheme = _themeChanger.getTheme() == Themes.darkTheme;
90
+ final appBarColor = _isDarkTheme
91
+ ? backgroundDarkColor : backgroundLightColor;
92
93
switch (appBarStyle) {
94
case AppBarStyle.regular:
@@ -93,8 +97,7 @@ abstract class BasePage extends StatelessWidget {
97
leading: leading(context),
98
middle: middle(context),
99
trailing: trailing(context),
96
- backgroundColor:
97
- _isDarkTheme ? backgroundDarkColor : backgroundLightColor);
100
+ backgroundColor: appBarColor);
101
102
case AppBarStyle.withShadow:
103
return NavBar.withShadow(
@@ -102,8 +105,16 @@ abstract class BasePage extends StatelessWidget {
105
leading: leading(context),
106
middle: middle(context),
107
trailing: trailing(context),
105
- backgroundColor:
106
- _isDarkTheme ? backgroundDarkColor : backgroundLightColor);
108
+ backgroundColor: appBarColor);
109
+
110
+ case AppBarStyle.transparent:
111
+ return CupertinoNavigationBar(
112
+ leading: leading(context),
113
+ middle: middle(context),
114
+ trailing: trailing(context),
115
+ backgroundColor: Colors.transparent,
116
+ border: null,
117
+ );
118
119
default:
120
return NavBar(
@@ -111,8 +122,7 @@ abstract class BasePage extends StatelessWidget {
122
leading: leading(context),
123
middle: middle(context),
124
trailing: trailing(context),
114
- backgroundColor:
115
- _isDarkTheme ? backgroundDarkColor : backgroundLightColor);
125
+ backgroundColor: appBarColor);
126
}
127
}
128
@@ -128,6 +138,7 @@ abstract class BasePage extends StatelessWidget {
138
backgroundColor:
139
_isDarkTheme ? backgroundDarkColor : backgroundLightColor,
140
resizeToAvoidBottomPadding: resizeToAvoidBottomPadding,
141
+ extendBodyBehindAppBar: extendBodyBehindAppBar,
142
endDrawer: endDrawer,
143
appBar: appBar(context),
144
body: body(context), //SafeArea(child: ),
lib/src/screens/exchange/exchange_page.dart
+549
-18
@@ -1,18 +1,38 @@
1
import 'dart:ui';
2
+import 'package:cake_wallet/core/address_validator.dart';
3
+import 'package:cake_wallet/core/amount_validator.dart';
4
+import 'package:cake_wallet/routes.dart';
5
+import 'package:cake_wallet/src/domain/common/crypto_currency.dart';
6
+import 'package:cake_wallet/src/domain/exchange/exchange_template.dart';
7
+import 'package:cake_wallet/src/domain/exchange/xmrto/xmrto_exchange_provider.dart';
8
+import 'package:cake_wallet/src/screens/exchange/widgets/exchange_card.dart';
9
+import 'package:cake_wallet/src/stores/exchange/exchange_trade_state.dart';
10
+import 'package:cake_wallet/src/stores/exchange/limits_state.dart';
11
+import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
12
+import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
13
+import 'package:cake_wallet/src/widgets/primary_button.dart';
14
+import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
15
+import 'package:cake_wallet/src/widgets/template_tile.dart';
16
+import 'package:dotted_border/dotted_border.dart';
17
import 'package:flutter/cupertino.dart';
18
import 'package:flutter/material.dart';
19
import 'package:cake_wallet/palette.dart';
20
import 'package:cake_wallet/generated/i18n.dart';
21
import 'package:cake_wallet/src/screens/base_page.dart';
22
import 'package:cake_wallet/src/screens/exchange/widgets/present_provider_picker.dart';
8
-import 'package:cake_wallet/src/screens/exchange/widgets/base_exchange_widget.dart';
23
import 'package:cake_wallet/src/widgets/trail_button.dart';
24
import 'package:cake_wallet/view_model/exchange/exchange_view_model.dart';
25
+import 'package:flutter_mobx/flutter_mobx.dart';
26
+import 'package:mobx/mobx.dart';
27
28
class ExchangePage extends BasePage {
29
ExchangePage(this.exchangeViewModel);
30
31
final ExchangeViewModel exchangeViewModel;
32
+ final depositKey = GlobalKey<ExchangeCardState>();
33
+ final receiveKey = GlobalKey<ExchangeCardState>();
34
+ final _formKey = GlobalKey<FormState>();
35
+ var _isReactionsSet = false;
36
37
@override
38
String get title => S.current.exchange;
@@ -21,10 +41,13 @@ class ExchangePage extends BasePage {
41
Color get titleColor => Colors.white;
42
43
@override
24
- Color get backgroundLightColor => Colors.transparent;
44
+ bool get resizeToAvoidBottomPadding => false;
45
46
@override
27
- Color get backgroundDarkColor => Colors.transparent;
47
+ bool get extendBodyBehindAppBar => true;
48
+
49
+ @override
50
+ AppBarStyle get appBarStyle => AppBarStyle.transparent;
51
52
@override
53
Widget middle(BuildContext context) =>
@@ -38,22 +61,530 @@ class ExchangePage extends BasePage {
61
);
62
63
@override
41
- Widget body(BuildContext context) =>
42
- BaseExchangeWidget(
43
- exchangeViewModel: exchangeViewModel,
44
- leading: leading(context),
45
- middle: middle(context),
46
- trailing: trailing(context),
47
- );
64
+ Widget body(BuildContext context) {
65
+ final arrowBottomPurple = Image.asset(
66
+ 'assets/images/arrow_bottom_purple_icon.png',
67
+ color: Colors.white,
68
+ height: 8,
69
+ );
70
+ final arrowBottomCakeGreen = Image.asset(
71
+ 'assets/images/arrow_bottom_cake_green.png',
72
+ color: Colors.white,
73
+ height: 8,
74
+ );
75
49
- @override
50
- Widget build(BuildContext context) {
51
- return Scaffold(
52
- resizeToAvoidBottomPadding: resizeToAvoidBottomPadding,
53
- body: Container(
54
- color: Theme.of(context).backgroundColor,
55
- child: body(context)
56
- )
76
+ final depositWalletName =
77
+ exchangeViewModel.depositCurrency == CryptoCurrency.xmr
78
+ ? exchangeViewModel.wallet.name
79
+ : null;
80
+ final receiveWalletName =
81
+ exchangeViewModel.receiveCurrency == CryptoCurrency.xmr
82
+ ? exchangeViewModel.wallet.name
83
+ : null;
84
+
85
+ WidgetsBinding.instance
86
+ .addPostFrameCallback((_) => _setReactions(context, exchangeViewModel));
87
+
88
+ return Container(
89
+ color: Theme.of(context).backgroundColor,
90
+ child: Form(
91
+ key: _formKey,
92
+ child: ScrollableWithBottomSection(
93
+ contentPadding: EdgeInsets.only(bottom: 24),
94
+ content: Column(
95
+ children: <Widget>[
96
+ Container(
97
+ padding: EdgeInsets.only(bottom: 32),
98
+ decoration: BoxDecoration(
99
+ borderRadius: BorderRadius.only(
100
+ bottomLeft: Radius.circular(24),
101
+ bottomRight: Radius.circular(24)
102
+ ),
103
+ gradient: LinearGradient(
104
+ colors: [
105
+ Theme.of(context).primaryTextTheme.body1.color,
106
+ Theme.of(context).primaryTextTheme.body1.decorationColor,
107
+ ],
108
+ stops: [0.35, 1.0],
109
+ begin: Alignment.topLeft,
110
+ end: Alignment.bottomRight),
111
+ ),
112
+ child: Column(
113
+ children: <Widget>[
114
+ Container(
115
+ decoration: BoxDecoration(
116
+ borderRadius: BorderRadius.only(
117
+ bottomLeft: Radius.circular(24),
118
+ bottomRight: Radius.circular(24)
119
+ ),
120
+ gradient: LinearGradient(
121
+ colors: [
122
+ Theme.of(context)
123
+ .primaryTextTheme
124
+ .subtitle
125
+ .color,
126
+ Theme.of(context)
127
+ .primaryTextTheme
128
+ .subtitle
129
+ .decorationColor,
130
+ ],
131
+ begin: Alignment.topLeft,
132
+ end: Alignment.bottomRight),
133
+ ),
134
+ padding: EdgeInsets.fromLTRB(24, 90, 24, 32),
135
+ child: Observer(
136
+ builder: (_) => ExchangeCard(
137
+ key: depositKey,
138
+ title: S.of(context).you_will_send,
139
+ initialCurrency:
140
+ exchangeViewModel.depositCurrency,
141
+ initialWalletName: depositWalletName,
142
+ initialAddress: exchangeViewModel
143
+ .depositCurrency ==
144
+ exchangeViewModel.wallet.currency
145
+ ? exchangeViewModel.wallet.address
146
+ : exchangeViewModel.depositAddress,
147
+ initialIsAmountEditable: true,
148
+ initialIsAddressEditable: exchangeViewModel
149
+ .isDepositAddressEnabled,
150
+ isAmountEstimated: false,
151
+ currencies: CryptoCurrency.all,
152
+ onCurrencySelected: (currency) =>
153
+ exchangeViewModel.changeDepositCurrency(
154
+ currency: currency),
155
+ imageArrow: arrowBottomPurple,
156
+ currencyButtonColor: Colors.transparent,
157
+ addressButtonsColor:
158
+ Theme.of(context).focusColor,
159
+ borderColor: Theme.of(context)
160
+ .primaryTextTheme
161
+ .body2
162
+ .color,
163
+ currencyValueValidator: AmountValidator(
164
+ type: exchangeViewModel.wallet.type),
165
+ addressTextFieldValidator: AddressValidator(
166
+ type:
167
+ exchangeViewModel.depositCurrency),
168
+ ),
169
+ ),
170
+ ),
171
+ Padding(
172
+ padding: EdgeInsets.only(top: 29, left: 24, right: 24),
173
+ child: Observer(
174
+ builder: (_) => ExchangeCard(
175
+ key: receiveKey,
176
+ title: S.of(context).you_will_get,
177
+ initialCurrency:
178
+ exchangeViewModel.receiveCurrency,
179
+ initialWalletName: receiveWalletName,
180
+ initialAddress:
181
+ exchangeViewModel.receiveCurrency ==
182
+ exchangeViewModel.wallet.currency
183
+ ? exchangeViewModel.wallet.address
184
+ : exchangeViewModel.receiveAddress,
185
+ initialIsAmountEditable: false,
186
+ initialIsAddressEditable:
187
+ exchangeViewModel.isReceiveAddressEnabled,
188
+ isAmountEstimated: true,
189
+ currencies: CryptoCurrency.all,
190
+ onCurrencySelected: (currency) =>
191
+ exchangeViewModel.changeReceiveCurrency(
192
+ currency: currency),
193
+ imageArrow: arrowBottomCakeGreen,
194
+ currencyButtonColor: Colors.transparent,
195
+ addressButtonsColor:
196
+ Theme.of(context).focusColor,
197
+ borderColor: Theme.of(context)
198
+ .primaryTextTheme
199
+ .body2
200
+ .decorationColor,
201
+ currencyValueValidator: AmountValidator(
202
+ type: exchangeViewModel.wallet.type),
203
+ addressTextFieldValidator: AddressValidator(
204
+ type: exchangeViewModel.receiveCurrency),
205
+ )),
206
+ )
207
+ ],
208
+ ),
209
+ ),
210
+ Padding(
211
+ padding: EdgeInsets.only(top: 30, left: 24, bottom: 24),
212
+ child: Row(
213
+ mainAxisAlignment: MainAxisAlignment.start,
214
+ children: <Widget>[
215
+ Text(
216
+ S.of(context).send_templates,
217
+ style: TextStyle(
218
+ fontSize: 18,
219
+ fontWeight: FontWeight.w600,
220
+ color: Theme.of(context)
221
+ .primaryTextTheme
222
+ .display4
223
+ .color),
224
+ )
225
+ ],
226
+ ),
227
+ ),
228
+ Container(
229
+ height: 40,
230
+ width: double.infinity,
231
+ padding: EdgeInsets.only(left: 24),
232
+ child: SingleChildScrollView(
233
+ scrollDirection: Axis.horizontal,
234
+ child: Row(
235
+ children: <Widget>[
236
+ GestureDetector(
237
+ onTap: () => Navigator.of(context)
238
+ .pushNamed(Routes.exchangeTemplate),
239
+ child: Container(
240
+ padding: EdgeInsets.only(left: 1, right: 10),
241
+ child: DottedBorder(
242
+ borderType: BorderType.RRect,
243
+ dashPattern: [6, 4],
244
+ color: Theme.of(context)
245
+ .primaryTextTheme
246
+ .display2
247
+ .decorationColor,
248
+ strokeWidth: 2,
249
+ radius: Radius.circular(20),
250
+ child: Container(
251
+ height: 34,
252
+ width: 75,
253
+ padding: EdgeInsets.only(
254
+ left: 10, right: 10),
255
+ alignment: Alignment.center,
256
+ decoration: BoxDecoration(
257
+ borderRadius: BorderRadius.all(
258
+ Radius.circular(20)),
259
+ color: Colors.transparent,
260
+ ),
261
+ child: Text(
262
+ S.of(context).send_new,
263
+ style: TextStyle(
264
+ fontSize: 14,
265
+ fontWeight: FontWeight.w600,
266
+ color: Theme.of(context)
267
+ .primaryTextTheme
268
+ .display3
269
+ .color),
270
+ ),
271
+ )),
272
+ ),
273
+ ),
274
+ Observer(builder: (_) {
275
+ final templates = exchangeViewModel.templates;
276
+ final itemCount =
277
+ exchangeViewModel.templates.length;
278
+
279
+ return ListView.builder(
280
+ scrollDirection: Axis.horizontal,
281
+ shrinkWrap: true,
282
+ physics: NeverScrollableScrollPhysics(),
283
+ itemCount: itemCount,
284
+ itemBuilder: (context, index) {
285
+ final template = templates[index];
286
+
287
+ return TemplateTile(
288
+ key: UniqueKey(),
289
+ amount: template.amount,
290
+ from: template.depositCurrency,
291
+ to: template.receiveCurrency,
292
+ onTap: () {
293
+ applyTemplate(
294
+ exchangeViewModel, template);
295
+ },
296
+ onRemove: () {
297
+ showDialog<void>(
298
+ context: context,
299
+ builder: (dialogContext) {
300
+ return AlertWithTwoActions(
301
+ alertTitle:
302
+ S.of(context).template,
303
+ alertContent: S
304
+ .of(context)
305
+ .confirm_delete_template,
306
+ leftButtonText:
307
+ S.of(context).delete,
308
+ rightButtonText:
309
+ S.of(context).cancel,
310
+ actionLeftButton: () {
311
+ Navigator.of(
312
+ dialogContext)
313
+ .pop();
314
+ exchangeViewModel
315
+ .exchangeTemplateStore
316
+ .remove(
317
+ template:
318
+ template);
319
+ exchangeViewModel
320
+ .exchangeTemplateStore
321
+ .update();
322
+ },
323
+ actionRightButton: () =>
324
+ Navigator.of(
325
+ dialogContext)
326
+ .pop());
327
+ });
328
+ },
329
+ );
330
+ });
331
+ }),
332
+ ],
333
+ )))
334
+ ],
335
+ ),
336
+ bottomSectionPadding:
337
+ EdgeInsets.only(left: 24, right: 24, bottom: 24),
338
+ bottomSection: Column(children: <Widget>[
339
+ Padding(
340
+ padding: EdgeInsets.only(bottom: 15),
341
+ child: Observer(builder: (_) {
342
+ final description =
343
+ exchangeViewModel.provider is XMRTOExchangeProvider
344
+ ? S.of(context).amount_is_guaranteed
345
+ : S.of(context).amount_is_estimate;
346
+ return Center(
347
+ child: Text(
348
+ description,
349
+ style: TextStyle(
350
+ color: Theme.of(context)
351
+ .primaryTextTheme
352
+ .display4
353
+ .decorationColor,
354
+ fontWeight: FontWeight.w500,
355
+ fontSize: 12),
356
+ ),
357
+ );
358
+ }),
359
+ ),
360
+ Observer(
361
+ builder: (_) => LoadingPrimaryButton(
362
+ text: S.of(context).exchange,
363
+ onPressed: () {
364
+ if (_formKey.currentState.validate()) {
365
+ exchangeViewModel.createTrade();
366
+ }
367
+ },
368
+ color: Palette.blueCraiola,
369
+ textColor: Colors.white,
370
+ isLoading:
371
+ exchangeViewModel.tradeState is TradeIsCreating,
372
+ )),
373
+ ]),
374
+ )),
375
);
376
}
377
+
378
+ void applyTemplate(
379
+ ExchangeViewModel exchangeViewModel, ExchangeTemplate template) {
380
+ exchangeViewModel.changeDepositCurrency(
381
+ currency: CryptoCurrency.fromString(template.depositCurrency));
382
+ exchangeViewModel.changeReceiveCurrency(
383
+ currency: CryptoCurrency.fromString(template.receiveCurrency));
384
+
385
+ switch (template.provider) {
386
+ case 'XMR.TO':
387
+ exchangeViewModel.changeProvider(
388
+ provider: exchangeViewModel.providerList[0]);
389
+ break;
390
+ case 'ChangeNOW':
391
+ exchangeViewModel.changeProvider(
392
+ provider: exchangeViewModel.providerList[1]);
393
+ break;
394
+ case 'MorphToken':
395
+ exchangeViewModel.changeProvider(
396
+ provider: exchangeViewModel.providerList[2]);
397
+ break;
398
+ }
399
+
400
+ exchangeViewModel.changeDepositAmount(amount: template.amount);
401
+ exchangeViewModel.depositAddress = template.depositAddress;
402
+ exchangeViewModel.receiveAddress = template.receiveAddress;
403
+ }
404
+
405
+ void _setReactions(
406
+ BuildContext context, ExchangeViewModel exchangeViewModel) {
407
+ if (_isReactionsSet) {
408
+ return;
409
+ }
410
+
411
+ final depositAddressController = depositKey.currentState.addressController;
412
+ final depositAmountController = depositKey.currentState.amountController;
413
+ final receiveAddressController = receiveKey.currentState.addressController;
414
+ final receiveAmountController = receiveKey.currentState.amountController;
415
+ final limitsState = exchangeViewModel.limitsState;
416
+
417
+ if (limitsState is LimitsLoadedSuccessfully) {
418
+ final min = limitsState.limits.min != null
419
+ ? limitsState.limits.min.toString()
420
+ : null;
421
+ final max = limitsState.limits.max != null
422
+ ? limitsState.limits.max.toString()
423
+ : null;
424
+ final key = depositKey;
425
+ key.currentState.changeLimits(min: min, max: max);
426
+ }
427
+
428
+ _onCurrencyChange(
429
+ exchangeViewModel.receiveCurrency, exchangeViewModel, receiveKey);
430
+ _onCurrencyChange(
431
+ exchangeViewModel.depositCurrency, exchangeViewModel, depositKey);
432
+
433
+ reaction(
434
+ (_) => exchangeViewModel.wallet.name,
435
+ (String _) => _onWalletNameChange(
436
+ exchangeViewModel, exchangeViewModel.receiveCurrency, receiveKey));
437
+
438
+ reaction(
439
+ (_) => exchangeViewModel.wallet.name,
440
+ (String _) => _onWalletNameChange(
441
+ exchangeViewModel, exchangeViewModel.depositCurrency, depositKey));
442
+
443
+ reaction(
444
+ (_) => exchangeViewModel.receiveCurrency,
445
+ (CryptoCurrency currency) =>
446
+ _onCurrencyChange(currency, exchangeViewModel, receiveKey));
447
+
448
+ reaction(
449
+ (_) => exchangeViewModel.depositCurrency,
450
+ (CryptoCurrency currency) =>
451
+ _onCurrencyChange(currency, exchangeViewModel, depositKey));
452
+
453
+ reaction((_) => exchangeViewModel.depositAmount, (String amount) {
454
+ if (depositKey.currentState.amountController.text != amount) {
455
+ depositKey.currentState.amountController.text = amount;
456
+ }
457
+ });
458
+
459
+ reaction((_) => exchangeViewModel.depositAddress, (String address) {
460
+ if (depositKey.currentState.addressController.text != address) {
461
+ depositKey.currentState.addressController.text = address;
462
+ }
463
+ });
464
+
465
+ reaction((_) => exchangeViewModel.isDepositAddressEnabled,
466
+ (bool isEnabled) {
467
+ depositKey.currentState.isAddressEditable(isEditable: isEnabled);
468
+ });
469
+
470
+ reaction((_) => exchangeViewModel.receiveAmount, (String amount) {
471
+ if (receiveKey.currentState.amountController.text != amount) {
472
+ receiveKey.currentState.amountController.text = amount;
473
+ }
474
+ });
475
+
476
+ reaction((_) => exchangeViewModel.receiveAddress, (String address) {
477
+ if (receiveKey.currentState.addressController.text != address) {
478
+ receiveKey.currentState.addressController.text = address;
479
+ }
480
+ });
481
+
482
+ reaction((_) => exchangeViewModel.isReceiveAddressEnabled,
483
+ (bool isEnabled) {
484
+ receiveKey.currentState.isAddressEditable(isEditable: isEnabled);
485
+ });
486
+
487
+ reaction((_) => exchangeViewModel.tradeState, (ExchangeTradeState state) {
488
+ if (state is TradeIsCreatedFailure) {
489
+ WidgetsBinding.instance.addPostFrameCallback((_) {
490
+ showDialog<void>(
491
+ context: context,
492
+ builder: (BuildContext context) {
493
+ return AlertWithOneAction(
494
+ alertTitle: S.of(context).error,
495
+ alertContent: state.error,
496
+ buttonText: S.of(context).ok,
497
+ buttonAction: () => Navigator.of(context).pop());
498
+ });
499
+ });
500
+ }
501
+ if (state is TradeIsCreatedSuccessfully) {
502
+ Navigator.of(context).pushNamed(Routes.exchangeConfirm);
503
+ }
504
+ });
505
+
506
+ reaction((_) => exchangeViewModel.limitsState, (LimitsState state) {
507
+ String min;
508
+ String max;
509
+
510
+ if (state is LimitsLoadedSuccessfully) {
511
+ min = state.limits.min != null ? state.limits.min.toString() : null;
512
+ max = state.limits.max != null ? state.limits.max.toString() : null;
513
+ }
514
+
515
+ if (state is LimitsLoadedFailure) {
516
+ min = '0';
517
+ max = '0';
518
+ }
519
+
520
+ if (state is LimitsIsLoading) {
521
+ min = '...';
522
+ max = '...';
523
+ }
524
+
525
+ depositKey.currentState.changeLimits(min: min, max: max);
526
+ receiveKey.currentState.changeLimits(min: null, max: null);
527
+ });
528
+
529
+ depositAddressController.addListener(
530
+ () => exchangeViewModel.depositAddress = depositAddressController.text);
531
+
532
+ depositAmountController.addListener(() {
533
+ if (depositAmountController.text != exchangeViewModel.depositAmount) {
534
+ exchangeViewModel.changeDepositAmount(
535
+ amount: depositAmountController.text);
536
+ }
537
+ });
538
+
539
+ receiveAddressController.addListener(
540
+ () => exchangeViewModel.receiveAddress = receiveAddressController.text);
541
+
542
+ receiveAmountController.addListener(() {
543
+ if (receiveAmountController.text != exchangeViewModel.receiveAmount) {
544
+ exchangeViewModel.changeReceiveAmount(
545
+ amount: receiveAmountController.text);
546
+ }
547
+ });
548
+
549
+ reaction((_) => exchangeViewModel.wallet.address, (String address) {
550
+ if (exchangeViewModel.depositCurrency == CryptoCurrency.xmr) {
551
+ depositKey.currentState.changeAddress(address: address);
552
+ }
553
+
554
+ if (exchangeViewModel.receiveCurrency == CryptoCurrency.xmr) {
555
+ receiveKey.currentState.changeAddress(address: address);
556
+ }
557
+ });
558
+
559
+ _isReactionsSet = true;
560
+ }
561
+
562
+ void _onCurrencyChange(CryptoCurrency currency,
563
+ ExchangeViewModel exchangeViewModel, GlobalKey<ExchangeCardState> key) {
564
+ final isCurrentTypeWallet = currency == exchangeViewModel.wallet.currency;
565
+
566
+ key.currentState.changeSelectedCurrency(currency);
567
+ key.currentState.changeWalletName(
568
+ isCurrentTypeWallet ? exchangeViewModel.wallet.name : null);
569
+
570
+ key.currentState.changeAddress(
571
+ address: isCurrentTypeWallet ? exchangeViewModel.wallet.address : '');
572
+
573
+ key.currentState.changeAmount(amount: '');
574
+ }
575
+
576
+ void _onWalletNameChange(ExchangeViewModel exchangeViewModel,
577
+ CryptoCurrency currency, GlobalKey<ExchangeCardState> key) {
578
+ final isCurrentTypeWallet = currency == exchangeViewModel.wallet.currency;
579
+
580
+ if (isCurrentTypeWallet) {
581
+ key.currentState.changeWalletName(exchangeViewModel.wallet.name);
582
+ key.currentState.addressController.text =
583
+ exchangeViewModel.wallet.address;
584
+ } else if (key.currentState.addressController.text ==
585
+ exchangeViewModel.wallet.address) {
586
+ key.currentState.changeWalletName(null);
587
+ key.currentState.addressController.text = null;
588
+ }
589
+ }
590
}
lib/src/screens/exchange/exchange_template_page.dart
+374
-19
@@ -1,16 +1,29 @@
1
import 'dart:ui';
2
+import 'package:cake_wallet/core/address_validator.dart';
3
+import 'package:cake_wallet/core/amount_validator.dart';
4
+import 'package:cake_wallet/src/domain/common/crypto_currency.dart';
5
+import 'package:cake_wallet/src/domain/exchange/xmrto/xmrto_exchange_provider.dart';
6
+import 'package:cake_wallet/src/screens/exchange/widgets/exchange_card.dart';
7
+import 'package:cake_wallet/src/stores/exchange/limits_state.dart';
8
+import 'package:cake_wallet/src/widgets/primary_button.dart';
9
+import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
10
import 'package:flutter/cupertino.dart';
11
import 'package:flutter/material.dart';
12
import 'package:cake_wallet/src/screens/base_page.dart';
13
import 'package:cake_wallet/src/screens/exchange/widgets/present_provider_picker.dart';
6
-import 'package:cake_wallet/src/screens/exchange/widgets/base_exchange_widget.dart';
14
import 'package:cake_wallet/generated/i18n.dart';
15
import 'package:cake_wallet/view_model/exchange/exchange_view_model.dart';
16
+import 'package:flutter_mobx/flutter_mobx.dart';
17
+import 'package:mobx/mobx.dart';
18
19
class ExchangeTemplatePage extends BasePage {
20
ExchangeTemplatePage(this.exchangeViewModel);
21
22
final ExchangeViewModel exchangeViewModel;
23
+ final depositKey = GlobalKey<ExchangeCardState>();
24
+ final receiveKey = GlobalKey<ExchangeCardState>();
25
+ final _formKey = GlobalKey<FormState>();
26
+ var _isReactionsSet = false;
27
28
@override
29
String get title => S.current.exchange_new_template;
@@ -19,33 +32,375 @@ class ExchangeTemplatePage extends BasePage {
32
Color get titleColor => Colors.white;
33
34
@override
22
- Color get backgroundLightColor => Colors.transparent;
35
+ bool get resizeToAvoidBottomPadding => false;
36
37
@override
25
- Color get backgroundDarkColor => Colors.transparent;
38
+ bool get extendBodyBehindAppBar => true;
39
+
40
+ @override
41
+ AppBarStyle get appBarStyle => AppBarStyle.transparent;
42
43
@override
44
Widget trailing(BuildContext context) =>
45
PresentProviderPicker(exchangeViewModel: exchangeViewModel);
46
47
@override
32
- Widget body(BuildContext context) =>
33
- BaseExchangeWidget(
34
- exchangeViewModel: exchangeViewModel,
35
- leading: leading(context),
36
- middle: middle(context),
37
- trailing: trailing(context),
38
- isTemplate: true
39
- );
48
+ Widget body(BuildContext context) {
49
+ final arrowBottomPurple = Image.asset(
50
+ 'assets/images/arrow_bottom_purple_icon.png',
51
+ color: Colors.white,
52
+ height: 8,
53
+ );
54
+ final arrowBottomCakeGreen = Image.asset(
55
+ 'assets/images/arrow_bottom_cake_green.png',
56
+ color: Colors.white,
57
+ height: 8,
58
+ );
59
41
- @override
42
- Widget build(BuildContext context) {
43
- return Scaffold(
44
- resizeToAvoidBottomPadding: resizeToAvoidBottomPadding,
45
- body: Container(
46
- color: Theme.of(context).backgroundColor,
47
- child: body(context)
48
- )
60
+ final depositWalletName =
61
+ exchangeViewModel.depositCurrency == CryptoCurrency.xmr
62
+ ? exchangeViewModel.wallet.name
63
+ : null;
64
+ final receiveWalletName =
65
+ exchangeViewModel.receiveCurrency == CryptoCurrency.xmr
66
+ ? exchangeViewModel.wallet.name
67
+ : null;
68
+
69
+ WidgetsBinding.instance
70
+ .addPostFrameCallback((_) => _setReactions(context, exchangeViewModel));
71
+
72
+ return Container(
73
+ color: Theme.of(context).backgroundColor,
74
+ child: Form(
75
+ key: _formKey,
76
+ child: ScrollableWithBottomSection(
77
+ contentPadding: EdgeInsets.only(bottom: 24),
78
+ content: Container(
79
+ padding: EdgeInsets.only(bottom: 32),
80
+ decoration: BoxDecoration(
81
+ borderRadius: BorderRadius.only(
82
+ bottomLeft: Radius.circular(24),
83
+ bottomRight: Radius.circular(24)
84
+ ),
85
+ gradient: LinearGradient(
86
+ colors: [
87
+ Theme.of(context).primaryTextTheme.body1.color,
88
+ Theme.of(context).primaryTextTheme.body1.decorationColor,
89
+ ],
90
+ stops: [0.35, 1.0],
91
+ begin: Alignment.topLeft,
92
+ end: Alignment.bottomRight),
93
+ ),
94
+ child: Column(
95
+ children: <Widget>[
96
+ Container(
97
+ decoration: BoxDecoration(
98
+ borderRadius: BorderRadius.only(
99
+ bottomLeft: Radius.circular(24),
100
+ bottomRight: Radius.circular(24)
101
+ ),
102
+ gradient: LinearGradient(
103
+ colors: [
104
+ Theme.of(context)
105
+ .primaryTextTheme
106
+ .subtitle
107
+ .color,
108
+ Theme.of(context)
109
+ .primaryTextTheme
110
+ .subtitle
111
+ .decorationColor,
112
+ ],
113
+ begin: Alignment.topLeft,
114
+ end: Alignment.bottomRight),
115
+ ),
116
+ padding: EdgeInsets.fromLTRB(24, 90, 24, 32),
117
+ child: Observer(
118
+ builder: (_) => ExchangeCard(
119
+ key: depositKey,
120
+ title: S.of(context).you_will_send,
121
+ initialCurrency:
122
+ exchangeViewModel.depositCurrency,
123
+ initialWalletName: depositWalletName,
124
+ initialAddress: exchangeViewModel
125
+ .depositCurrency ==
126
+ exchangeViewModel.wallet.currency
127
+ ? exchangeViewModel.wallet.address
128
+ : exchangeViewModel.depositAddress,
129
+ initialIsAmountEditable: true,
130
+ initialIsAddressEditable: exchangeViewModel
131
+ .isDepositAddressEnabled,
132
+ isAmountEstimated: false,
133
+ currencies: CryptoCurrency.all,
134
+ onCurrencySelected: (currency) =>
135
+ exchangeViewModel.changeDepositCurrency(
136
+ currency: currency),
137
+ imageArrow: arrowBottomPurple,
138
+ currencyButtonColor: Colors.transparent,
139
+ addressButtonsColor:
140
+ Theme.of(context).focusColor,
141
+ borderColor: Theme.of(context)
142
+ .primaryTextTheme
143
+ .body2
144
+ .color,
145
+ currencyValueValidator: AmountValidator(
146
+ type: exchangeViewModel.wallet.type),
147
+ addressTextFieldValidator: AddressValidator(
148
+ type:
149
+ exchangeViewModel.depositCurrency),
150
+ ),
151
+ ),
152
+ ),
153
+ Padding(
154
+ padding: EdgeInsets.only(top: 29, left: 24, right: 24),
155
+ child: Observer(
156
+ builder: (_) => ExchangeCard(
157
+ key: receiveKey,
158
+ title: S.of(context).you_will_get,
159
+ initialCurrency:
160
+ exchangeViewModel.receiveCurrency,
161
+ initialWalletName: receiveWalletName,
162
+ initialAddress:
163
+ exchangeViewModel.receiveCurrency ==
164
+ exchangeViewModel.wallet.currency
165
+ ? exchangeViewModel.wallet.address
166
+ : exchangeViewModel.receiveAddress,
167
+ initialIsAmountEditable: false,
168
+ initialIsAddressEditable:
169
+ exchangeViewModel.isReceiveAddressEnabled,
170
+ isAmountEstimated: true,
171
+ currencies: CryptoCurrency.all,
172
+ onCurrencySelected: (currency) =>
173
+ exchangeViewModel.changeReceiveCurrency(
174
+ currency: currency),
175
+ imageArrow: arrowBottomCakeGreen,
176
+ currencyButtonColor: Colors.transparent,
177
+ addressButtonsColor:
178
+ Theme.of(context).focusColor,
179
+ borderColor: Theme.of(context)
180
+ .primaryTextTheme
181
+ .body2
182
+ .decorationColor,
183
+ currencyValueValidator: AmountValidator(
184
+ type: exchangeViewModel.wallet.type),
185
+ addressTextFieldValidator: AddressValidator(
186
+ type: exchangeViewModel.receiveCurrency),
187
+ )),
188
+ )
189
+ ],
190
+ ),
191
+ ),
192
+ bottomSectionPadding:
193
+ EdgeInsets.only(left: 24, right: 24, bottom: 24),
194
+ bottomSection: Column(children: <Widget>[
195
+ Padding(
196
+ padding: EdgeInsets.only(bottom: 15),
197
+ child: Observer(builder: (_) {
198
+ final description =
199
+ exchangeViewModel.provider is XMRTOExchangeProvider
200
+ ? S.of(context).amount_is_guaranteed
201
+ : S.of(context).amount_is_estimate;
202
+ return Center(
203
+ child: Text(
204
+ description,
205
+ style: TextStyle(
206
+ color: Theme.of(context)
207
+ .primaryTextTheme
208
+ .display4
209
+ .decorationColor,
210
+ fontWeight: FontWeight.w500,
211
+ fontSize: 12),
212
+ ),
213
+ );
214
+ }),
215
+ ),
216
+ PrimaryButton(
217
+ onPressed: () {
218
+ if (_formKey.currentState.validate()) {
219
+ exchangeViewModel.exchangeTemplateStore.addTemplate(
220
+ amount: exchangeViewModel.depositAmount,
221
+ depositCurrency:
222
+ exchangeViewModel.depositCurrency.toString(),
223
+ receiveCurrency:
224
+ exchangeViewModel.receiveCurrency.toString(),
225
+ provider: exchangeViewModel.provider.toString(),
226
+ depositAddress: exchangeViewModel.depositAddress,
227
+ receiveAddress: exchangeViewModel.receiveAddress);
228
+ exchangeViewModel.exchangeTemplateStore.update();
229
+ Navigator.of(context).pop();
230
+ }
231
+ },
232
+ text: S.of(context).save,
233
+ color: Colors.green,
234
+ textColor: Colors.white),
235
+ ]),
236
+ ))
237
);
238
}
239
+
240
+ void _setReactions(
241
+ BuildContext context, ExchangeViewModel exchangeViewModel) {
242
+ if (_isReactionsSet) {
243
+ return;
244
+ }
245
+
246
+ final depositAddressController = depositKey.currentState.addressController;
247
+ final depositAmountController = depositKey.currentState.amountController;
248
+ final receiveAddressController = receiveKey.currentState.addressController;
249
+ final receiveAmountController = receiveKey.currentState.amountController;
250
+ final limitsState = exchangeViewModel.limitsState;
251
+
252
+ if (limitsState is LimitsLoadedSuccessfully) {
253
+ final min = limitsState.limits.min != null
254
+ ? limitsState.limits.min.toString()
255
+ : null;
256
+ final max = limitsState.limits.max != null
257
+ ? limitsState.limits.max.toString()
258
+ : null;
259
+ final key = depositKey;
260
+ key.currentState.changeLimits(min: min, max: max);
261
+ }
262
+
263
+ _onCurrencyChange(
264
+ exchangeViewModel.receiveCurrency, exchangeViewModel, receiveKey);
265
+ _onCurrencyChange(
266
+ exchangeViewModel.depositCurrency, exchangeViewModel, depositKey);
267
+
268
+ reaction(
269
+ (_) => exchangeViewModel.wallet.name,
270
+ (String _) => _onWalletNameChange(
271
+ exchangeViewModel, exchangeViewModel.receiveCurrency, receiveKey));
272
+
273
+ reaction(
274
+ (_) => exchangeViewModel.wallet.name,
275
+ (String _) => _onWalletNameChange(
276
+ exchangeViewModel, exchangeViewModel.depositCurrency, depositKey));
277
+
278
+ reaction(
279
+ (_) => exchangeViewModel.receiveCurrency,
280
+ (CryptoCurrency currency) =>
281
+ _onCurrencyChange(currency, exchangeViewModel, receiveKey));
282
+
283
+ reaction(
284
+ (_) => exchangeViewModel.depositCurrency,
285
+ (CryptoCurrency currency) =>
286
+ _onCurrencyChange(currency, exchangeViewModel, depositKey));
287
+
288
+ reaction((_) => exchangeViewModel.depositAmount, (String amount) {
289
+ if (depositKey.currentState.amountController.text != amount) {
290
+ depositKey.currentState.amountController.text = amount;
291
+ }
292
+ });
293
+
294
+ reaction((_) => exchangeViewModel.depositAddress, (String address) {
295
+ if (depositKey.currentState.addressController.text != address) {
296
+ depositKey.currentState.addressController.text = address;
297
+ }
298
+ });
299
+
300
+ reaction((_) => exchangeViewModel.isDepositAddressEnabled,
301
+ (bool isEnabled) {
302
+ depositKey.currentState.isAddressEditable(isEditable: isEnabled);
303
+ });
304
+
305
+ reaction((_) => exchangeViewModel.receiveAmount, (String amount) {
306
+ if (receiveKey.currentState.amountController.text != amount) {
307
+ receiveKey.currentState.amountController.text = amount;
308
+ }
309
+ });
310
+
311
+ reaction((_) => exchangeViewModel.receiveAddress, (String address) {
312
+ if (receiveKey.currentState.addressController.text != address) {
313
+ receiveKey.currentState.addressController.text = address;
314
+ }
315
+ });
316
+
317
+ reaction((_) => exchangeViewModel.isReceiveAddressEnabled,
318
+ (bool isEnabled) {
319
+ receiveKey.currentState.isAddressEditable(isEditable: isEnabled);
320
+ });
321
+
322
+ reaction((_) => exchangeViewModel.limitsState, (LimitsState state) {
323
+ String min;
324
+ String max;
325
+
326
+ if (state is LimitsLoadedSuccessfully) {
327
+ min = state.limits.min != null ? state.limits.min.toString() : null;
328
+ max = state.limits.max != null ? state.limits.max.toString() : null;
329
+ }
330
+
331
+ if (state is LimitsLoadedFailure) {
332
+ min = '0';
333
+ max = '0';
334
+ }
335
+
336
+ if (state is LimitsIsLoading) {
337
+ min = '...';
338
+ max = '...';
339
+ }
340
+
341
+ depositKey.currentState.changeLimits(min: min, max: max);
342
+ receiveKey.currentState.changeLimits(min: null, max: null);
343
+ });
344
+
345
+ depositAddressController.addListener(
346
+ () => exchangeViewModel.depositAddress = depositAddressController.text);
347
+
348
+ depositAmountController.addListener(() {
349
+ if (depositAmountController.text != exchangeViewModel.depositAmount) {
350
+ exchangeViewModel.changeDepositAmount(
351
+ amount: depositAmountController.text);
352
+ }
353
+ });
354
+
355
+ receiveAddressController.addListener(
356
+ () => exchangeViewModel.receiveAddress = receiveAddressController.text);
357
+
358
+ receiveAmountController.addListener(() {
359
+ if (receiveAmountController.text != exchangeViewModel.receiveAmount) {
360
+ exchangeViewModel.changeReceiveAmount(
361
+ amount: receiveAmountController.text);
362
+ }
363
+ });
364
+
365
+ reaction((_) => exchangeViewModel.wallet.address, (String address) {
366
+ if (exchangeViewModel.depositCurrency == CryptoCurrency.xmr) {
367
+ depositKey.currentState.changeAddress(address: address);
368
+ }
369
+
370
+ if (exchangeViewModel.receiveCurrency == CryptoCurrency.xmr) {
371
+ receiveKey.currentState.changeAddress(address: address);
372
+ }
373
+ });
374
+
375
+ _isReactionsSet = true;
376
+ }
377
+
378
+ void _onCurrencyChange(CryptoCurrency currency,
379
+ ExchangeViewModel exchangeViewModel, GlobalKey<ExchangeCardState> key) {
380
+ final isCurrentTypeWallet = currency == exchangeViewModel.wallet.currency;
381
+
382
+ key.currentState.changeSelectedCurrency(currency);
383
+ key.currentState.changeWalletName(
384
+ isCurrentTypeWallet ? exchangeViewModel.wallet.name : null);
385
+
386
+ key.currentState.changeAddress(
387
+ address: isCurrentTypeWallet ? exchangeViewModel.wallet.address : '');
388
+
389
+ key.currentState.changeAmount(amount: '');
390
+ }
391
+
392
+ void _onWalletNameChange(ExchangeViewModel exchangeViewModel,
393
+ CryptoCurrency currency, GlobalKey<ExchangeCardState> key) {
394
+ final isCurrentTypeWallet = currency == exchangeViewModel.wallet.currency;
395
+
396
+ if (isCurrentTypeWallet) {
397
+ key.currentState.changeWalletName(exchangeViewModel.wallet.name);
398
+ key.currentState.addressController.text =
399
+ exchangeViewModel.wallet.address;
400
+ } else if (key.currentState.addressController.text ==
401
+ exchangeViewModel.wallet.address) {
402
+ key.currentState.changeWalletName(null);
403
+ key.currentState.addressController.text = null;
404
+ }
405
+ }
406
}
\ No newline at end of file
lib/src/screens/exchange/widgets/base_exchange_widget.dart
deleted
-618
@@ -1,618 +0,0 @@
1
-import 'dart:ui';
2
-import 'package:cake_wallet/palette.dart';
3
-import 'package:cake_wallet/src/domain/exchange/exchange_template.dart';
4
-import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
5
-import 'package:cake_wallet/src/widgets/template_tile.dart';
6
-import 'package:dotted_border/dotted_border.dart';
7
-import 'package:flutter/cupertino.dart';
8
-import 'package:flutter/material.dart';
9
-import 'package:flutter_mobx/flutter_mobx.dart';
10
-import 'package:mobx/mobx.dart';
11
-import 'package:cake_wallet/routes.dart';
12
-import 'package:cake_wallet/generated/i18n.dart';
13
-import 'package:cake_wallet/src/domain/common/crypto_currency.dart';
14
-import 'package:cake_wallet/src/domain/exchange/xmrto/xmrto_exchange_provider.dart';
15
-import 'package:cake_wallet/src/stores/exchange/exchange_trade_state.dart';
16
-import 'package:cake_wallet/src/stores/exchange/limits_state.dart';
17
-import 'package:cake_wallet/src/screens/exchange/widgets/exchange_card.dart';
18
-import 'package:cake_wallet/src/widgets/primary_button.dart';
19
-import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
20
-import 'package:cake_wallet/src/widgets/top_panel.dart';
21
-import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
22
-import 'package:cake_wallet/view_model/exchange/exchange_view_model.dart';
23
-import 'package:cake_wallet/core/address_validator.dart';
24
-import 'package:cake_wallet/core/amount_validator.dart';
25
-
26
-class BaseExchangeWidget extends StatefulWidget {
27
- BaseExchangeWidget({
28
- @required this.exchangeViewModel,
29
- this.leading,
30
- this.middle,
31
- this.trailing,
32
- this.isTemplate = false,
33
- });
34
-
35
- final ExchangeViewModel exchangeViewModel;
36
- final Widget leading;
37
- final Widget middle;
38
- final Widget trailing;
39
- final bool isTemplate;
40
-
41
- @override
42
- BaseExchangeWidgetState createState() => BaseExchangeWidgetState(
43
- exchangeViewModel: exchangeViewModel,
44
- leading: leading,
45
- middle: middle,
46
- trailing: trailing,
47
- isTemplate: isTemplate);
48
-}
49
-
50
-class BaseExchangeWidgetState extends State<BaseExchangeWidget> {
51
- BaseExchangeWidgetState({
52
- @required this.exchangeViewModel,
53
- @required this.leading,
54
- @required this.middle,
55
- @required this.trailing,
56
- @required this.isTemplate,
57
- });
58
-
59
- final ExchangeViewModel exchangeViewModel;
60
- final Widget leading;
61
- final Widget middle;
62
- final Widget trailing;
63
- final bool isTemplate;
64
- final double topPanelHeight = 290;
65
-
66
- final depositKey = GlobalKey<ExchangeCardState>();
67
- final receiveKey = GlobalKey<ExchangeCardState>();
68
- final _formKey = GlobalKey<FormState>();
69
- var _isReactionsSet = false;
70
-
71
- @override
72
- Widget build(BuildContext context) {
73
- final arrowBottomPurple = Image.asset(
74
- 'assets/images/arrow_bottom_purple_icon.png',
75
- color: Colors.white,
76
- height: 8,
77
- );
78
- final arrowBottomCakeGreen = Image.asset(
79
- 'assets/images/arrow_bottom_cake_green.png',
80
- color: Colors.white,
81
- height: 8,
82
- );
83
-
84
- final depositWalletName =
85
- exchangeViewModel.depositCurrency == CryptoCurrency.xmr
86
- ? exchangeViewModel.wallet.name
87
- : null;
88
- final receiveWalletName =
89
- exchangeViewModel.receiveCurrency == CryptoCurrency.xmr
90
- ? exchangeViewModel.wallet.name
91
- : null;
92
-
93
- WidgetsBinding.instance
94
- .addPostFrameCallback((_) => _setReactions(context, exchangeViewModel));
95
-
96
- return Form(
97
- key: _formKey,
98
- child: ScrollableWithBottomSection(
99
- contentPadding: EdgeInsets.only(bottom: 24),
100
- content: Column(
101
- children: <Widget>[
102
- TopPanel(
103
- gradient: LinearGradient(colors: [
104
- Theme.of(context).primaryTextTheme.body1.color,
105
- Theme.of(context).primaryTextTheme.body1.decorationColor,
106
- ], stops: [
107
- 0.35,
108
- 1.0
109
- ], begin: Alignment.topLeft, end: Alignment.bottomRight),
110
- edgeInsets: EdgeInsets.only(bottom: 32),
111
- widget: Column(
112
- children: <Widget>[
113
- TopPanel(
114
- edgeInsets: EdgeInsets.all(0),
115
- gradient: LinearGradient(
116
- colors: [
117
- Theme.of(context)
118
- .primaryTextTheme
119
- .subtitle
120
- .color,
121
- Theme.of(context)
122
- .primaryTextTheme
123
- .subtitle
124
- .decorationColor,
125
- ],
126
- begin: Alignment.topLeft,
127
- end: Alignment.bottomRight),
128
- widget: Column(
129
- children: <Widget>[
130
- CupertinoNavigationBar(
131
- leading: leading,
132
- middle: middle,
133
- trailing: trailing,
134
- backgroundColor: Colors.transparent,
135
- border: null,
136
- ),
137
- Padding(
138
- padding: EdgeInsets.fromLTRB(24, 29, 24, 32),
139
- child: Observer(
140
- builder: (_) => ExchangeCard(
141
- key: depositKey,
142
- title: S.of(context).you_will_send,
143
- initialCurrency:
144
- exchangeViewModel.depositCurrency,
145
- initialWalletName: depositWalletName,
146
- initialAddress: exchangeViewModel
147
- .depositCurrency ==
148
- exchangeViewModel.wallet.currency
149
- ? exchangeViewModel.wallet.address
150
- : exchangeViewModel.depositAddress,
151
- initialIsAmountEditable: true,
152
- initialIsAddressEditable: exchangeViewModel
153
- .isDepositAddressEnabled,
154
- isAmountEstimated: false,
155
- currencies: CryptoCurrency.all,
156
- onCurrencySelected: (currency) =>
157
- exchangeViewModel.changeDepositCurrency(
158
- currency: currency),
159
- imageArrow: arrowBottomPurple,
160
- currencyButtonColor: Colors.transparent,
161
- addressButtonsColor:
162
- Theme.of(context).focusColor,
163
- borderColor: Theme.of(context)
164
- .primaryTextTheme
165
- .body2
166
- .color,
167
- currencyValueValidator: AmountValidator(
168
- type: exchangeViewModel.wallet.type),
169
- addressTextFieldValidator: AddressValidator(
170
- type:
171
- exchangeViewModel.depositCurrency),
172
- ),
173
- ),
174
- )
175
- ],
176
- )),
177
- Padding(
178
- padding: EdgeInsets.only(top: 29, left: 24, right: 24),
179
- child: Observer(
180
- builder: (_) => ExchangeCard(
181
- key: receiveKey,
182
- title: S.of(context).you_will_get,
183
- initialCurrency:
184
- exchangeViewModel.receiveCurrency,
185
- initialWalletName: receiveWalletName,
186
- initialAddress:
187
- exchangeViewModel.receiveCurrency ==
188
- exchangeViewModel.wallet.currency
189
- ? exchangeViewModel.wallet.address
190
- : exchangeViewModel.receiveAddress,
191
- initialIsAmountEditable: false,
192
- initialIsAddressEditable:
193
- exchangeViewModel.isReceiveAddressEnabled,
194
- isAmountEstimated: true,
195
- currencies: CryptoCurrency.all,
196
- onCurrencySelected: (currency) =>
197
- exchangeViewModel.changeReceiveCurrency(
198
- currency: currency),
199
- imageArrow: arrowBottomCakeGreen,
200
- currencyButtonColor: Colors.transparent,
201
- addressButtonsColor:
202
- Theme.of(context).focusColor,
203
- borderColor: Theme.of(context)
204
- .primaryTextTheme
205
- .body2
206
- .decorationColor,
207
- currencyValueValidator: AmountValidator(
208
- type: exchangeViewModel.wallet.type),
209
- addressTextFieldValidator: AddressValidator(
210
- type: exchangeViewModel.receiveCurrency),
211
- )),
212
- )
213
- ],
214
- )),
215
- isTemplate
216
- ? Offstage()
217
- : Padding(
218
- padding: EdgeInsets.only(top: 30, left: 24, bottom: 24),
219
- child: Row(
220
- mainAxisAlignment: MainAxisAlignment.start,
221
- children: <Widget>[
222
- Text(
223
- S.of(context).send_templates,
224
- style: TextStyle(
225
- fontSize: 18,
226
- fontWeight: FontWeight.w600,
227
- color: Theme.of(context)
228
- .primaryTextTheme
229
- .display4
230
- .color),
231
- )
232
- ],
233
- ),
234
- ),
235
- isTemplate
236
- ? Offstage()
237
- : Container(
238
- height: 40,
239
- width: double.infinity,
240
- padding: EdgeInsets.only(left: 24),
241
- child: SingleChildScrollView(
242
- scrollDirection: Axis.horizontal,
243
- child: Row(
244
- children: <Widget>[
245
- GestureDetector(
246
- onTap: () => Navigator.of(context)
247
- .pushNamed(Routes.exchangeTemplate),
248
- child: Container(
249
- padding: EdgeInsets.only(left: 1, right: 10),
250
- child: DottedBorder(
251
- borderType: BorderType.RRect,
252
- dashPattern: [6, 4],
253
- color: Theme.of(context)
254
- .primaryTextTheme
255
- .display2
256
- .decorationColor,
257
- strokeWidth: 2,
258
- radius: Radius.circular(20),
259
- child: Container(
260
- height: 34,
261
- width: 75,
262
- padding: EdgeInsets.only(
263
- left: 10, right: 10),
264
- alignment: Alignment.center,
265
- decoration: BoxDecoration(
266
- borderRadius: BorderRadius.all(
267
- Radius.circular(20)),
268
- color: Colors.transparent,
269
- ),
270
- child: Text(
271
- S.of(context).send_new,
272
- style: TextStyle(
273
- fontSize: 14,
274
- fontWeight: FontWeight.w600,
275
- color: Theme.of(context)
276
- .primaryTextTheme
277
- .display3
278
- .color),
279
- ),
280
- )),
281
- ),
282
- ),
283
- Observer(builder: (_) {
284
- final templates = exchangeViewModel.templates;
285
- final itemCount =
286
- exchangeViewModel.templates.length;
287
-
288
- return ListView.builder(
289
- scrollDirection: Axis.horizontal,
290
- shrinkWrap: true,
291
- physics: NeverScrollableScrollPhysics(),
292
- itemCount: itemCount,
293
- itemBuilder: (context, index) {
294
- final template = templates[index];
295
-
296
- return TemplateTile(
297
- key: UniqueKey(),
298
- amount: template.amount,
299
- from: template.depositCurrency,
300
- to: template.receiveCurrency,
301
- onTap: () {
302
- applyTemplate(
303
- exchangeViewModel, template);
304
- },
305
- onRemove: () {
306
- showDialog<void>(
307
- context: context,
308
- builder: (dialogContext) {
309
- return AlertWithTwoActions(
310
- alertTitle:
311
- S.of(context).template,
312
- alertContent: S
313
- .of(context)
314
- .confirm_delete_template,
315
- leftButtonText:
316
- S.of(context).delete,
317
- rightButtonText:
318
- S.of(context).cancel,
319
- actionLeftButton: () {
320
- Navigator.of(
321
- dialogContext)
322
- .pop();
323
- exchangeViewModel
324
- .exchangeTemplateStore
325
- .remove(
326
- template:
327
- template);
328
- exchangeViewModel
329
- .exchangeTemplateStore
330
- .update();
331
- },
332
- actionRightButton: () =>
333
- Navigator.of(
334
- dialogContext)
335
- .pop());
336
- });
337
- },
338
- );
339
- });
340
- }),
341
- ],
342
- )))
343
- ],
344
- ),
345
- bottomSectionPadding:
346
- EdgeInsets.only(left: 24, right: 24, bottom: 24),
347
- bottomSection: Column(children: <Widget>[
348
- Padding(
349
- padding: EdgeInsets.only(bottom: 15),
350
- child: Observer(builder: (_) {
351
- final description =
352
- exchangeViewModel.provider is XMRTOExchangeProvider
353
- ? S.of(context).amount_is_guaranteed
354
- : S.of(context).amount_is_estimate;
355
- return Center(
356
- child: Text(
357
- description,
358
- style: TextStyle(
359
- color: Theme.of(context)
360
- .primaryTextTheme
361
- .display4
362
- .decorationColor,
363
- fontWeight: FontWeight.w500,
364
- fontSize: 12),
365
- ),
366
- );
367
- }),
368
- ),
369
- isTemplate
370
- ? PrimaryButton(
371
- onPressed: () {
372
- if (_formKey.currentState.validate()) {
373
- exchangeViewModel.exchangeTemplateStore.addTemplate(
374
- amount: exchangeViewModel.depositAmount,
375
- depositCurrency:
376
- exchangeViewModel.depositCurrency.toString(),
377
- receiveCurrency:
378
- exchangeViewModel.receiveCurrency.toString(),
379
- provider: exchangeViewModel.provider.toString(),
380
- depositAddress: exchangeViewModel.depositAddress,
381
- receiveAddress: exchangeViewModel.receiveAddress);
382
- exchangeViewModel.exchangeTemplateStore.update();
383
- Navigator.of(context).pop();
384
- }
385
- },
386
- text: S.of(context).save,
387
- color: Colors.green,
388
- textColor: Colors.white)
389
- : Observer(
390
- builder: (_) => LoadingPrimaryButton(
391
- text: S.of(context).exchange,
392
- onPressed: () {
393
- if (_formKey.currentState.validate()) {
394
- exchangeViewModel.createTrade();
395
- }
396
- },
397
- color: Palette.blueCraiola,
398
- textColor: Colors.white,
399
- isLoading:
400
- exchangeViewModel.tradeState is TradeIsCreating,
401
- )),
402
- ]),
403
- ));
404
- }
405
-
406
- void applyTemplate(
407
- ExchangeViewModel exchangeViewModel, ExchangeTemplate template) {
408
- exchangeViewModel.changeDepositCurrency(
409
- currency: CryptoCurrency.fromString(template.depositCurrency));
410
- exchangeViewModel.changeReceiveCurrency(
411
- currency: CryptoCurrency.fromString(template.receiveCurrency));
412
-
413
- switch (template.provider) {
414
- case 'XMR.TO':
415
- exchangeViewModel.changeProvider(
416
- provider: exchangeViewModel.providerList[0]);
417
- break;
418
- case 'ChangeNOW':
419
- exchangeViewModel.changeProvider(
420
- provider: exchangeViewModel.providerList[1]);
421
- break;
422
- case 'MorphToken':
423
- exchangeViewModel.changeProvider(
424
- provider: exchangeViewModel.providerList[2]);
425
- break;
426
- }
427
-
428
- exchangeViewModel.changeDepositAmount(amount: template.amount);
429
- exchangeViewModel.depositAddress = template.depositAddress;
430
- exchangeViewModel.receiveAddress = template.receiveAddress;
431
- }
432
-
433
- void _setReactions(
434
- BuildContext context, ExchangeViewModel exchangeViewModel) {
435
- if (_isReactionsSet) {
436
- return;
437
- }
438
-
439
- final depositAddressController = depositKey.currentState.addressController;
440
- final depositAmountController = depositKey.currentState.amountController;
441
- final receiveAddressController = receiveKey.currentState.addressController;
442
- final receiveAmountController = receiveKey.currentState.amountController;
443
- final limitsState = exchangeViewModel.limitsState;
444
-
445
- if (limitsState is LimitsLoadedSuccessfully) {
446
- final min = limitsState.limits.min != null
447
- ? limitsState.limits.min.toString()
448
- : null;
449
- final max = limitsState.limits.max != null
450
- ? limitsState.limits.max.toString()
451
- : null;
452
- final key = depositKey;
453
- key.currentState.changeLimits(min: min, max: max);
454
- }
455
-
456
- _onCurrencyChange(
457
- exchangeViewModel.receiveCurrency, exchangeViewModel, receiveKey);
458
- _onCurrencyChange(
459
- exchangeViewModel.depositCurrency, exchangeViewModel, depositKey);
460
-
461
- reaction(
462
- (_) => exchangeViewModel.wallet.name,
463
- (String _) => _onWalletNameChange(
464
- exchangeViewModel, exchangeViewModel.receiveCurrency, receiveKey));
465
-
466
- reaction(
467
- (_) => exchangeViewModel.wallet.name,
468
- (String _) => _onWalletNameChange(
469
- exchangeViewModel, exchangeViewModel.depositCurrency, depositKey));
470
-
471
- reaction(
472
- (_) => exchangeViewModel.receiveCurrency,
473
- (CryptoCurrency currency) =>
474
- _onCurrencyChange(currency, exchangeViewModel, receiveKey));
475
-
476
- reaction(
477
- (_) => exchangeViewModel.depositCurrency,
478
- (CryptoCurrency currency) =>
479
- _onCurrencyChange(currency, exchangeViewModel, depositKey));
480
-
481
- reaction((_) => exchangeViewModel.depositAmount, (String amount) {
482
- if (depositKey.currentState.amountController.text != amount) {
483
- depositKey.currentState.amountController.text = amount;
484
- }
485
- });
486
-
487
- reaction((_) => exchangeViewModel.depositAddress, (String address) {
488
- if (depositKey.currentState.addressController.text != address) {
489
- depositKey.currentState.addressController.text = address;
490
- }
491
- });
492
-
493
- reaction((_) => exchangeViewModel.isDepositAddressEnabled,
494
- (bool isEnabled) {
495
- depositKey.currentState.isAddressEditable(isEditable: isEnabled);
496
- });
497
-
498
- reaction((_) => exchangeViewModel.receiveAmount, (String amount) {
499
- if (receiveKey.currentState.amountController.text != amount) {
500
- receiveKey.currentState.amountController.text = amount;
501
- }
502
- });
503
-
504
- reaction((_) => exchangeViewModel.receiveAddress, (String address) {
505
- if (receiveKey.currentState.addressController.text != address) {
506
- receiveKey.currentState.addressController.text = address;
507
- }
508
- });
509
-
510
- reaction((_) => exchangeViewModel.isReceiveAddressEnabled,
511
- (bool isEnabled) {
512
- receiveKey.currentState.isAddressEditable(isEditable: isEnabled);
513
- });
514
-
515
- reaction((_) => exchangeViewModel.tradeState, (ExchangeTradeState state) {
516
- if (state is TradeIsCreatedFailure) {
517
- WidgetsBinding.instance.addPostFrameCallback((_) {
518
- showDialog<void>(
519
- context: context,
520
- builder: (BuildContext context) {
521
- return AlertWithOneAction(
522
- alertTitle: S.of(context).error,
523
- alertContent: state.error,
524
- buttonText: S.of(context).ok,
525
- buttonAction: () => Navigator.of(context).pop());
526
- });
527
- });
528
- }
529
- if (state is TradeIsCreatedSuccessfully) {
530
- Navigator.of(context).pushNamed(Routes.exchangeConfirm);
531
- }
532
- });
533
-
534
- reaction((_) => exchangeViewModel.limitsState, (LimitsState state) {
535
- String min;
536
- String max;
537
-
538
- if (state is LimitsLoadedSuccessfully) {
539
- min = state.limits.min != null ? state.limits.min.toString() : null;
540
- max = state.limits.max != null ? state.limits.max.toString() : null;
541
- }
542
-
543
- if (state is LimitsLoadedFailure) {
544
- min = '0';
545
- max = '0';
546
- }
547
-
548
- if (state is LimitsIsLoading) {
549
- min = '...';
550
- max = '...';
551
- }
552
-
553
- depositKey.currentState.changeLimits(min: min, max: max);
554
- receiveKey.currentState.changeLimits(min: null, max: null);
555
- });
556
-
557
- depositAddressController.addListener(
558
- () => exchangeViewModel.depositAddress = depositAddressController.text);
559
-
560
- depositAmountController.addListener(() {
561
- if (depositAmountController.text != exchangeViewModel.depositAmount) {
562
- exchangeViewModel.changeDepositAmount(
563
- amount: depositAmountController.text);
564
- }
565
- });
566
-
567
- receiveAddressController.addListener(
568
- () => exchangeViewModel.receiveAddress = receiveAddressController.text);
569
-
570
- receiveAmountController.addListener(() {
571
- if (receiveAmountController.text != exchangeViewModel.receiveAmount) {
572
- exchangeViewModel.changeReceiveAmount(
573
- amount: receiveAmountController.text);
574
- }
575
- });
576
-
577
- reaction((_) => exchangeViewModel.wallet.address, (String address) {
578
- if (exchangeViewModel.depositCurrency == CryptoCurrency.xmr) {
579
- depositKey.currentState.changeAddress(address: address);
580
- }
581
-
582
- if (exchangeViewModel.receiveCurrency == CryptoCurrency.xmr) {
583
- receiveKey.currentState.changeAddress(address: address);
584
- }
585
- });
586
-
587
- _isReactionsSet = true;
588
- }
589
-
590
- void _onCurrencyChange(CryptoCurrency currency,
591
- ExchangeViewModel exchangeViewModel, GlobalKey<ExchangeCardState> key) {
592
- final isCurrentTypeWallet = currency == exchangeViewModel.wallet.currency;
593
-
594
- key.currentState.changeSelectedCurrency(currency);
595
- key.currentState.changeWalletName(
596
- isCurrentTypeWallet ? exchangeViewModel.wallet.name : null);
597
-
598
- key.currentState.changeAddress(
599
- address: isCurrentTypeWallet ? exchangeViewModel.wallet.address : '');
600
-
601
- key.currentState.changeAmount(amount: '');
602
- }
603
-
604
- void _onWalletNameChange(ExchangeViewModel exchangeViewModel,
605
- CryptoCurrency currency, GlobalKey<ExchangeCardState> key) {
606
- final isCurrentTypeWallet = currency == exchangeViewModel.wallet.currency;
607
-
608
- if (isCurrentTypeWallet) {
609
- key.currentState.changeWalletName(exchangeViewModel.wallet.name);
610
- key.currentState.addressController.text =
611
- exchangeViewModel.wallet.address;
612
- } else if (key.currentState.addressController.text ==
613
- exchangeViewModel.wallet.address) {
614
- key.currentState.changeWalletName(null);
615
- key.currentState.addressController.text = null;
616
- }
617
- }
618
-}
lib/src/screens/send/send_page.dart
+351
-359
@@ -16,7 +16,6 @@ import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
16
import 'package:cake_wallet/view_model/send/send_view_model.dart';
17
import 'package:cake_wallet/src/screens/base_page.dart';
18
import 'package:cake_wallet/generated/i18n.dart';
19
-import 'package:cake_wallet/src/widgets/top_panel.dart';
19
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
20
import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
21
import 'package:cake_wallet/src/screens/send/widgets/confirm_sending_alert.dart';
@@ -42,99 +41,189 @@ class SendPage extends BasePage {
41
@override
42
Color get titleColor => Colors.white;
43
45
- @override
46
- Color get backgroundLightColor => Colors.transparent;
47
-
44
@override
45
bool get resizeToAvoidBottomPadding => false;
46
47
@override
52
- Widget trailing(context) => TrailButton(
53
- caption: S.of(context).clear, onPressed: () => sendViewModel.reset());
48
+ bool get extendBodyBehindAppBar => true;
49
50
@override
56
- Color get backgroundDarkColor => Colors.transparent;
51
+ AppBarStyle get appBarStyle => AppBarStyle.transparent;
52
53
@override
59
- Widget build(BuildContext context) {
60
- return Scaffold(
61
- resizeToAvoidBottomPadding: resizeToAvoidBottomPadding,
62
- body: Container(
63
- color: Theme.of(context).backgroundColor, child: body(context)));
64
- }
54
+ Widget trailing(context) => TrailButton(
55
+ caption: S.of(context).clear, onPressed: () => sendViewModel.reset());
56
57
@override
58
Widget body(BuildContext context) {
59
_setEffects(context);
60
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,
61
+ return Container(
62
+ color: Theme.of(context).backgroundColor,
63
+ child: ScrollableWithBottomSection(
64
+ contentPadding: EdgeInsets.only(bottom: 24),
65
+ content: Column(
66
+ children: <Widget>[
67
+ Container(
68
+ decoration: BoxDecoration(
69
+ borderRadius: BorderRadius.only(
70
+ bottomLeft: Radius.circular(24),
71
+ bottomRight: Radius.circular(24)
72
+ ),
73
+ gradient: LinearGradient(colors: [
74
+ Theme.of(context).primaryTextTheme.subhead.color,
75
+ Theme.of(context).primaryTextTheme.subhead.decorationColor,
76
+ ], begin: Alignment.topLeft, end: Alignment.bottomRight),
77
),
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,
78
+ child: Form(
79
+ key: _formKey,
80
+ child: Column(children: <Widget>[
81
+ Padding(
82
+ padding: EdgeInsets.fromLTRB(24, 90, 24, 32),
83
+ child: Column(
84
+ children: <Widget>[
85
+ AddressTextField(
86
+ controller: _addressController,
87
+ focusNode: _focusNode,
88
+ onURIScanned: (uri) {
89
+ var address = '';
90
+ var amount = '';
91
+
92
+ if (uri != null) {
93
+ address = uri.path;
94
+ amount = uri.queryParameters['tx_amount'];
95
+ } else {
96
+ address = uri.toString();
97
+ }
98
+
99
+ _addressController.text = address;
100
+ _cryptoAmountController.text = amount;
101
+ },
102
+ options: [
103
+ AddressTextFieldOption.paste,
104
+ AddressTextFieldOption.qrCode,
105
+ AddressTextFieldOption.addressBook
106
+ ],
107
+ buttonColor:
108
+ Theme.of(context).primaryTextTheme.display1.color,
109
+ borderColor:
110
+ Theme.of(context).primaryTextTheme.headline.color,
111
+ textStyle: TextStyle(
112
+ fontSize: 14,
113
+ fontWeight: FontWeight.w500,
114
+ color: Colors.white),
115
+ hintStyle: TextStyle(
116
+ fontSize: 14,
117
+ fontWeight: FontWeight.w500,
118
+ color: Theme.of(context)
119
+ .primaryTextTheme
120
+ .headline
121
+ .decorationColor),
122
+ validator: sendViewModel.addressValidator,
123
+ ),
124
+ Observer(builder: (_) {
125
+ return Padding(
126
+ padding: const EdgeInsets.only(top: 20),
127
+ child: BaseTextFormField(
128
+ controller: _cryptoAmountController,
129
+ keyboardType: TextInputType.numberWithOptions(
130
+ signed: false, decimal: true),
131
+ inputFormatters: [
132
+ BlacklistingTextInputFormatter(
133
+ RegExp('[\\-|\\ |\\,]'))
134
+ ],
135
+ prefixIcon: Padding(
136
+ padding: EdgeInsets.only(top: 9),
137
+ child:
138
+ Text(sendViewModel.currency.title + ':',
139
+ style: TextStyle(
140
+ fontSize: 16,
141
+ fontWeight: FontWeight.w600,
142
+ color: Colors.white,
143
+ )),
144
+ ),
145
+ suffixIcon: Container(
146
+ height: 32,
147
+ width: 32,
148
+ margin: EdgeInsets.only(
149
+ left: 14, top: 4, bottom: 10),
150
+ decoration: BoxDecoration(
151
+ color: Theme.of(context)
152
+ .primaryTextTheme
153
+ .display1
154
+ .color,
155
+ borderRadius: BorderRadius.all(
156
+ Radius.circular(6))),
157
+ child: InkWell(
158
+ onTap: () =>
159
+ sendViewModel.setSendAll(),
160
+ child: Center(
161
+ child: Text(S.of(context).all,
162
+ textAlign: TextAlign.center,
163
+ style: TextStyle(
164
+ fontSize: 12,
165
+ fontWeight: FontWeight.bold,
166
+ color: Theme.of(context)
167
+ .primaryTextTheme
168
+ .display1
169
+ .decorationColor)),
170
+ ),
171
+ ),
172
+ ),
173
+ hintText: '0.0000',
174
+ borderColor: Theme.of(context)
175
+ .primaryTextTheme
176
+ .headline
177
+ .color,
178
+ textStyle: TextStyle(
179
+ fontSize: 14,
180
+ fontWeight: FontWeight.w500,
181
+ color: Colors.white),
182
+ placeholderTextStyle: TextStyle(
183
+ color: Theme.of(context)
184
+ .primaryTextTheme
185
+ .headline
186
+ .decorationColor,
187
+ fontWeight: FontWeight.w500,
188
+ fontSize: 14),
189
+ validator: sendViewModel.amountValidator));
190
+ }),
191
+ Observer(
192
+ builder: (_) => Padding(
193
+ padding: EdgeInsets.only(top: 10),
194
+ child: Row(
195
+ mainAxisSize: MainAxisSize.max,
196
+ mainAxisAlignment:
197
+ MainAxisAlignment.spaceBetween,
198
+ children: <Widget>[
199
+ Expanded(
200
+ child: Text(
201
+ S.of(context).available_balance + ':',
202
+ style: TextStyle(
203
+ fontSize: 12,
204
+ fontWeight: FontWeight.w600,
205
+ color: Theme.of(context)
206
+ .primaryTextTheme
207
+ .headline
208
+ .decorationColor),
209
+ )),
210
+ Text(
211
+ sendViewModel.balance,
212
+ style: TextStyle(
213
+ fontSize: 12,
214
+ fontWeight: FontWeight.w600,
215
+ color: Theme.of(context)
216
+ .primaryTextTheme
217
+ .headline
218
+ .decorationColor),
219
+ )
220
+ ],
221
+ ),
222
+ )),
223
+ Padding(
224
+ padding: const EdgeInsets.only(top: 20),
225
+ child: BaseTextFormField(
226
+ controller: _fiatAmountController,
227
keyboardType: TextInputType.numberWithOptions(
228
signed: false, decimal: true),
229
inputFormatters: [
@@ -143,43 +232,14 @@ class SendPage extends BasePage {
232
],
233
prefixIcon: Padding(
234
padding: EdgeInsets.only(top: 9),
146
- child:
147
- Text(sendViewModel.currency.title + ':',
235
+ child: Text(sendViewModel.fiat.title + ':',
236
style: TextStyle(
237
fontSize: 16,
238
fontWeight: FontWeight.w600,
239
color: Colors.white,
240
)),
241
),
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',
242
+ hintText: '0.00',
243
borderColor: Theme.of(context)
244
.primaryTextTheme
245
.headline
@@ -195,262 +255,194 @@ class SendPage extends BasePage {
255
.decorationColor,
256
fontWeight: FontWeight.w500,
257
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,
258
+ )),
259
+ Observer(
260
+ builder: (_) => GestureDetector(
261
+ onTap: () =>
262
+ _setTransactionPriority(context),
263
+ child: Container(
264
+ padding: EdgeInsets.only(top: 24),
265
+ child: Row(
266
+ mainAxisAlignment:
267
+ MainAxisAlignment.spaceBetween,
268
+ children: <Widget>[
269
+ Text(S.of(context).send_estimated_fee,
270
+ style: TextStyle(
271
+ fontSize: 12,
272
+ fontWeight: FontWeight.w500,
273
+ //color: Theme.of(context).primaryTextTheme.display2.color,
274
+ color: Colors.white)),
275
+ Container(
276
+ child: Row(
277
+ children: <Widget>[
278
+ Text(
279
+ sendViewModel.estimatedFee
280
+ .toString() +
281
+ ' ' +
282
+ sendViewModel
283
+ .currency.title,
284
+ style: TextStyle(
285
+ fontSize: 12,
286
+ fontWeight:
287
+ FontWeight.w600,
288
+ //color: Theme.of(context).primaryTextTheme.display2.color,
289
+ color: Colors.white)),
290
+ Padding(
291
+ padding:
292
+ EdgeInsets.only(left: 5),
293
+ child: Icon(
294
+ Icons.arrow_forward_ios,
295
+ size: 12,
296
+ color: Colors.white,
297
+ ),
298
+ )
299
+ ],
300
+ ),
301
+ )
302
+ ],
303
+ ),
304
+ ),
305
+ ))
306
+ ],
307
+ ),
308
+ )
309
+ ]),
310
+ ),
311
+ ),
312
+ Padding(
313
+ padding: EdgeInsets.only(top: 30, left: 24, bottom: 24),
314
+ child: Row(
315
+ mainAxisAlignment: MainAxisAlignment.start,
316
+ children: <Widget>[
317
+ Text(
318
+ S.of(context).send_templates,
319
+ style: TextStyle(
320
+ fontSize: 18,
321
+ fontWeight: FontWeight.w600,
322
+ color: Theme.of(context)
323
+ .primaryTextTheme
324
+ .display4
325
+ .color),
326
+ )
327
+ ],
328
+ ),
329
+ ),
330
+ Container(
331
+ height: 40,
332
+ width: double.infinity,
333
+ padding: EdgeInsets.only(left: 24),
334
+ child: SingleChildScrollView(
335
+ scrollDirection: Axis.horizontal,
336
+ child: Row(
337
+ children: <Widget>[
338
+ GestureDetector(
339
+ onTap: () => Navigator.of(context)
340
+ .pushNamed(Routes.sendTemplate),
341
+ child: Container(
342
+ padding: EdgeInsets.only(left: 1, right: 10),
343
+ child: DottedBorder(
344
+ borderType: BorderType.RRect,
345
+ dashPattern: [6, 4],
346
+ color: Theme.of(context)
347
+ .primaryTextTheme
348
+ .display2
349
+ .decorationColor,
350
+ strokeWidth: 2,
351
+ radius: Radius.circular(20),
352
+ child: Container(
353
+ height: 34,
354
+ width: 75,
355
+ padding: EdgeInsets.only(left: 10, right: 10),
356
+ alignment: Alignment.center,
357
+ decoration: BoxDecoration(
358
+ borderRadius:
359
+ BorderRadius.all(Radius.circular(20)),
360
+ color: Colors.transparent,
361
+ ),
362
+ child: Text(
363
+ S.of(context).send_new,
364
style: TextStyle(
222
- fontSize: 12,
365
+ fontSize: 14,
366
fontWeight: FontWeight.w600,
367
color: Theme.of(context)
368
.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
- ))
369
+ .display3
370
+ .color),
371
+ ),
372
+ )),
373
+ ),
374
+ ),
375
+ // Observer(
376
+ // builder: (_) {
377
+ // final templates = sendViewModel.templates;
378
+ // final itemCount = templates.length;
379
+
380
+ // return ListView.builder(
381
+ // scrollDirection: Axis.horizontal,
382
+ // shrinkWrap: true,
383
+ // physics: NeverScrollableScrollPhysics(),
384
+ // itemCount: itemCount,
385
+ // itemBuilder: (context, index) {
386
+ // final template = templates[index];
387
+
388
+ // return TemplateTile(
389
+ // key: UniqueKey(),
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
+ // onRemove: () {
399
+ // showDialog<void>(
400
+ // context: context,
401
+ // builder: (dialogContext) {
402
+ // return AlertWithTwoActions(
403
+ // alertTitle: S.of(context).template,
404
+ // alertContent: S.of(context).confirm_delete_template,
405
+ // leftButtonText: S.of(context).delete,
406
+ // rightButtonText: S.of(context).cancel,
407
+ // actionLeftButton: () {
408
+ // Navigator.of(dialogContext).pop();
409
+ // sendViewModel.sendTemplateStore.remove(template: template);
410
+ // sendViewModel.sendTemplateStore.update();
411
+ // },
412
+ // actionRightButton: () => Navigator.of(dialogContext).pop()
413
+ // );
414
+ // }
415
+ // );
416
+ // },
417
+ // );
418
+ // }
419
+ // );
420
+ // }
421
+ // )
422
],
423
),
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
- ),
424
+ ),
425
+ )
426
+ ],
427
),
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
- ],
428
+ bottomSectionPadding: EdgeInsets.only(left: 24, right: 24, bottom: 24),
429
+ bottomSection: Observer(builder: (_) {
430
+ return LoadingPrimaryButton(
431
+ onPressed: () {
432
+ if (_formKey.currentState.validate()) {
433
+ print('SENT!!!');
434
+ }
435
+ },
436
+ text: S.of(context).send,
437
+ color: Palette.blueCraiola,
438
+ textColor: Colors.white,
439
+ isLoading: sendViewModel.state is TransactionIsCreating ||
440
+ sendViewModel.state is TransactionCommitting,
441
+ isDisabled:
442
+ false // FIXME !(syncStore.status is SyncedSyncStatus),
443
+ );
444
+ })
445
),
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
- })
446
);
447
}
448
lib/src/screens/send/send_template_page.dart
+235
-15
@@ -1,14 +1,27 @@
1
+import 'package:cake_wallet/src/widgets/address_text_field.dart';
2
+import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
3
+import 'package:cake_wallet/src/widgets/primary_button.dart';
4
+import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
5
import 'package:flutter/cupertino.dart';
6
import 'package:flutter/material.dart';
7
import 'package:cake_wallet/src/screens/base_page.dart';
8
import 'package:cake_wallet/generated/i18n.dart';
9
import 'package:cake_wallet/view_model/send/send_view_model.dart';
6
-import 'package:cake_wallet/src/screens/send/widgets/base_send_widget.dart';
10
+import 'package:flutter/services.dart';
11
+import 'package:flutter_mobx/flutter_mobx.dart';
12
+import 'package:mobx/mobx.dart';
13
14
class SendTemplatePage extends BasePage {
15
SendTemplatePage({@required this.sendViewModel});
16
17
final SendViewModel sendViewModel;
18
+ final _addressController = TextEditingController();
19
+ final _cryptoAmountController = TextEditingController();
20
+ final _fiatAmountController = TextEditingController();
21
+ final _nameController = TextEditingController();
22
+ final _formKey = GlobalKey<FormState>();
23
+
24
+ bool _effectsInstalled = false;
25
26
@override
27
String get title => S.current.exchange_new_template;
@@ -17,26 +30,233 @@ class SendTemplatePage extends BasePage {
30
Color get titleColor => Colors.white;
31
32
@override
20
- Color get backgroundLightColor => Colors.transparent;
33
+ bool get resizeToAvoidBottomPadding => false;
34
35
@override
23
- Color get backgroundDarkColor => Colors.transparent;
36
+ bool get extendBodyBehindAppBar => true;
37
38
@override
26
- bool get resizeToAvoidBottomPadding => false;
39
+ AppBarStyle get appBarStyle => AppBarStyle.transparent;
40
41
@override
29
- Widget body(BuildContext context) => BaseSendWidget(
30
- sendViewModel: sendViewModel,
31
- leading: leading(context),
32
- middle: middle(context),
33
- isTemplate: true);
42
+ Widget body(BuildContext context) {
43
+ _setEffects(context);
44
35
- @override
36
- Widget build(BuildContext context) {
37
- return Scaffold(
38
- resizeToAvoidBottomPadding: resizeToAvoidBottomPadding,
39
- body: Container(
40
- color: Theme.of(context).backgroundColor, child: body(context)));
45
+ return Container(
46
+ color: Theme.of(context).backgroundColor,
47
+ child: ScrollableWithBottomSection(
48
+ contentPadding: EdgeInsets.only(bottom: 24),
49
+ content: Container(
50
+ decoration: BoxDecoration(
51
+ borderRadius: BorderRadius.only(
52
+ bottomLeft: Radius.circular(24),
53
+ bottomRight: Radius.circular(24)
54
+ ),
55
+ gradient: LinearGradient(colors: [
56
+ Theme.of(context).primaryTextTheme.subhead.color,
57
+ Theme.of(context).primaryTextTheme.subhead.decorationColor,
58
+ ], begin: Alignment.topLeft, end: Alignment.bottomRight),
59
+ ),
60
+ child: Form(
61
+ key: _formKey,
62
+ child: Column(children: <Widget>[
63
+ Padding(
64
+ padding: EdgeInsets.fromLTRB(24, 90, 24, 32),
65
+ child: Column(
66
+ children: <Widget>[
67
+ BaseTextFormField(
68
+ controller: _nameController,
69
+ hintText: S.of(context).send_name,
70
+ borderColor: Theme.of(context)
71
+ .primaryTextTheme
72
+ .headline
73
+ .color,
74
+ textStyle: TextStyle(
75
+ fontSize: 14,
76
+ fontWeight: FontWeight.w500,
77
+ color: Colors.white),
78
+ placeholderTextStyle: TextStyle(
79
+ color: Theme.of(context)
80
+ .primaryTextTheme
81
+ .headline
82
+ .decorationColor,
83
+ fontWeight: FontWeight.w500,
84
+ fontSize: 14),
85
+ validator: sendViewModel.templateValidator,
86
+ ),
87
+ Padding(
88
+ padding: EdgeInsets.only(top: 20),
89
+ child: AddressTextField(
90
+ controller: _addressController,
91
+ onURIScanned: (uri) {
92
+ var address = '';
93
+ var amount = '';
94
+
95
+ if (uri != null) {
96
+ address = uri.path;
97
+ amount = uri.queryParameters['tx_amount'];
98
+ } else {
99
+ address = uri.toString();
100
+ }
101
+
102
+ _addressController.text = address;
103
+ _cryptoAmountController.text = amount;
104
+ },
105
+ options: [
106
+ AddressTextFieldOption.paste,
107
+ AddressTextFieldOption.qrCode,
108
+ AddressTextFieldOption.addressBook
109
+ ],
110
+ buttonColor:
111
+ Theme.of(context).primaryTextTheme.display1.color,
112
+ borderColor:
113
+ Theme.of(context).primaryTextTheme.headline.color,
114
+ textStyle: TextStyle(
115
+ fontSize: 14,
116
+ fontWeight: FontWeight.w500,
117
+ color: Colors.white),
118
+ hintStyle: TextStyle(
119
+ fontSize: 14,
120
+ fontWeight: FontWeight.w500,
121
+ color: Theme.of(context)
122
+ .primaryTextTheme
123
+ .headline
124
+ .decorationColor),
125
+ validator: sendViewModel.addressValidator,
126
+ ),
127
+ ),
128
+ Observer(builder: (_) {
129
+ return Padding(
130
+ padding: const EdgeInsets.only(top: 20),
131
+ child: BaseTextFormField(
132
+ controller: _cryptoAmountController,
133
+ keyboardType: TextInputType.numberWithOptions(
134
+ signed: false, decimal: true),
135
+ inputFormatters: [
136
+ BlacklistingTextInputFormatter(
137
+ RegExp('[\\-|\\ |\\,]'))
138
+ ],
139
+ prefixIcon: Padding(
140
+ padding: EdgeInsets.only(top: 9),
141
+ child:
142
+ Text(sendViewModel.currency.title + ':',
143
+ style: TextStyle(
144
+ fontSize: 16,
145
+ fontWeight: FontWeight.w600,
146
+ color: Colors.white,
147
+ )),
148
+ ),
149
+ hintText: '0.0000',
150
+ borderColor: Theme.of(context)
151
+ .primaryTextTheme
152
+ .headline
153
+ .color,
154
+ textStyle: TextStyle(
155
+ fontSize: 14,
156
+ fontWeight: FontWeight.w500,
157
+ color: Colors.white),
158
+ placeholderTextStyle: TextStyle(
159
+ color: Theme.of(context)
160
+ .primaryTextTheme
161
+ .headline
162
+ .decorationColor,
163
+ fontWeight: FontWeight.w500,
164
+ fontSize: 14),
165
+ validator: sendViewModel.amountValidator));
166
+ }),
167
+ Padding(
168
+ padding: const EdgeInsets.only(top: 20),
169
+ child: BaseTextFormField(
170
+ controller: _fiatAmountController,
171
+ keyboardType: TextInputType.numberWithOptions(
172
+ signed: false, decimal: true),
173
+ inputFormatters: [
174
+ BlacklistingTextInputFormatter(
175
+ RegExp('[\\-|\\ |\\,]'))
176
+ ],
177
+ prefixIcon: Padding(
178
+ padding: EdgeInsets.only(top: 9),
179
+ child: Text(sendViewModel.fiat.title + ':',
180
+ style: TextStyle(
181
+ fontSize: 16,
182
+ fontWeight: FontWeight.w600,
183
+ color: Colors.white,
184
+ )),
185
+ ),
186
+ hintText: '0.00',
187
+ borderColor: Theme.of(context)
188
+ .primaryTextTheme
189
+ .headline
190
+ .color,
191
+ textStyle: TextStyle(
192
+ fontSize: 14,
193
+ fontWeight: FontWeight.w500,
194
+ color: Colors.white),
195
+ placeholderTextStyle: TextStyle(
196
+ color: Theme.of(context)
197
+ .primaryTextTheme
198
+ .headline
199
+ .decorationColor,
200
+ fontWeight: FontWeight.w500,
201
+ fontSize: 14),
202
+ )),
203
+ ],
204
+ ),
205
+ )
206
+ ]),
207
+ ),
208
+ ),
209
+ bottomSectionPadding: EdgeInsets.only(left: 24, right: 24, bottom: 24),
210
+ bottomSection: PrimaryButton(
211
+ onPressed: () {
212
+ if (_formKey.currentState.validate()) {
213
+ // sendViewModel.sendTemplateStore.addTemplate(
214
+ // name: _nameController.text,
215
+ // address: _addressController.text,
216
+ // cryptoCurrency: sendViewModel.currency.title,
217
+ // amount: _cryptoAmountController.text);
218
+ // sendViewModel.sendTemplateStore.update();
219
+ Navigator.of(context).pop();
220
+ }
221
+ },
222
+ text: S.of(context).save,
223
+ color: Colors.green,
224
+ textColor: Colors.white),
225
+ ),
226
+ );
227
+ }
228
+
229
+ void _setEffects(BuildContext context) {
230
+ if (_effectsInstalled) {
231
+ return;
232
+ }
233
+
234
+ reaction((_) => sendViewModel.fiatAmount, (String amount) {
235
+ if (amount != _fiatAmountController.text) {
236
+ _fiatAmountController.text = amount;
237
+ }
238
+ });
239
+
240
+ reaction((_) => sendViewModel.cryptoAmount, (String amount) {
241
+ if (amount != _cryptoAmountController.text) {
242
+ _cryptoAmountController.text = amount;
243
+ }
244
+ });
245
+
246
+ reaction((_) => sendViewModel.address, (String address) {
247
+ if (address != _addressController.text) {
248
+ _addressController.text = address;
249
+ }
250
+ });
251
+
252
+ _addressController.addListener(() {
253
+ final address = _addressController.text;
254
+
255
+ if (sendViewModel.address != address) {
256
+ sendViewModel.address = address;
257
+ }
258
+ });
259
+
260
+ _effectsInstalled = true;
261
}
262
}
lib/src/screens/send/widgets/base_send_widget.dart
deleted
-709
@@ -1,709 +0,0 @@
1
-import 'dart:ui';
2
-import 'package:cake_wallet/src/domain/common/transaction_priority.dart';
3
-import 'package:cake_wallet/src/widgets/picker.dart';
4
-import 'package:cake_wallet/src/widgets/primary_button.dart';
5
-import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
6
-import 'package:cake_wallet/view_model/send/send_view_model_state.dart';
7
-import 'package:flutter/cupertino.dart';
8
-import 'package:flutter/material.dart';
9
-import 'package:cake_wallet/view_model/send/send_view_model.dart';
10
-import 'package:flutter/services.dart';
11
-import 'package:flutter_mobx/flutter_mobx.dart';
12
-import 'package:mobx/mobx.dart';
13
-import 'package:cake_wallet/palette.dart';
14
-import 'package:cake_wallet/src/widgets/address_text_field.dart';
15
-import 'package:cake_wallet/generated/i18n.dart';
16
-import 'package:cake_wallet/src/widgets/top_panel.dart';
17
-import 'package:dotted_border/dotted_border.dart';
18
-import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
19
-import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
20
-import 'package:cake_wallet/src/screens/send/widgets/confirm_sending_alert.dart';
21
-import 'package:cake_wallet/src/screens/send/widgets/sending_alert.dart';
22
-import 'package:cake_wallet/src/widgets/template_tile.dart';
23
-import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
24
-import 'package:cake_wallet/routes.dart';
25
-
26
-class BaseSendWidget extends StatelessWidget {
27
- BaseSendWidget(
28
- {@required this.sendViewModel,
29
- @required this.leading,
30
- @required this.middle,
31
- this.isTemplate = false});
32
-
33
- final SendViewModel sendViewModel;
34
- final bool isTemplate;
35
- final Widget leading;
36
- final Widget middle;
37
-
38
- final _addressController = TextEditingController();
39
- final _cryptoAmountController = TextEditingController();
40
- final _fiatAmountController = TextEditingController();
41
- final _nameController = TextEditingController();
42
- final _focusNode = FocusNode();
43
- final _formKey = GlobalKey<FormState>();
44
-
45
- bool _effectsInstalled = false;
46
-
47
- @override
48
- Widget build(BuildContext context) {
49
- _setEffects(context);
50
-
51
- return ScrollableWithBottomSection(
52
- contentPadding: EdgeInsets.only(bottom: 24),
53
- content: Column(
54
- children: <Widget>[
55
- TopPanel(
56
- edgeInsets: EdgeInsets.all(0),
57
- gradient: LinearGradient(colors: [
58
- Theme.of(context).primaryTextTheme.subhead.color,
59
- Theme.of(context).primaryTextTheme.subhead.decorationColor,
60
- ], begin: Alignment.topLeft, end: Alignment.bottomRight),
61
- widget: Form(
62
- key: _formKey,
63
- child: Column(children: <Widget>[
64
- CupertinoNavigationBar(
65
- leading: leading,
66
- middle: middle,
67
- backgroundColor: Colors.transparent,
68
- border: null,
69
- ),
70
- Padding(
71
- padding: EdgeInsets.fromLTRB(24, 24, 24, 32),
72
- child: Column(
73
- children: <Widget>[
74
- isTemplate
75
- ? BaseTextFormField(
76
- controller: _nameController,
77
- hintText: S.of(context).send_name,
78
- borderColor: Theme.of(context)
79
- .primaryTextTheme
80
- .headline
81
- .color,
82
- textStyle: TextStyle(
83
- fontSize: 14,
84
- fontWeight: FontWeight.w500,
85
- color: Colors.white),
86
- placeholderTextStyle: TextStyle(
87
- color: Theme.of(context)
88
- .primaryTextTheme
89
- .headline
90
- .decorationColor,
91
- fontWeight: FontWeight.w500,
92
- fontSize: 14),
93
- validator: sendViewModel.templateValidator,
94
- )
95
- : Offstage(),
96
- Padding(
97
- padding: EdgeInsets.only(top: isTemplate ? 20 : 0),
98
- child: AddressTextField(
99
- controller: _addressController,
100
- // placeholder: S
101
- // .of(context)
102
- // .send_address(sendViewModel.cryptoCurrencyTitle),
103
- focusNode: _focusNode,
104
- onURIScanned: (uri) {
105
- var address = '';
106
- var amount = '';
107
-
108
- if (uri != null) {
109
- address = uri.path;
110
- amount = uri.queryParameters['tx_amount'];
111
- } else {
112
- address = uri.toString();
113
- }
114
-
115
- _addressController.text = address;
116
- _cryptoAmountController.text = amount;
117
- },
118
- options: [
119
- AddressTextFieldOption.paste,
120
- AddressTextFieldOption.qrCode,
121
- AddressTextFieldOption.addressBook
122
- ],
123
- buttonColor:
124
- Theme.of(context).primaryTextTheme.display1.color,
125
- borderColor:
126
- Theme.of(context).primaryTextTheme.headline.color,
127
- textStyle: TextStyle(
128
- fontSize: 14,
129
- fontWeight: FontWeight.w500,
130
- color: Colors.white),
131
- hintStyle: TextStyle(
132
- fontSize: 14,
133
- fontWeight: FontWeight.w500,
134
- color: Theme.of(context)
135
- .primaryTextTheme
136
- .headline
137
- .decorationColor),
138
- validator: sendViewModel.addressValidator,
139
- ),
140
- ),
141
- Observer(builder: (_) {
142
- return Padding(
143
- padding: const EdgeInsets.only(top: 20),
144
- child: BaseTextFormField(
145
- controller: _cryptoAmountController,
146
- keyboardType: TextInputType.numberWithOptions(
147
- signed: false, decimal: true),
148
- inputFormatters: [
149
- BlacklistingTextInputFormatter(
150
- RegExp('[\\-|\\ |\\,]'))
151
- ],
152
- prefixIcon: Padding(
153
- padding: EdgeInsets.only(top: 9),
154
- child:
155
- Text(sendViewModel.currency.title + ':',
156
- style: TextStyle(
157
- fontSize: 16,
158
- fontWeight: FontWeight.w600,
159
- color: Colors.white,
160
- )),
161
- ),
162
- suffixIcon: isTemplate
163
- ? Offstage()
164
- : Container(
165
- height: 32,
166
- width: 32,
167
- margin: EdgeInsets.only(
168
- left: 14, top: 4, bottom: 10),
169
- decoration: BoxDecoration(
170
- color: Theme.of(context)
171
- .primaryTextTheme
172
- .display1
173
- .color,
174
- borderRadius: BorderRadius.all(
175
- Radius.circular(6))),
176
- child: InkWell(
177
- onTap: () =>
178
- sendViewModel.setSendAll(),
179
- child: Center(
180
- child: Text(S.of(context).all,
181
- textAlign: TextAlign.center,
182
- style: TextStyle(
183
- fontSize: 12,
184
- fontWeight: FontWeight.bold,
185
- color: Theme.of(context)
186
- .primaryTextTheme
187
- .display1
188
- .decorationColor)),
189
- ),
190
- ),
191
- ),
192
- hintText: '0.0000',
193
- borderColor: Theme.of(context)
194
- .primaryTextTheme
195
- .headline
196
- .color,
197
- textStyle: TextStyle(
198
- fontSize: 14,
199
- fontWeight: FontWeight.w500,
200
- color: Colors.white),
201
- placeholderTextStyle: TextStyle(
202
- color: Theme.of(context)
203
- .primaryTextTheme
204
- .headline
205
- .decorationColor,
206
- fontWeight: FontWeight.w500,
207
- fontSize: 14),
208
- validator: sendViewModel.amountValidator));
209
- }),
210
- isTemplate
211
- ? Offstage()
212
- : Observer(
213
- builder: (_) => Padding(
214
- padding: EdgeInsets.only(top: 10),
215
- child: Row(
216
- mainAxisSize: MainAxisSize.max,
217
- mainAxisAlignment:
218
- MainAxisAlignment.spaceBetween,
219
- children: <Widget>[
220
- Expanded(
221
- child: Text(
222
- S.of(context).available_balance + ':',
223
- style: TextStyle(
224
- fontSize: 12,
225
- fontWeight: FontWeight.w600,
226
- color: Theme.of(context)
227
- .primaryTextTheme
228
- .headline
229
- .decorationColor),
230
- )),
231
- Text(
232
- sendViewModel.balance,
233
- style: TextStyle(
234
- fontSize: 12,
235
- fontWeight: FontWeight.w600,
236
- color: Theme.of(context)
237
- .primaryTextTheme
238
- .headline
239
- .decorationColor),
240
- )
241
- ],
242
- ),
243
- )),
244
- Padding(
245
- padding: const EdgeInsets.only(top: 20),
246
- child: BaseTextFormField(
247
- controller: _fiatAmountController,
248
- keyboardType: TextInputType.numberWithOptions(
249
- signed: false, decimal: true),
250
- inputFormatters: [
251
- BlacklistingTextInputFormatter(
252
- RegExp('[\\-|\\ |\\,]'))
253
- ],
254
- prefixIcon: Padding(
255
- padding: EdgeInsets.only(top: 9),
256
- child: Text(sendViewModel.fiat.title + ':',
257
- style: TextStyle(
258
- fontSize: 16,
259
- fontWeight: FontWeight.w600,
260
- color: Colors.white,
261
- )),
262
- ),
263
- hintText: '0.00',
264
- borderColor: Theme.of(context)
265
- .primaryTextTheme
266
- .headline
267
- .color,
268
- textStyle: TextStyle(
269
- fontSize: 14,
270
- fontWeight: FontWeight.w500,
271
- color: Colors.white),
272
- placeholderTextStyle: TextStyle(
273
- color: Theme.of(context)
274
- .primaryTextTheme
275
- .headline
276
- .decorationColor,
277
- fontWeight: FontWeight.w500,
278
- fontSize: 14),
279
- )),
280
- isTemplate
281
- ? Offstage()
282
- : Observer(
283
- builder: (_) => GestureDetector(
284
- onTap: () =>
285
- _setTransactionPriority(context),
286
- child: Container(
287
- padding: EdgeInsets.only(top: 24),
288
- child: Row(
289
- mainAxisAlignment:
290
- MainAxisAlignment.spaceBetween,
291
- children: <Widget>[
292
- Text(S.of(context).send_estimated_fee,
293
- style: TextStyle(
294
- fontSize: 12,
295
- fontWeight: FontWeight.w500,
296
- //color: Theme.of(context).primaryTextTheme.display2.color,
297
- color: Colors.white)),
298
- Container(
299
- child: Row(
300
- children: <Widget>[
301
- Text(
302
- sendViewModel.estimatedFee
303
- .toString() +
304
- ' ' +
305
- sendViewModel
306
- .currency.title,
307
- style: TextStyle(
308
- fontSize: 12,
309
- fontWeight:
310
- FontWeight.w600,
311
- //color: Theme.of(context).primaryTextTheme.display2.color,
312
- color: Colors.white)),
313
- Padding(
314
- padding:
315
- EdgeInsets.only(left: 5),
316
- child: Icon(
317
- Icons.arrow_forward_ios,
318
- size: 12,
319
- color: Colors.white,
320
- ),
321
- )
322
- ],
323
- ),
324
- )
325
- ],
326
- ),
327
- ),
328
- ))
329
- ],
330
- ),
331
- )
332
- ]),
333
- ),
334
- ),
335
- isTemplate
336
- ? Offstage()
337
- : Padding(
338
- padding: EdgeInsets.only(top: 30, left: 24, bottom: 24),
339
- child: Row(
340
- mainAxisAlignment: MainAxisAlignment.start,
341
- children: <Widget>[
342
- Text(
343
- S.of(context).send_templates,
344
- style: TextStyle(
345
- fontSize: 18,
346
- fontWeight: FontWeight.w600,
347
- color: Theme.of(context)
348
- .primaryTextTheme
349
- .display4
350
- .color),
351
- )
352
- ],
353
- ),
354
- ),
355
- isTemplate
356
- ? Offstage()
357
- : Container(
358
- height: 40,
359
- width: double.infinity,
360
- padding: EdgeInsets.only(left: 24),
361
- child: SingleChildScrollView(
362
- scrollDirection: Axis.horizontal,
363
- child: Row(
364
- children: <Widget>[
365
- GestureDetector(
366
- onTap: () => Navigator.of(context)
367
- .pushNamed(Routes.sendTemplate),
368
- child: Container(
369
- padding: EdgeInsets.only(left: 1, right: 10),
370
- child: DottedBorder(
371
- borderType: BorderType.RRect,
372
- dashPattern: [6, 4],
373
- color: Theme.of(context)
374
- .primaryTextTheme
375
- .display2
376
- .decorationColor,
377
- strokeWidth: 2,
378
- radius: Radius.circular(20),
379
- child: Container(
380
- height: 34,
381
- width: 75,
382
- padding: EdgeInsets.only(left: 10, right: 10),
383
- alignment: Alignment.center,
384
- decoration: BoxDecoration(
385
- borderRadius:
386
- BorderRadius.all(Radius.circular(20)),
387
- color: Colors.transparent,
388
- ),
389
- child: Text(
390
- S.of(context).send_new,
391
- style: TextStyle(
392
- fontSize: 14,
393
- fontWeight: FontWeight.w600,
394
- color: Theme.of(context)
395
- .primaryTextTheme
396
- .display3
397
- .color),
398
- ),
399
- )),
400
- ),
401
- ),
402
- // Observer(
403
- // builder: (_) {
404
- // final templates = sendViewModel.templates;
405
- // final itemCount = templates.length;
406
-
407
- // return ListView.builder(
408
- // scrollDirection: Axis.horizontal,
409
- // shrinkWrap: true,
410
- // physics: NeverScrollableScrollPhysics(),
411
- // itemCount: itemCount,
412
- // itemBuilder: (context, index) {
413
- // final template = templates[index];
414
-
415
- // return TemplateTile(
416
- // key: UniqueKey(),
417
- // to: template.name,
418
- // amount: template.amount,
419
- // from: template.cryptoCurrency,
420
- // onTap: () {
421
- // _addressController.text = template.address;
422
- // _cryptoAmountController.text = template.amount;
423
- // getOpenaliasRecord(context);
424
- // },
425
- // onRemove: () {
426
- // showDialog<void>(
427
- // context: context,
428
- // builder: (dialogContext) {
429
- // return AlertWithTwoActions(
430
- // alertTitle: S.of(context).template,
431
- // alertContent: S.of(context).confirm_delete_template,
432
- // leftButtonText: S.of(context).delete,
433
- // rightButtonText: S.of(context).cancel,
434
- // actionLeftButton: () {
435
- // Navigator.of(dialogContext).pop();
436
- // sendViewModel.sendTemplateStore.remove(template: template);
437
- // sendViewModel.sendTemplateStore.update();
438
- // },
439
- // actionRightButton: () => Navigator.of(dialogContext).pop()
440
- // );
441
- // }
442
- // );
443
- // },
444
- // );
445
- // }
446
- // );
447
- // }
448
- // )
449
- ],
450
- ),
451
- ),
452
- )
453
- ],
454
- ),
455
- bottomSectionPadding: EdgeInsets.only(left: 24, right: 24, bottom: 24),
456
- bottomSection: isTemplate
457
- ? PrimaryButton(
458
- onPressed: () {
459
- if (_formKey.currentState.validate()) {
460
- // sendViewModel.sendTemplateStore.addTemplate(
461
- // name: _nameController.text,
462
- // address: _addressController.text,
463
- // cryptoCurrency: sendViewModel.currency.title,
464
- // amount: _cryptoAmountController.text);
465
- // sendViewModel.sendTemplateStore.update();
466
- Navigator.of(context).pop();
467
- }
468
- },
469
- text: S.of(context).save,
470
- color: Colors.green,
471
- textColor: Colors.white)
472
- : Observer(builder: (_) {
473
- return LoadingPrimaryButton(
474
- onPressed: () {
475
- if (_formKey.currentState.validate()) {
476
- print('SENT!!!');
477
- }
478
- },
479
- text: S.of(context).send,
480
- color: Palette.blueCraiola,
481
- textColor: Colors.white,
482
- isLoading: sendViewModel.state is TransactionIsCreating ||
483
- sendViewModel.state is TransactionCommitting,
484
- isDisabled:
485
- false // FIXME !(syncStore.status is SyncedSyncStatus),
486
- );
487
- }),
488
- );
489
- }
490
-
491
- void _setEffects(BuildContext context) {
492
- if (_effectsInstalled) {
493
- return;
494
- }
495
-
496
- reaction((_) => sendViewModel.sendAll, (bool all) {
497
- if (all) {
498
- _cryptoAmountController.text = S.current.all;
499
- _fiatAmountController.text = null;
500
- }
501
- });
502
-
503
- reaction((_) => sendViewModel.fiatAmount, (String amount) {
504
- if (amount != _fiatAmountController.text) {
505
- _fiatAmountController.text = amount;
506
- }
507
- });
508
-
509
- reaction((_) => sendViewModel.cryptoAmount, (String amount) {
510
- if (sendViewModel.sendAll && amount != S.current.all) {
511
- sendViewModel.sendAll = false;
512
- }
513
-
514
- if (amount != _cryptoAmountController.text) {
515
- _cryptoAmountController.text = amount;
516
- }
517
- });
518
-
519
- reaction((_) => sendViewModel.address, (String address) {
520
- if (address != _addressController.text) {
521
- _addressController.text = address;
522
- }
523
- });
524
-
525
- _addressController.addListener(() {
526
- final address = _addressController.text;
527
-
528
- if (sendViewModel.address != address) {
529
- sendViewModel.address = address;
530
- }
531
- });
532
-
533
- reaction((_) => sendViewModel.state, (SendViewModelState state) {
534
- if (state is SendingFailed) {
535
- WidgetsBinding.instance.addPostFrameCallback((_) {
536
- showDialog<void>(
537
- context: context,
538
- builder: (BuildContext context) {
539
- return AlertWithOneAction(
540
- alertTitle: S.of(context).error,
541
- alertContent: state.error,
542
- buttonText: S.of(context).ok,
543
- buttonAction: () => Navigator.of(context).pop());
544
- });
545
- });
546
- }
547
-
548
- if (state is TransactionCreatedSuccessfully) {
549
- WidgetsBinding.instance.addPostFrameCallback((_) {
550
- showDialog<void>(
551
- context: context,
552
- builder: (BuildContext context) {
553
- return ConfirmSendingAlert(
554
- alertTitle: S.of(context).confirm_sending,
555
- amount: S.of(context).send_amount,
556
- amountValue:
557
- sendViewModel.pendingTransaction.amountFormatted,
558
- fee: S.of(context).send_fee,
559
- feeValue: sendViewModel.pendingTransaction.feeFormatted,
560
- leftButtonText: S.of(context).ok,
561
- rightButtonText: S.of(context).cancel,
562
- actionLeftButton: () {
563
- Navigator.of(context).pop();
564
- sendViewModel.commitTransaction();
565
- showDialog<void>(
566
- context: context,
567
- builder: (BuildContext context) {
568
- return Observer(builder: (_) {
569
- final state = sendViewModel.state;
570
-
571
- if (state is TransactionCommitted) {
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
- Center(
582
- child: Padding(
583
- padding: EdgeInsets.only(
584
- top: 220, left: 24, right: 24),
585
- child: Text(
586
- S.of(context).send_success,
587
- textAlign: TextAlign.center,
588
- style: TextStyle(
589
- fontSize: 22,
590
- fontWeight: FontWeight.bold,
591
- color: Theme.of(context)
592
- .primaryTextTheme
593
- .title
594
- .color,
595
- decoration: TextDecoration.none,
596
- ),
597
- ),
598
- ),
599
- ),
600
- Positioned(
601
- left: 24,
602
- right: 24,
603
- bottom: 24,
604
- child: PrimaryButton(
605
- onPressed: () =>
606
- Navigator.of(context).pop(),
607
- text: S.of(context).send_got_it,
608
- color: Colors.blue,
609
- textColor: Colors.white))
610
- ],
611
- );
612
- }
613
-
614
- return Stack(
615
- children: <Widget>[
616
- Container(
617
- color: Theme.of(context).backgroundColor,
618
- child: Center(
619
- child: Image.asset(
620
- 'assets/images/birthday_cake.png'),
621
- ),
622
- ),
623
- BackdropFilter(
624
- filter: ImageFilter.blur(
625
- sigmaX: 3.0, sigmaY: 3.0),
626
- child: Container(
627
- decoration: BoxDecoration(
628
- color: Theme.of(context)
629
- .backgroundColor
630
- .withOpacity(0.25)),
631
- child: Center(
632
- child: Padding(
633
- padding: EdgeInsets.only(top: 220),
634
- child: Text(
635
- S.of(context).send_sending,
636
- textAlign: TextAlign.center,
637
- style: TextStyle(
638
- fontSize: 22,
639
- fontWeight: FontWeight.bold,
640
- color: Theme.of(context)
641
- .primaryTextTheme
642
- .title
643
- .color,
644
- decoration: TextDecoration.none,
645
- ),
646
- ),
647
- ),
648
- ),
649
- ),
650
- )
651
- ],
652
- );
653
- });
654
- });
655
- },
656
- actionRightButton: () => Navigator.of(context).pop());
657
- });
658
- });
659
- }
660
-
661
- if (state is TransactionCommitted) {
662
- WidgetsBinding.instance.addPostFrameCallback((_) {
663
- _addressController.text = '';
664
- _cryptoAmountController.text = '';
665
- });
666
- }
667
- });
668
-
669
- _effectsInstalled = true;
670
- }
671
-
672
- Future<void> getOpenaliasRecord(BuildContext context) async {
673
- // final isOpenalias =
674
- // await sendViewModel.isOpenaliasRecord(_addressController.text);
675
-
676
- // if (isOpenalias) {
677
- // _addressController.text = sendViewModel.recordAddress;
678
-
679
- // await showDialog<void>(
680
- // context: context,
681
- // builder: (BuildContext context) {
682
- // return AlertWithOneAction(
683
- // alertTitle: S.of(context).openalias_alert_title,
684
- // alertContent: S
685
- // .of(context)
686
- // .openalias_alert_content(sendViewModel.recordName),
687
- // buttonText: S.of(context).ok,
688
- // buttonAction: () => Navigator.of(context).pop());
689
- // });
690
- // }
691
- }
692
-
693
- Future<void> _setTransactionPriority(BuildContext context) async {
694
- final items = TransactionPriority.all;
695
- final selectedItem = items.indexOf(sendViewModel.transactionPriority);
696
-
697
- await showDialog<void>(
698
- builder: (_) => Picker(
699
- items: items,
700
- selectedAtIndex: selectedItem,
701
- title: S.of(context).please_select,
702
- mainAxisAlignment: MainAxisAlignment.center,
703
- onItemSelected: (TransactionPriority priority) => null,
704
- // sendViewModel.setTransactionPriority(priority),
705
- isAlwaysShowScrollThumb: true,
706
- ),
707
- context: context);
708
- }
709
-}
lib/src/widgets/top_panel.dart
deleted
-44
@@ -1,44 +0,0 @@
1
-import 'package:flutter/material.dart';
2
-
3
-class TopPanel extends StatefulWidget {
4
- TopPanel({
5
- @required this.widget,
6
- this.edgeInsets = const EdgeInsets.all(24),
7
- this.color,
8
- this.gradient
9
- });
10
-
11
- final Color color;
12
- final Widget widget;
13
- final EdgeInsets edgeInsets;
14
- final Gradient gradient;
15
-
16
- @override
17
- TopPanelState createState() => TopPanelState(widget, edgeInsets, color, gradient);
18
-}
19
-
20
-class TopPanelState extends State<TopPanel> {
21
- TopPanelState(this._widget, this._edgeInsets, this._color, this._gradient);
22
-
23
- final Color _color;
24
- final Widget _widget;
25
- final EdgeInsets _edgeInsets;
26
- final Gradient _gradient;
27
-
28
- @override
29
- Widget build(BuildContext context) {
30
- return Container(
31
- width: double.infinity,
32
- padding: _edgeInsets,
33
- decoration: BoxDecoration(
34
- borderRadius: BorderRadius.only(
35
- bottomLeft: Radius.circular(24),
36
- bottomRight: Radius.circular(24)
37
- ),
38
- color: _color,
39
- gradient: _gradient
40
- ),
41
- child: _widget,
42
- );
43
- }
44
-}
\ No newline at end of file