From b1add664ad5b762618190c3ad8e9e5f4c24600bf Mon Sep 17 00:00:00 2001
From: OleksandrSobol <dr.alexander.sobol@gmail.com>
Date: Mon, 31 May 2021 21:04:00 +0300
Subject: [PATCH] CAKE-329 | reworked unspent_coins_list_page.dart and
 unspent_coins_list_item.dart; fixed standard_checkbox.dart; applied unspent
 coins control only to btc wallet

---
 lib/palette.dart                              |   1 +
 lib/src/screens/send/send_page.dart           |  71 +++++-----
 .../unspent_coins_list_page.dart              |  70 +++++++---
 .../widgets/unspent_coins_list_item.dart      | 121 +++++++++++-------
 lib/src/widgets/standard_checkbox.dart        |  22 ++--
 lib/view_model/send/send_view_model.dart      |   5 +
 .../unspent_coins_list_view_model.dart        |  37 ++++--
 7 files changed, 209 insertions(+), 118 deletions(-)

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;