diff --git a/lib/palette.dart b/lib/palette.dart index 336f7b7f9..301669a24 100644 --- a/lib/palette.dart +++ b/lib/palette.dart @@ -44,6 +44,7 @@ class Palette { static const Color dullGray = Color.fromRGBO(98, 98, 98, 1.0); static const Color protectiveBlue = Color.fromRGBO(33, 148, 255, 1.0); static const Color darkBlue = Color.fromRGBO(109, 128, 178, 1.0); + static const Color paleCornflowerBlue = Color.fromRGBO(185, 196, 237, 1.0); } class PaletteDark { diff --git a/lib/src/screens/send/send_page.dart b/lib/src/screens/send/send_page.dart index 1fd74e130..22ba76836 100644 --- a/lib/src/screens/send/send_page.dart +++ b/lib/src/screens/send/send_page.dart @@ -425,7 +425,31 @@ class SendPage extends BasePage { ], ), ), - )) + )), + if (sendViewModel.isBitcoinWallet) Padding( + padding: EdgeInsets.only(top: 6), + child: GestureDetector( + onTap: () => Navigator.of(context) + .pushNamed(Routes.unspentCoinsList), + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Coin control (optional)', + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w600, + color: Colors.white)), + Icon( + Icons.arrow_forward_ios, + size: 12, + color: Colors.white, + ) + ], + ) + ) + ) ], ), ) @@ -558,35 +582,22 @@ class SendPage extends BasePage { ), bottomSectionPadding: EdgeInsets.only(left: 24, right: 24, bottom: 24), - bottomSection: Column( - children: [ - Observer(builder: (_) { - return LoadingPrimaryButton( - onPressed: () async { - if (_formKey.currentState.validate()) { - await sendViewModel.createTransaction(); - } - }, - text: S.of(context).send, - color: Theme.of(context).accentTextTheme.body2.color, - textColor: Colors.white, - isLoading: sendViewModel.state is IsExecutingState || - sendViewModel.state is TransactionCommitting, - isDisabled: - false // FIXME !(syncStore.status is SyncedSyncStatus), - ); - }), - Padding( - padding: EdgeInsets.only(top: 12), - child: PrimaryButton( - onPressed: () => Navigator.of(context).pushNamed(Routes.unspentCoinsList), - text: 'Unspent coins', - color: Colors.green, - textColor: Colors.white, - ) - ) - ], - )), + bottomSection: Observer(builder: (_) { + return LoadingPrimaryButton( + onPressed: () async { + if (_formKey.currentState.validate()) { + await sendViewModel.createTransaction(); + } + }, + text: S.of(context).send, + color: Theme.of(context).accentTextTheme.body2.color, + textColor: Colors.white, + isLoading: sendViewModel.state is IsExecutingState || + sendViewModel.state is TransactionCommitting, + isDisabled: + false // FIXME !(syncStore.status is SyncedSyncStatus), + ); + })), )); } diff --git a/lib/src/screens/unspent_coins/unspent_coins_list_page.dart b/lib/src/screens/unspent_coins/unspent_coins_list_page.dart index cc175eb01..81dbaf104 100644 --- a/lib/src/screens/unspent_coins/unspent_coins_list_page.dart +++ b/lib/src/screens/unspent_coins/unspent_coins_list_page.dart @@ -1,10 +1,12 @@ import 'package:cake_wallet/src/screens/unspent_coins/widgets/unspent_coins_list_item.dart'; -import 'package:cake_wallet/src/widgets/standard_list.dart'; +import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; +import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cake_wallet/view_model/unspent_coins/unspent_coins_list_view_model.dart'; import 'package:flutter/material.dart'; import 'package:flutter/cupertino.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; +import 'package:cake_wallet/generated/i18n.dart'; class UnspentCoinsListPage extends BasePage { UnspentCoinsListPage({this.unspentCoinsListViewModel}); @@ -12,27 +14,59 @@ class UnspentCoinsListPage extends BasePage { @override String get title => 'Unspent coins'; + @override + Widget trailing(BuildContext context) { + final questionImage = Image.asset('assets/images/question_mark.png', + color: Theme.of(context).primaryTextTheme.title.color); + + return SizedBox( + height: 20.0, + width: 20.0, + child: ButtonTheme( + minWidth: double.minPositive, + child: FlatButton( + highlightColor: Colors.transparent, + splashColor: Colors.transparent, + padding: EdgeInsets.all(0), + onPressed: () => showPopUp<void>( + context: context, + builder: (BuildContext context) { + return AlertWithOneAction( + alertTitle: '', + alertContent: 'Information about unspent coins', + buttonText: S.of(context).ok, + buttonAction: () => Navigator.of(context).pop()); + }), + child: questionImage), + ), + ); + } + final UnspentCoinsListViewModel unspentCoinsListViewModel; @override Widget body(BuildContext context) { - return Observer(builder: (_) => SectionStandardList( - sectionCount: 1, - itemCounter: (int _) => unspentCoinsListViewModel.items.length, - itemBuilder: (_, __, index) { - final item = unspentCoinsListViewModel.items[index]; + return Container( + padding: EdgeInsets.fromLTRB(24, 12, 24, 24), + child: Observer( + builder: (_) => ListView.separated( + itemCount: unspentCoinsListViewModel.items.length, + separatorBuilder: (_, __) => + SizedBox(height: 15), + itemBuilder: (_, int index) { + final item = unspentCoinsListViewModel.items[index]; - return GestureDetector( - onTap: () {print('Item taped');}, - child: UnspentCoinsListItem( - address: item.address, - amount: item.amount, - isFrozen: item.isFrozen, - note: item.note, - isSending: item.isSending, - onCheckBoxTap: (value) {print('CheckBox taped');}, - )); - })); + return GestureDetector( + onTap: () {print('Item taped');}, + child: UnspentCoinsListItem( + address: item.address, + amount: item.amount, + isSending: item.isSending, + onCheckBoxTap: (value) {}, + )); + } + ) + ) + ); } - } \ No newline at end of file diff --git a/lib/src/screens/unspent_coins/widgets/unspent_coins_list_item.dart b/lib/src/screens/unspent_coins/widgets/unspent_coins_list_item.dart index eb8ba33c0..790e19c77 100644 --- a/lib/src/screens/unspent_coins/widgets/unspent_coins_list_item.dart +++ b/lib/src/screens/unspent_coins/widgets/unspent_coins_list_item.dart @@ -1,74 +1,101 @@ import 'package:auto_size_text/auto_size_text.dart'; +import 'package:cake_wallet/palette.dart'; import 'package:cake_wallet/src/widgets/standard_checkbox.dart'; import 'package:flutter/material.dart'; import 'package:flutter/cupertino.dart'; -class UnspentCoinsListItem extends StatelessWidget { +class UnspentCoinsListItem extends StatefulWidget { UnspentCoinsListItem({ @required this.address, @required this.amount, - @required this.isFrozen, - @required this.note, @required this.isSending, @required this.onCheckBoxTap, -}); + }); final String address; final String amount; - final bool isFrozen; - final String note; final bool isSending; final Function(bool) onCheckBoxTap; + @override UnspentCoinsListItemState createState() => + UnspentCoinsListItemState( + address: address, + amount: amount, + isSending: isSending, + onCheckBoxTap: onCheckBoxTap + ); + +} + +class UnspentCoinsListItemState extends State<UnspentCoinsListItem> { + UnspentCoinsListItemState({ + @required this.address, + @required this.amount, + @required this.isSending, + @required this.onCheckBoxTap, + }) : checkBoxValue = isSending; + + static const amountColor = Palette.darkBlueCraiola; + static const addressColor = Palette.darkGray; + static const selectedItemColor = Palette.paleCornflowerBlue; + static const unselectedItemColor = Palette.moderateLavender; + + final String address; + final String amount; + final bool isSending; + final Function(bool) onCheckBoxTap; + + bool checkBoxValue; + @override Widget build(BuildContext context) { - final textStyle = TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - color: Theme.of(context) - .primaryTextTheme - .title - .color); + final itemColor = checkBoxValue? selectedItemColor : unselectedItemColor; return Container( - padding: EdgeInsets.fromLTRB(24, 16, 24, 16), - color: Theme.of(context).backgroundColor, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + height: 62, + padding: EdgeInsets.all(12), + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(12)), + color: itemColor), + child: Row( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: CrossAxisAlignment.center, children: [ - Text( - address ?? 'Address', - style: textStyle, - ), Padding( - padding: EdgeInsets.only(top: 12), - child: Text( - amount ?? 'Amount', - style: textStyle, - ) - ), - if (isFrozen ?? false) Padding( - padding: EdgeInsets.only(top: 12), - child: Text( - 'Freeze', - style: textStyle, - ) - ), - if (note?.isNotEmpty ?? false) Padding( - padding: EdgeInsets.only(top: 12), - child: AutoSizeText( - note, - style: textStyle, - maxLines: 1 - ) - ), - Padding( - padding: EdgeInsets.only(top: 12), + padding: EdgeInsets.only(right: 12), child: StandardCheckbox( - value: isSending, - caption: 'Sending', - onChanged: onCheckBoxTap + value: checkBoxValue, + onChanged: (value) { + onCheckBoxTap(value); + checkBoxValue = value; + setState(() {}); + } ) + ), + Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + AutoSizeText( + amount ?? 'Amount', + style: TextStyle( + color: amountColor, + fontSize: 16, + fontWeight: FontWeight.w600 + ), + maxLines: 1, + ), + AutoSizeText( + address ?? 'Address', + style: TextStyle( + color: addressColor, + fontSize: 12, + ), + maxLines: 1, + ) + ] + ) ) ], ) diff --git a/lib/src/widgets/standard_checkbox.dart b/lib/src/widgets/standard_checkbox.dart index 64ae95acc..9deec340b 100644 --- a/lib/src/widgets/standard_checkbox.dart +++ b/lib/src/widgets/standard_checkbox.dart @@ -44,9 +44,6 @@ class StandardCheckboxState extends State<StandardCheckbox> { Container( height: 24.0, width: 24.0, - margin: EdgeInsets.only( - right: 10.0, - ), decoration: BoxDecoration( border: Border.all( color: Theme.of(context) @@ -65,14 +62,17 @@ class StandardCheckboxState extends State<StandardCheckbox> { ) : Offstage(), ), - Text( - caption, - style: TextStyle( - fontSize: 16.0, - color: Theme.of(context) - .primaryTextTheme - .title - .color), + if (caption.isNotEmpty) Padding( + padding: EdgeInsets.only(left: 10), + child: Text( + caption, + style: TextStyle( + fontSize: 16.0, + color: Theme.of(context) + .primaryTextTheme + .title + .color), + ) ) ], ), diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart index 689032223..a9e6aaf93 100644 --- a/lib/view_model/send/send_view_model.dart +++ b/lib/view_model/send/send_view_model.dart @@ -55,6 +55,8 @@ abstract class SendViewModelBase with Store { _settingsStore.priority[_wallet.type] = priorities.first; } + isBitcoinWallet = _wallet is BitcoinWallet; + _setCryptoNumMaximumFractionDigits(); } @@ -182,6 +184,9 @@ abstract class SendViewModelBase with Store { @observable PendingTransaction pendingTransaction; + @observable + bool isBitcoinWallet; + @computed String get balance => _wallet.balance.formattedAvailableBalance ?? '0.0'; diff --git a/lib/view_model/unspent_coins/unspent_coins_list_view_model.dart b/lib/view_model/unspent_coins/unspent_coins_list_view_model.dart index 5f631e52a..25167f785 100644 --- a/lib/view_model/unspent_coins/unspent_coins_list_view_model.dart +++ b/lib/view_model/unspent_coins/unspent_coins_list_view_model.dart @@ -5,32 +5,45 @@ part 'unspent_coins_list_view_model.g.dart'; const List<Map<String, dynamic>> unspentCoinsMap = [ <String, dynamic>{ - "address" : "11111111111111121111132432432432432432432443124324324234324324324324332424", - "amount" : "222", + "address" : "bc1qm80mu5p3mf04a7cj7teymasf04dwpc3av2fwtr", + "amount" : "0.00358 BTC", "isFrozen" : true, "note" : "333cvgf23132132132132131321321314rwrtdggfdddewq ewqasfdxgdhgfgfszczcxgbhhhbcgbc"}, <String, dynamic>{ - "address" : "444", - "amount" : "555", + "address" : "bc1qm80mu5p3mf04a7cj7teymasf04dwpc3av2fwtr", + "amount" : "0.00567894 BTC", "note" : "sfjskf"}, <String, dynamic>{ - "address" : "777", - "amount" : "888", + "address" : "bc1qm80mu5p3mf04a7cj7teymasf04dwpc3av2fwtr", + "amount" : "0.00087 BTC", "isFrozen" : false}, <String, dynamic>{ - "address" : "11111111111111121111132432432432432432432443124324324234324324324324332424", - "amount" : "222", + "address" : "bc1qm80mu5p3mf04a7cj7teymasf04dwpc3av2fwtr", + "amount" : "0.00012 BTC", "isFrozen" : true, "note" : "333cvgf23132132132132131321321314rwrtdggfdddewq ewqasfdxgdhgfgfszczcxgbhhhbcgbc"}, <String, dynamic>{ - "address" : "444", - "amount" : "555", + "address" : "bc1qm80mu5p3mf04a7cj7teymasf04dwpc3av2fwtr", + "amount" : "0.00574 BTC", "note" : "sffsfsdsgs"}, <String, dynamic>{ - "address" : "777", - "amount" : "888", + "address" : "bc1qm80mu5p3mf04a7cj7teymasf04dwpc3av2fwtr", + "amount" : "0.000482 BTC", "isFrozen" : false}, <String, dynamic>{}, + <String, dynamic>{ + "address" : "bc1qm80mu5p3mf04a7cj7teymasf04dwpc3av2fwtr", + "amount" : "0.00012 BTC", + "isFrozen" : true, + "note" : "333cvgf23132132132132131321321314rwrtdggfdddewq ewqasfdxgdhgfgfszczcxgbhhhbcgbc"}, + <String, dynamic>{ + "address" : "bc1qm80mu5p3mf04a7cj7teymasf04dwpc3av2fwtr", + "amount" : "0.00574 BTC", + "note" : "sffsfsdsgs"}, + <String, dynamic>{ + "address" : "bc1qm80mu5p3mf04a7cj7teymasf04dwpc3av2fwtr", + "amount" : "0.000482 BTC", + "isFrozen" : false}, ]; class UnspentCoinsListViewModel = UnspentCoinsListViewModelBase with _$UnspentCoinsListViewModel;