Merge redesign part 2.

M committed Sep 2, 2020 at 11:47 UTC 9074bee6db574c12b241617fe95c928f88c8b7f9
6 files changed +570 -440
lib/src/screens/send/send_page.dart
+17 -7
@@ -95,16 +95,26 @@ class SendPage extends BasePage {
95 // }
96 }
97
98 - @override
99 - Widget body(BuildContext context) {
100 - return super.build(context);
101 - }
102 -
98 // @override
104 - // Widget build(BuildContext context) {
105 - // return BaseSendWidget(sendViewModel: sendViewModel);
99 + // Widget body(BuildContext context) {
100 + // return super.build(context);
101 // }
102
103 + @override
104 + Widget body(BuildContext context) => BaseSendWidget(
105 + sendViewModel: sendViewModel,
106 + leading: leading(context),
107 + middle: middle(context),
108 + );
109 +
110 + @override
111 + Widget build(BuildContext context) {
112 + return Scaffold(
113 + resizeToAvoidBottomPadding: resizeToAvoidBottomPadding,
114 + body: Container(
115 + color: Theme.of(context).backgroundColor, child: body(context)));
116 + }
117 +
118 // @override
119 // Widget build(BuildContext context) {
120 // _setEffects(context);
lib/src/screens/send/send_template_page.dart
+10 -15
@@ -2,7 +2,7 @@ import 'package:flutter/cupertino.dart';
2 import 'package:flutter/material.dart';
3 import 'package:cake_wallet/src/screens/base_page.dart';
4 import 'package:cake_wallet/generated/i18n.dart';
5 -import 'package:cake_wallet/view_model/send_view_model.dart';
5 +import 'package:cake_wallet/view_model/send/send_view_model.dart';
6 import 'package:cake_wallet/src/screens/send/widgets/base_send_widget.dart';
7
8 class SendTemplatePage extends BasePage {
@@ -26,22 +26,17 @@ class SendTemplatePage extends BasePage {
26 bool get resizeToAvoidBottomPadding => false;
27
28 @override
29 - Widget body(BuildContext context) =>
30 - BaseSendWidget(
31 - sendViewModel: sendViewModel,
32 - leading: leading(context),
33 - middle: middle(context),
34 - isTemplate: true
35 - );
29 + Widget body(BuildContext context) => BaseSendWidget(
30 + sendViewModel: sendViewModel,
31 + leading: leading(context),
32 + middle: middle(context),
33 + isTemplate: true);
34
35 @override
36 Widget build(BuildContext context) {
37 return Scaffold(
40 - resizeToAvoidBottomPadding: resizeToAvoidBottomPadding,
41 - body: Container(
42 - color: Theme.of(context).backgroundColor,
43 - child: body(context)
44 - )
45 - );
38 + resizeToAvoidBottomPadding: resizeToAvoidBottomPadding,
39 + body: Container(
40 + color: Theme.of(context).backgroundColor, child: body(context)));
41 }
47 -}
\ No newline at end of file
42 +}
lib/src/screens/send/widgets/base_send_widget.dart
+485 -384
@@ -1,10 +1,12 @@
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';
7 -import 'package:cake_wallet/view_model/send_view_model.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';
@@ -22,12 +24,11 @@ import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
24 import 'package:cake_wallet/routes.dart';
25
26 class BaseSendWidget extends StatelessWidget {
25 - BaseSendWidget({
26 - @required this.sendViewModel,
27 - @required this.leading,
28 - @required this.middle,
29 - this.isTemplate = false
30 - });
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;
@@ -45,7 +46,6 @@ class BaseSendWidget extends StatelessWidget {
46
47 @override
48 Widget build(BuildContext context) {
48 -
49 _setEffects(context);
50
51 return ScrollableWithBottomSection(
@@ -57,9 +57,7 @@ class BaseSendWidget extends StatelessWidget {
57 gradient: LinearGradient(colors: [
58 Theme.of(context).primaryTextTheme.subhead.color,
59 Theme.of(context).primaryTextTheme.subhead.decorationColor,
60 - ],
61 - begin: Alignment.topLeft,
62 - end: Alignment.bottomRight),
60 + ], begin: Alignment.topLeft, end: Alignment.bottomRight),
61 widget: Form(
62 key: _formKey,
63 child: Column(children: <Widget>[
@@ -74,28 +72,34 @@ class BaseSendWidget extends StatelessWidget {
72 child: Column(
73 children: <Widget>[
74 isTemplate
77 - ? BaseTextFormField(
78 - controller: _nameController,
79 - hintText: S.of(context).send_name,
80 - borderColor: Theme.of(context).primaryTextTheme.headline.color,
81 - textStyle: TextStyle(
82 - fontSize: 14,
83 - fontWeight: FontWeight.w500,
84 - color: Colors.white
85 - ),
86 - placeholderTextStyle: TextStyle(
87 - color: Theme.of(context).primaryTextTheme.headline.decorationColor,
88 - fontWeight: FontWeight.w500,
89 - fontSize: 14),
90 - validator: sendViewModel.templateValidator,
91 - )
92 - : Offstage(),
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,
97 - placeholder: S.of(context).send_address(
98 - sendViewModel.cryptoCurrencyTitle),
100 + // placeholder: S
101 + // .of(context)
102 + // .send_address(sendViewModel.cryptoCurrencyTitle),
103 focusNode: _focusNode,
104 onURIScanned: (uri) {
105 var address = '';
@@ -116,113 +120,127 @@ class BaseSendWidget extends StatelessWidget {
120 AddressTextFieldOption.qrCode,
121 AddressTextFieldOption.addressBook
122 ],
119 - buttonColor: Theme.of(context).primaryTextTheme.display1.color,
120 - borderColor: Theme.of(context).primaryTextTheme.headline.color,
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,
124 - color: Colors.white
125 - ),
130 + color: Colors.white),
131 hintStyle: TextStyle(
132 fontSize: 14,
133 fontWeight: FontWeight.w500,
129 - color: Theme.of(context).primaryTextTheme.headline.decorationColor
130 - ),
134 + color: Theme.of(context)
135 + .primaryTextTheme
136 + .headline
137 + .decorationColor),
138 validator: sendViewModel.addressValidator,
139 ),
140 ),
134 - Observer(
135 - builder: (_) {
136 - return Padding(
137 - padding: const EdgeInsets.only(top: 20),
138 - child: BaseTextFormField(
139 - controller: _cryptoAmountController,
140 - keyboardType: TextInputType.numberWithOptions(
141 - signed: false, decimal: true),
142 - inputFormatters: [
143 - BlacklistingTextInputFormatter(
144 - RegExp('[\\-|\\ |\\,]'))
145 - ],
146 - prefixIcon: Padding(
147 - padding: EdgeInsets.only(top: 9),
148 - child: Text(sendViewModel.currency.title + ':',
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 )),
154 - ),
155 - suffixIcon: isTemplate
161 + ),
162 + suffixIcon: isTemplate
163 ? Offstage()
164 : Container(
158 - height: 32,
159 - width: 32,
160 - margin: EdgeInsets.only(left: 14, top: 4, bottom: 10),
161 - decoration: BoxDecoration(
162 - color: Theme.of(context).primaryTextTheme.display1.color,
163 - borderRadius: BorderRadius.all(Radius.circular(6))
164 - ),
165 - child: InkWell(
166 - onTap: () => sendViewModel.setSendAll(),
167 - child: Center(
168 - child: Text(S.of(context).all,
169 - textAlign: TextAlign.center,
170 - style: TextStyle(
171 - fontSize: 12,
172 - fontWeight: FontWeight.bold,
173 - color: Theme.of(context).primaryTextTheme.display1.decorationColor
174 - )
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 ),
178 - ),
179 - hintText: '0.0000',
180 - borderColor: Theme.of(context).primaryTextTheme.headline.color,
181 - textStyle: TextStyle(
182 - fontSize: 14,
183 - fontWeight: FontWeight.w500,
184 - color: Colors.white
185 - ),
186 - placeholderTextStyle: TextStyle(
187 - color: Theme.of(context).primaryTextTheme.headline.decorationColor,
188 - fontWeight: FontWeight.w500,
189 - fontSize: 14),
190 - validator: sendViewModel.amountValidator
191 - )
192 - );
193 - }
194 - ),
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
196 - ? Offstage()
197 - : Observer(
198 - builder: (_) => Padding(
199 - padding: EdgeInsets.only(top: 10),
200 - child: Row(
201 - mainAxisSize: MainAxisSize.max,
202 - mainAxisAlignment: MainAxisAlignment.spaceBetween,
203 - children: <Widget>[
204 - Expanded(
205 - child: Text(
206 - S.of(context).available_balance + ':',
207 - style: TextStyle(
208 - fontSize: 12,
209 - fontWeight: FontWeight.w600,
210 - color: Theme.of(context).primaryTextTheme.headline.decorationColor
211 - ),
212 - )
213 - ),
214 - Text(
215 - sendViewModel.balance,
216 - style: TextStyle(
217 - fontSize: 12,
218 - fontWeight: FontWeight.w600,
219 - color: Theme.of(context).primaryTextTheme.headline.decorationColor
220 - ),
221 - )
222 - ],
223 - ),
224 - )
225 - ),
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(
@@ -235,8 +253,7 @@ class BaseSendWidget extends StatelessWidget {
253 ],
254 prefixIcon: Padding(
255 padding: EdgeInsets.only(top: 9),
238 - child: Text(
239 - sendViewModel.fiat.title + ':',
256 + child: Text(sendViewModel.fiat.title + ':',
257 style: TextStyle(
258 fontSize: 16,
259 fontWeight: FontWeight.w600,
@@ -244,62 +261,71 @@ class BaseSendWidget extends StatelessWidget {
261 )),
262 ),
263 hintText: '0.00',
247 - borderColor: Theme.of(context).primaryTextTheme.headline.color,
264 + borderColor: Theme.of(context)
265 + .primaryTextTheme
266 + .headline
267 + .color,
268 textStyle: TextStyle(
269 fontSize: 14,
270 fontWeight: FontWeight.w500,
251 - color: Colors.white
252 - ),
271 + color: Colors.white),
272 placeholderTextStyle: TextStyle(
254 - color: Theme.of(context).primaryTextTheme.headline.decorationColor,
273 + color: Theme.of(context)
274 + .primaryTextTheme
275 + .headline
276 + .decorationColor,
277 fontWeight: FontWeight.w500,
278 fontSize: 14),
257 - )
258 - ),
279 + )),
280 isTemplate
260 - ? Offstage()
261 - : Observer(
262 - builder: (_) => GestureDetector(
263 - onTap: () => _setTransactionPriority(context),
264 - child: Container(
265 - padding: EdgeInsets.only(top: 24),
266 - child: Row(
267 - mainAxisAlignment: 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 - )),
276 - Container(
277 - child: Row(
278 - children: <Widget>[
279 - Text(
280 - sendViewModel.estimatedFee.toString() + ' '
281 - + sendViewModel.currency.title,
282 - style: TextStyle(
283 - fontSize: 12,
284 - fontWeight: FontWeight.w600,
285 - //color: Theme.of(context).primaryTextTheme.display2.color,
286 - color: Colors.white
287 - )),
288 - Padding(
289 - padding: EdgeInsets.only(left: 5),
290 - child: Icon(
291 - Icons.arrow_forward_ios,
292 - size: 12,
293 - color: Colors.white,),
294 - )
295 - ],
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 ),
297 - )
298 - ],
299 - ),
300 - ),
301 - )
302 - )
328 + ))
329 ],
330 ),
331 )
@@ -307,156 +333,158 @@ class BaseSendWidget extends StatelessWidget {
333 ),
334 ),
335 isTemplate
310 - ? Offstage()
311 - : Padding(
312 - padding: EdgeInsets.only(
313 - top: 30,
314 - left: 24,
315 - bottom: 24
316 - ),
317 - child: Row(
318 - mainAxisAlignment: MainAxisAlignment.start,
319 - children: <Widget>[
320 - Text(
321 - S.of(context).send_templates,
322 - style: TextStyle(
323 - fontSize: 18,
324 - fontWeight: FontWeight.w600,
325 - color: Theme.of(context).primaryTextTheme.display4.color
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 ),
327 - )
328 - ],
329 - ),
330 - ),
354 + ),
355 isTemplate
332 - ? Offstage()
333 - : Container(
334 - height: 40,
335 - width: double.infinity,
336 - padding: EdgeInsets.only(left: 24),
337 - child: SingleChildScrollView(
338 - scrollDirection: Axis.horizontal,
339 - child: Row(
340 - children: <Widget>[
341 - GestureDetector(
342 - onTap: () => Navigator.of(context)
343 - .pushNamed(Routes.sendTemplate),
344 - child: Container(
345 - padding: EdgeInsets.only(left: 1, right: 10),
346 - child: DottedBorder(
347 - borderType: BorderType.RRect,
348 - dashPattern: [6, 4],
349 - color: Theme.of(context).primaryTextTheme.display2.decorationColor,
350 - strokeWidth: 2,
351 - radius: Radius.circular(20),
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(
353 - height: 34,
354 - width: 75,
355 - padding: EdgeInsets.only(left: 10, right: 10),
356 - alignment: Alignment.center,
357 - decoration: BoxDecoration(
358 - borderRadius: BorderRadius.all(Radius.circular(20)),
359 - color: Colors.transparent,
360 - ),
361 - child: Text(
362 - S.of(context).send_new,
363 - style: TextStyle(
364 - fontSize: 14,
365 - fontWeight: FontWeight.w600,
366 - color: Theme.of(context).primaryTextTheme.display3.color
367 - ),
368 - ),
369 - )
370 - ),
371 - ),
372 - ),
373 - Observer(
374 - builder: (_) {
375 - final templates = sendViewModel.templates;
376 - final itemCount = templates.length;
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
378 - return ListView.builder(
379 - scrollDirection: Axis.horizontal,
380 - shrinkWrap: true,
381 - physics: NeverScrollableScrollPhysics(),
382 - itemCount: itemCount,
383 - itemBuilder: (context, index) {
384 - final template = templates[index];
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
386 - return TemplateTile(
387 - key: UniqueKey(),
388 - to: template.name,
389 - amount: template.amount,
390 - from: template.cryptoCurrency,
391 - onTap: () {
392 - _addressController.text = template.address;
393 - _cryptoAmountController.text = template.amount;
394 - getOpenaliasRecord(context);
395 - },
396 - onRemove: () {
397 - showDialog<void>(
398 - context: context,
399 - builder: (dialogContext) {
400 - return AlertWithTwoActions(
401 - alertTitle: S.of(context).template,
402 - alertContent: S.of(context).confirm_delete_template,
403 - leftButtonText: S.of(context).delete,
404 - rightButtonText: S.of(context).cancel,
405 - actionLeftButton: () {
406 - Navigator.of(dialogContext).pop();
407 - sendViewModel.sendTemplateStore.remove(template: template);
408 - sendViewModel.sendTemplateStore.update();
409 - },
410 - actionRightButton: () => Navigator.of(dialogContext).pop()
411 - );
412 - }
413 - );
414 - },
415 - );
416 - }
417 - );
418 - }
419 - )
420 - ],
421 - ),
422 - ),
423 - )
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(
429 - onPressed: () {
430 - if (_formKey.currentState.validate()) {
431 - sendViewModel.sendTemplateStore.addTemplate(
432 - name: _nameController.text,
433 - address: _addressController.text,
434 - cryptoCurrency: sendViewModel.currency.title,
435 - amount: _cryptoAmountController.text
436 - );
437 - sendViewModel.sendTemplateStore.update();
438 - Navigator.of(context).pop();
439 - }
440 - },
441 - text: S.of(context).save,
442 - color: Colors.green,
443 - textColor: Colors.white)
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: (_) {
445 - return LoadingPrimaryButton(
446 - onPressed: () {
447 - if (_formKey.currentState.validate()) {
448 - print('SENT!!!');
449 - }
450 - },
451 - text: S.of(context).send,
452 - color: Palette.blueCraiola,
453 - textColor: Colors.white,
454 - isLoading: sendViewModel.state is TransactionIsCreating ||
455 - sendViewModel.state is TransactionCommitting,
456 - isDisabled:
457 - false // FIXME !(syncStore.status is SyncedSyncStatus),
458 - );
459 - }),
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
@@ -465,6 +493,13 @@ class BaseSendWidget extends StatelessWidget {
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;
@@ -472,6 +507,10 @@ class BaseSendWidget extends StatelessWidget {
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 }
@@ -487,29 +526,7 @@ class BaseSendWidget extends StatelessWidget {
526 final address = _addressController.text;
527
528 if (sendViewModel.address != address) {
490 - sendViewModel.changeAddress(address);
491 - }
492 - });
493 -
494 - _fiatAmountController.addListener(() {
495 - final fiatAmount = _fiatAmountController.text;
496 -
497 - if (sendViewModel.fiatAmount != fiatAmount) {
498 - sendViewModel.changeFiatAmount(fiatAmount);
499 - }
500 - });
501 -
502 - _cryptoAmountController.addListener(() {
503 - final cryptoAmount = _cryptoAmountController.text;
504 -
505 - if (sendViewModel.cryptoAmount != cryptoAmount) {
506 - sendViewModel.changeCryptoAmount(cryptoAmount);
507 - }
508 - });
509 -
510 - _focusNode.addListener(() {
511 - if (!_focusNode.hasFocus && _addressController.text.isNotEmpty) {
512 - getOpenaliasRecord(context);
529 + sendViewModel.address = address;
530 }
531 });
532
@@ -519,44 +536,126 @@ class BaseSendWidget extends StatelessWidget {
536 showDialog<void>(
537 context: context,
538 builder: (BuildContext context) {
522 - return AlertDialog(
523 - title: Text(S.of(context).error),
524 - content: Text(state.error),
525 - actions: <Widget>[
526 - FlatButton(
527 - child: Text(S.of(context).ok),
528 - onPressed: () => Navigator.of(context).pop())
529 - ],
530 - );
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) {
536 -// WidgetsBinding.instance.addPostFrameCallback((_) {
537 -// showDialog<void>(
538 -// context: context,
539 -// builder: (BuildContext context) {
540 -// return ConfirmSendingAlert(
541 -// alertTitle: S.of(context).confirm_sending,
542 -// amount: S.of(context).send_amount,
543 -// amountValue: sendStore.pendingTransaction.amount,
544 -// fee: S.of(context).send_fee,
545 -// feeValue: sendStore.pendingTransaction.fee,
546 -// leftButtonText: S.of(context).ok,
547 -// rightButtonText: S.of(context).cancel,
548 -// actionLeftButton: () {
549 -// Navigator.of(context).pop();
550 -// sendStore.commitTransaction();
551 -// showDialog<void>(
552 -// context: context,
553 -// builder: (BuildContext context) {
554 -// return SendingAlert(sendStore: sendStore);
555 -// });
556 -// },
557 -// actionRightButton: () => Navigator.of(context).pop());
558 -// });
559 -// });
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) {
@@ -571,22 +670,24 @@ class BaseSendWidget extends StatelessWidget {
670 }
671
672 Future<void> getOpenaliasRecord(BuildContext context) async {
574 - final isOpenalias = await sendViewModel.isOpenaliasRecord(_addressController.text);
673 + // final isOpenalias =
674 + // await sendViewModel.isOpenaliasRecord(_addressController.text);
675
576 - if (isOpenalias) {
577 - _addressController.text = sendViewModel.recordAddress;
676 + // if (isOpenalias) {
677 + // _addressController.text = sendViewModel.recordAddress;
678
579 - await showDialog<void>(
580 - context: context,
581 - builder: (BuildContext context) {
582 - return AlertWithOneAction(
583 - alertTitle: S.of(context).openalias_alert_title,
584 - alertContent: S.of(context).openalias_alert_content(sendViewModel.recordName),
585 - buttonText: S.of(context).ok,
586 - buttonAction: () => Navigator.of(context).pop()
587 - );
588 - });
589 - }
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 {
@@ -595,14 +696,14 @@ class BaseSendWidget extends StatelessWidget {
696
697 await showDialog<void>(
698 builder: (_) => Picker(
598 - items: items,
599 - selectedAtIndex: selectedItem,
600 - title: S.of(context).please_select,
601 - mainAxisAlignment: MainAxisAlignment.center,
602 - onItemSelected: (TransactionPriority priority) =>
603 - sendViewModel.setTransactionPriority(priority),
604 - isAlwaysShowScrollThumb: true,
605 - ),
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 }
608 -}
\ No newline at end of file
709 +}
lib/store/settings_store.dart
+1 -1
@@ -138,7 +138,7 @@ abstract class SettingsStoreBase with Store {
138 sharedPreferences.getBool(shouldSaveRecipientAddressKey);
139 final allowBiometricalAuthentication =
140 sharedPreferences.getBool(allowBiometricalAuthenticationKey) ?? false;
141 - final savedDarkTheme = sharedPreferences.getBool(currentDarkTheme) ?? true;
141 + final savedDarkTheme = sharedPreferences.getBool(currentDarkTheme) ?? false;
142 final actionListDisplayMode = ObservableList<ActionListDisplayMode>();
143 actionListDisplayMode.addAll(deserializeActionlistDisplayModes(
144 sharedPreferences.getInt(displayActionListModeKey) ??
lib/view_model/exchange/exchange_view_model.dart
+47 -26
@@ -1,5 +1,6 @@
1 import 'package:cake_wallet/core/wallet_base.dart';
2 import 'package:cake_wallet/src/domain/common/crypto_currency.dart';
3 +import 'package:cake_wallet/src/domain/common/wallet_type.dart';
4 import 'package:cake_wallet/src/domain/exchange/exchange_provider.dart';
5 import 'package:cake_wallet/src/domain/exchange/limits.dart';
6 import 'package:cake_wallet/src/domain/exchange/trade.dart';
@@ -25,22 +26,18 @@ part 'exchange_view_model.g.dart';
26 class ExchangeViewModel = ExchangeViewModelBase with _$ExchangeViewModel;
27
28 abstract class ExchangeViewModelBase with Store {
28 - ExchangeViewModelBase({
29 - this.wallet,
30 - this.trades,
31 - this.exchangeTemplateStore,
32 - this.tradesStore}) {
33 -
29 + ExchangeViewModelBase(
30 + {this.wallet,
31 + this.trades,
32 + this.exchangeTemplateStore,
33 + this.tradesStore}) {
34 providerList = [
35 XMRTOExchangeProvider(),
36 ChangeNowExchangeProvider(),
37 MorphTokenExchangeProvider(trades: trades)
38 ];
39
40 - provider = providerList[ 0 ];
41 -
42 - depositCurrency = CryptoCurrency.xmr;
43 - receiveCurrency = CryptoCurrency.btc;
40 + _initialPairBasedOnWallet();
41 isDepositAddressEnabled = !(depositCurrency == wallet.currency);
42 isReceiveAddressEnabled = !(receiveCurrency == wallet.currency);
43 depositAmount = '';
@@ -50,6 +47,7 @@ abstract class ExchangeViewModelBase with Store {
47 limitsState = LimitsInitialState();
48 tradeState = ExchangeTradeStateInitial();
49 _cryptoNumberFormat = NumberFormat()..maximumFractionDigits = 12;
50 + provider = providersForCurrentPair().first;
51 loadLimits();
52 }
53
@@ -140,8 +138,11 @@ abstract class ExchangeViewModelBase with Store {
138
139 provider
140 .calculateAmount(
143 - from: depositCurrency, to: receiveCurrency, amount: _amount)
144 - .then((amount) => _cryptoNumberFormat.format(amount).toString().replaceAll(RegExp("\\,"), ""))
141 + from: depositCurrency, to: receiveCurrency, amount: _amount)
142 + .then((amount) => _cryptoNumberFormat
143 + .format(amount)
144 + .toString()
145 + .replaceAll(RegExp('\\,'), ''))
146 .then((amount) => depositAmount = amount);
147 }
148
@@ -158,8 +159,11 @@ abstract class ExchangeViewModelBase with Store {
159 final _amount = double.parse(amount);
160 provider
161 .calculateAmount(
161 - from: depositCurrency, to: receiveCurrency, amount: _amount)
162 - .then((amount) => _cryptoNumberFormat.format(amount).toString().replaceAll(RegExp("\\,"), ""))
162 + from: depositCurrency, to: receiveCurrency, amount: _amount)
163 + .then((amount) => _cryptoNumberFormat
164 + .format(amount)
165 + .toString()
166 + .replaceAll(RegExp('\\,'), ''))
167 .then((amount) => receiveAmount = amount);
168 }
169
@@ -217,11 +221,13 @@ abstract class ExchangeViewModelBase with Store {
221
222 if (limitsState is LimitsLoadedSuccessfully && amount != null) {
223 if (double.parse(amount) < limits.min) {
220 - tradeState = TradeIsCreatedFailure(error: S.current.error_text_minimal_limit('${provider.description}',
221 - '${limits.min}', currency.toString()));
224 + tradeState = TradeIsCreatedFailure(
225 + error: S.current.error_text_minimal_limit('${provider.description}',
226 + '${limits.min}', currency.toString()));
227 } else if (limits.max != null && double.parse(amount) > limits.max) {
223 - tradeState = TradeIsCreatedFailure(error: S.current.error_text_maximum_limit('${provider.description}',
224 - '${limits.max}', currency.toString()));
228 + tradeState = TradeIsCreatedFailure(
229 + error: S.current.error_text_maximum_limit('${provider.description}',
230 + '${limits.max}', currency.toString()));
231 } else {
232 try {
233 tradeState = TradeIsCreating();
@@ -235,9 +241,10 @@ abstract class ExchangeViewModelBase with Store {
241 }
242 }
243 } else {
238 - tradeState = TradeIsCreatedFailure(error: S.current.error_text_limits_loading_failed('${provider.description}'));
244 + tradeState = TradeIsCreatedFailure(
245 + error: S.current
246 + .error_text_limits_loading_failed('${provider.description}'));
247 }
240 -
248 }
249
250 @action
@@ -261,9 +268,9 @@ abstract class ExchangeViewModelBase with Store {
268 {CryptoCurrency from, CryptoCurrency to}) {
269 final providers = providerList
270 .where((provider) => provider.pairList
264 - .where((pair) =>
265 - pair.from == depositCurrency && pair.to == receiveCurrency)
266 - .isNotEmpty)
271 + .where((pair) =>
272 + pair.from == depositCurrency && pair.to == receiveCurrency)
273 + .isNotEmpty)
274 .toList();
275
276 return providers;
@@ -272,12 +279,12 @@ abstract class ExchangeViewModelBase with Store {
279 void _onPairChange() {
280 final isPairExist = provider.pairList
281 .where((pair) =>
275 - pair.from == depositCurrency && pair.to == receiveCurrency)
282 + pair.from == depositCurrency && pair.to == receiveCurrency)
283 .isNotEmpty;
284
285 if (!isPairExist) {
286 final provider =
280 - _providerForPair(from: depositCurrency, to: receiveCurrency);
287 + _providerForPair(from: depositCurrency, to: receiveCurrency);
288
289 if (provider != null) {
290 changeProvider(provider: provider);
@@ -295,4 +302,18 @@ abstract class ExchangeViewModelBase with Store {
302 return providers.isNotEmpty ? providers[0] : null;
303 }
304
298 -}
\ No newline at end of file
305 + void _initialPairBasedOnWallet() {
306 + switch (wallet.type) {
307 + case WalletType.monero:
308 + depositCurrency = CryptoCurrency.xmr;
309 + receiveCurrency = CryptoCurrency.btc;
310 + break;
311 + case WalletType.bitcoin:
312 + depositCurrency = CryptoCurrency.btc;
313 + receiveCurrency = CryptoCurrency.xmr;
314 + break;
315 + default:
316 + break;
317 + }
318 + }
319 +}
lib/view_model/send/send_view_model.dart
+10 -7
@@ -1,7 +1,8 @@
1 -import 'package:cake_wallet/src/domain/common/calculate_fiat_amount.dart';
2 -import 'package:cake_wallet/store/dashboard/fiat_convertation_store.dart';
1 import 'package:intl/intl.dart';
2 import 'package:mobx/mobx.dart';
3 +import 'package:cake_wallet/core/template_validator.dart';
4 +import 'package:cake_wallet/src/domain/common/calculate_fiat_amount.dart';
5 +import 'package:cake_wallet/store/dashboard/fiat_convertation_store.dart';
6 import 'package:cake_wallet/core/address_validator.dart';
7 import 'package:cake_wallet/core/amount_validator.dart';
8 import 'package:cake_wallet/core/pending_transaction.dart';
@@ -28,7 +29,7 @@ abstract class SendViewModelBase with Store {
29 : state = InitialSendViewModelState(),
30 _cryptoNumberFormat = NumberFormat()..maximumFractionDigits = 12,
31 // FIXME: need to be based on wallet type.
31 - all = false;
32 + sendAll = false;
33
34 @observable
35 SendViewModelState state;
@@ -43,7 +44,7 @@ abstract class SendViewModelBase with Store {
44 String address;
45
46 @observable
46 - bool all;
47 + bool sendAll;
48
49 FiatCurrency get fiat => _settingsStore.fiatCurrency;
50
@@ -59,6 +60,8 @@ abstract class SendViewModelBase with Store {
60
61 Validator get addressValidator => AddressValidator(type: _wallet.currency);
62
63 + Validator get templateValidator => TemplateValidator();
64 +
65 PendingTransaction pendingTransaction;
66
67 @computed
@@ -83,7 +86,7 @@ abstract class SendViewModelBase with Store {
86 final NumberFormat _cryptoNumberFormat;
87
88 @action
86 - void setAll() => all = true;
89 + void setSendAll() => sendAll = true;
90
91 @action
92 void reset() {
@@ -118,7 +121,7 @@ abstract class SendViewModelBase with Store {
121 void setCryptoAmount(String amount) {
122 // FIXME: hardcoded value.
123 if (amount.toUpperCase() != 'ALL') {
121 - all = false;
124 + sendAll = false;
125 }
126
127 cryptoAmount = amount;
@@ -162,7 +165,7 @@ abstract class SendViewModelBase with Store {
165
166 Object _credentials() {
167 final amount =
165 - !all ? double.parse(cryptoAmount.replaceAll(',', '.')) : null;
168 + !sendAll ? double.parse(cryptoAmount.replaceAll(',', '.')) : null;
169
170 switch (_wallet.type) {
171 case WalletType.bitcoin: